2012년 3월 13일 화요일

Java에서 signal 처리 - JNI -

출처 : http://www.javaservice.net/~java/bbs/read.cgi?m=devtip&b=javatip&c=r_p&n=978538886

Java에서 signal 처리 - JNI -



signal 핸들링은 (제 생각엔) Java 에선 뜨거운 감자 같습니다. 왜냐면, signal
핸들링은 OS 마다 다른데, 어떤 OS에서든 동작해야 하는 Java 입장에선 일반화된
Java API를 제공하기엔 바람직하지 않은 듯 합니다.

예를 들어 kill 명령어는 Unix 에서는 일반적이지만, Windows 에선 (제가 알기로는)
kill 명령어가 없듯이 (즉, signal 를 해당 process 에게 줄수 있는 방법이 없듯이)
java 에서 signal 핸들링은 결국 OS 종속적인 JNI 를 이용해 필요할 때 알아서
사용토록하고, Java 는 관여치 않는 듯 합니다.

C 에서 signal 핸들링을 해 보셨고, 또, Java 의 JNI 를 해 보셨다면, 저처럼
어렵지 않게 다음과 같은 테스트를 해 볼 수 있을 겁니다.


첫번째 예제는 실행된 Java 프로그램에서 가능한 모든 종류의 signal 을 잡아보는 
예제입니다. 기본개념은 JNI C 메소드를 호출해 signal 을 등록하고, C native 코드에서
signal 이 오면, Java 의 특정 메소드를 JNI callback 을 이용해 호출시켜 주는
구조입니다.


javaservice:/home/guest/source/signal$ ls -alF
total 12
drwxr-xr-x   3 java     java         4096 Jan  1 23:21 ./
drwxrwxrwx   6 guest    users        4096 Jan  1 23:21 ../
drwxr-xr-x   3 java     java         4096 Jan  1 23:20 org/
javaservice:/home/guest/source/signal$ ls -alF org/jsn/signal/
total 12
drwxr-xr-x   2 java     java         4096 Jan  1 23:36 ./
drwxr-xr-x   3 java     java         4096 Jan  1 23:21 ../
-rw-r--r--   1 java     java          651 Jan  1 23:36 SignalTest.java
javaservice:/home/guest/source/signal# cat org/jsn/signal/SignalTest.java
package org.jsn.signal;

public class SignalTest {

  public SignalTest() {
    for(int i=1;i<31;i++)
        signal(i, "handle");
    System.out.println("signal listening");
  }

  public void do_something(){
    // infinite loop
    for(int i=0; true ; i++) {
      System.out.println("waiting..." + i);
      try{Thread.sleep(1000 * 10);}catch(Exception e){}
    }
  }

  public native synchronized void signal(int signum, String handles);


 /* This callback method will be called by native code*/
  public void handle(int signum) {
    System.out.println("I have got signal : " + signum);
    if ( signum == 3 || signum == 9 || signum == 15 ) {
      System.out.println("gracefully exited, really?");
      System.exit(0);// NOTE: this does NOT work;
    }
  }

  static {
    try{
      System.loadLibrary("signalhandle");
    }catch(Exception e){
      e.printStackTrace();
    }
  }
  public static void main(String[] args){
    SignalTest test = new SignalTest();
    test.do_something();
  }
}


javaservice:/home/guest/source/signal$
javaservice:/home/guest/source/signal$ javac org/jsn/signal/SignalTest.java
javaservice:/home/guest/source/signal$ ls -alF org/jsn/signal/
total 16
drwxr-xr-x   2 java     java         4096 Jan  1 23:37 ./
drwxr-xr-x   3 java     java         4096 Jan  1 23:21 ../
-rw-r--r--   1 java     java         1088 Jan  1 23:37 SignalTest.class
-rw-r--r--   1 java     java          651 Jan  1 23:36 SignalTest.java
javaservice:/home/guest/source/signal$ javah -jni org.jsn.signal.SignalTest
javaservice:/home/guest/source/signal$ ls -alF
total 16
drwxr-xr-x   3 java     java         4096 Jan  1 23:38 ./
drwxrwxrwx   6 guest    users        4096 Jan  1 23:21 ../
drwxr-xr-x   3 java     java         4096 Jan  1 23:20 org/
-rw-r--r--   1 java     java          488 Jan  1 23:38 org_jsn_signal_SignalTest.h
javaservice:/home/guest/source/signal# cat org_jsn_signal_SignalTest.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_jsn_signal_SignalTest */

#ifndef _Included_org_jsn_signal_SignalTest
#define _Included_org_jsn_signal_SignalTest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     org_jsn_signal_SignalTest
 * Method:    signal
 * Signature: (ILjava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_org_jsn_signal_SignalTest_signal
  (JNIEnv *, jobject, jint, jstring);

#ifdef __cplusplus
}
#endif
#endif
javaservice:/home/guest/source/signal#

(....... vi signalhandle.c .......   )

javaservice:/home/guest/source/signal# ls -alF
total 48
   4 drwxr-xr-x   3 java     java         4096 Jan  2 01:38 ./
   4 drwxrwxrwx   6 guest    users        4096 Jan  2 01:33 ../
   8 -rw-r--r--   1 root     root         4625 Jan  2 01:28 NativeStringUtil.c
   4 -rw-r--r--   1 root     root          559 Jan  2 01:28 NativeStringUtil.h
   4 -rw-r--r--   1 root     root          129 Jan  2 01:38 cc
   4 drwxr-xr-x   3 java     java         4096 Jan  1 23:20 org/
   4 -rw-r--r--   1 java     java          488 Jan  2 01:35 org_jsn_signal_SignalTest.h
   4 -rw-r--r--   1 java     java          829 Jan  2 01:37 signalhandle.c
javaservice:/home/guest/source/signal#
javaservice:/home/guest/source/signal# cat signalhandle.c
#include <signal.h>
#include "org_jsn_signal_SignalTest.h"
#include "NativeStringUtil.h"

/*
 NOTE: global variable !!
 */
JNIEnv *g_env;
jobject g_obj;
jmethodID g_mid;

void signal_handle(signum)
int signum;
{
   if ( g_mid == 0 ) return;
   (*g_env)->CallVoidMethod(g_env, g_obj, g_mid, signum);
}

/*
 * Class:     org_jsn_signal_SignalTest
 * Method:    signal
 * Signature: (ILjava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_org_jsn_signal_SignalTest_signal
  (JNIEnv *env, jobject obj, jint signum, jstring handle_name)
{
  jclass cls = (*env)->GetObjectClass(env, obj);
  char *method = jbyteArray2cstr( env, javaGetBytes(env, handle_name) );
  jmethodID mid = (*env)->GetMethodID(env,cls, method, "(I)V");
  if ( mid == 0 ) return;
  g_env = env;
  g_obj = obj;
  g_mid = mid;

  signal(signum, signal_handle);
}


javaservice:/home/guest/source/signal# cat cc
#!/bin/sh
gcc -shared -I/usr/java/include \
-I/usr/java/include/linux \
-o libsignalhandle.so signalhandle.c NativeStringUtil.c

javaservice:/home/guest/source/signal# sh cc
javaservice:/home/guest/source/signal#
javaservice:/home/guest/source/signal# export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
javaservice:/home/guest/source/signal# export CLASSPATH=.:$CLASSPATH
javaservice:/home/guest/source/signal#
javaservice:/home/guest/source/signal# java org.jsn.signal.SignalTest
signal listening
waiting...0
waiting...1
waiting...2
....

이렇게 수행되고 있을 때, 다른 터미널에서 kill 명령어를 날려 봅니다.

[Terminal B]
javaservice:/root# ps -ef|grep java|grep root
root     17102 15065  2 01:00 pts/4    00:00:00 /usr/java/bin/linux/native_threa
root     17110 17102  0 01:00 pts/4    00:00:00 /usr/java/bin/linux/native_threa
root     17111 17110  0 01:00 pts/4    00:00:00 /usr/java/bin/linux/native_threa
root     17112 17110  0 01:00 pts/4    00:00:00 /usr/java/bin/linux/native_threa
root     17115 15768  0 01:00 pts/3    00:00:00 grep java
javaservice:/root# kill -2 17102
javaservice:/root# kill -3 17102
javaservice:/root# kill -15 17102
javaservice:/root# kill -10 17102
javaservice:/root# kill -9 17102
javaservice:/root#


결과는 다음과 같습니다.

javaservice:/home/guest/source/signal# java org.jsn.signal.SignalTest
signal listening
waiting...0
waiting...1
waiting...2
I have got signal : 2
I have got signal : 3
gracefully exited, really?
waiting...3
I have got signal : 15
gracefully exited, really?
waiting...4
I have got signal : 10
waiting...5
Killed
javaservice:/home/guest/source/signal#

이 프로그램은 Ctl-C 를 눌려도 종료되지 않습니다. signal 2 : SIGINT 가 잡히기
때문입니다. 오로지 다른 터미널 창에서 kill -9 를 날려야만 죽습니다.
주의할 점은 JNI의 callback 을 통해 수행되는 Java code 에서 System.exit() 을
날려도 JVM 이 exit 되지는 않습니다.

NOTE: signal 번호는 아래의 첨부 A 를 참조하세요.

따라서, 이와 같은 signal 처리는 단지 자바프로그램에서 process 의 signal 을
받아 무언가를 하도록 할 때 사용될 수 있을 뿐이며, "gracefully exiting" 을
이처럼 JNI의 callback 을 이용해 구현할 수는 없는 듯 합니다. 즉, Ctl-C 를
누른다거나, kill -9 를 제외한 kill -3 (SIGQUIT), kill -15(SIGTERM) 를 잡아채어
미진한 종료작업을 수행한 수 JVM이 내려가도록 하려면 뭔가 다른 방법을 강구해야
하는 듯 합니다.


JNI callback 을 사용하지 말아야 한다면, JNI 메소드를 부르되 signal 이
올 때까지 blocking 이 걸려있으면 될 듯 한데, 어디 한번 또 해 볼까요....

[두번째 예제] "gracefully exiting"
기본적인 개념은 별도의 자바 Thread 가 C native 코드를 호출하여 특정 signal 이
발생할 때 까지 기다리게 됩니다.


javaservice:/home/guest/source/signal2#
javaservice:/home/guest/source/signal2#
javaservice:/home/guest/source/signal2# ls -alF
total 24
   4 drwxr-xr-x   3 root     root         4096 Jan  2 02:30 ./
   4 drwxrwxrwx   7 guest    users        4096 Jan  2 01:43 ../
   4 -rw-r--r--   1 root     root          129 Jan  2 01:43 cc
   4 drwxr-xr-x   3 root     root         4096 Jan  2 01:43 org/
   4 -rw-r--r--   1 root     root          269 Jan  2 02:26 signalhandle2.c
   
javaservice:/home/guest/source/signal2#
javaservice:/home/guest/source/signal2#
javaservice:/home/guest/source/signal2# ls -alF org/jsn/signal/
total 24
   4 drwxr-xr-x   2 root     root         4096 Jan  2 02:03 ./
   4 drwxr-xr-x   3 root     root         4096 Jan  2 01:43 ../
   4 -rw-r--r--   1 root     root          488 Jan  2 02:03 SignalMonitor.java
   4 -rw-r--r--   1 root     root          505 Jan  2 02:00 SignalTest2.java

javaservice:/home/guest/source/signal2# cat org/jsn/signal/SignalMonitor.java
package org.jsn.signal;

public class SignalMonitor extends Thread
{
  static {
    try{
        System.loadLibrary("signalhandle2");
    }catch(Exception e){
        e.printStackTrace();
    }
  }
  public SignalMonitor(){
    super();
  }
  public void run(){
    signal_wait(15);  // SIGTERM
    System.out.println("I've got SIGTERM signal");
    System.out.println("program terminated gracefully");
    System.exit(1);
  }
  public native synchronized void signal_wait(int signum);
}

javaservice:/home/guest/source/signal2#
javaservice:/home/guest/source/signal2# cat org/jsn/signal/SignalTest2.java
package org.jsn.signal;

public class SignalTest2 {

  public SignalTest2() {
    SignalMonitor monitor = new SignalMonitor();
    monitor.start();
    System.out.println("signal listening");
  }

  public void do_something(){
    // infinite loop
    for(int i=0; true ; i++) {
      System.out.println("waiting..." + i);
      try{Thread.sleep(1000 * 10);}catch(Exception e){}
    }
  }

  public static void main(String[] args){
    SignalTest2 test = new SignalTest2();
    test.do_something();
  }
}

javaservice:/home/guest/source/signal2#
javaservice:/home/guest/source/signal2#
javaservice:/home/guest/source/signal2# javac org/jsn/signal/*.java
javaservice:/home/guest/source/signal2# ls -alF org/jsn/signal/
total 24
   4 drwxr-xr-x   2 root     root         4096 Jan  2 02:44 ./
   4 drwxr-xr-x   3 root     root         4096 Jan  2 01:43 ../
   4 -rw-r--r--   1 root     root          813 Jan  2 02:55 SignalMonitor.class
   4 -rw-r--r--   1 root     root          489 Jan  2 02:44 SignalMonitor.java
   4 -rw-r--r--   1 root     root          953 Jan  2 02:55 SignalTest2.class
   4 -rw-r--r--   1 root     root          505 Jan  2 02:00 SignalTest2.java
javaservice:/home/guest/source/signal2#
javaservice:/home/guest/source/signal2# javah -jni org.jsn.signal.SignalMonitor
javaservice:/home/guest/source/signal2# ls -alF
total 40
   4 drwxr-xr-x   3 root     root         4096 Jan  2 02:05 ./
   4 drwxrwxrwx   7 guest    users        4096 Jan  2 01:43 ../
   4 -rw-r--r--   1 root     root          129 Jan  2 01:43 cc
   4 drwxr-xr-x   3 root     root         4096 Jan  2 01:43 org/
   4 -rw-r--r--   1 root     root          487 Jan  2 02:05 org_jsn_signal_SignalMonitor.h
   4 -rw-r--r--   1 root     root          269 Jan  2 02:26 signalhandle2.c

javaservice:/home/guest/source/signal2#
javaservice:/home/guest/source/signal2# cat org_jsn_signal_SignalMonitor.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_jsn_signal_SignalMonitor */

#ifndef _Included_org_jsn_signal_SignalMonitor
#define _Included_org_jsn_signal_SignalMonitor
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     org_jsn_signal_SignalMonitor
 * Method:    signal_wait
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_org_jsn_signal_SignalMonitor_signal_1wait
  (JNIEnv *, jobject, jint);

#ifdef __cplusplus
}
#endif
#endif

javaservice:/home/guest/source/signal2#
javaservice:/home/guest/source/signal2# cat signalhandle2.c
#include <signal.h>
#include "org_jsn_signal_SignalMonitor.h"

int signal_reached = 0;

void signal_handle(signum)
int signum;
{
   signal_reached = 1;
}

/*
 * Class:     org_jsn_signal_SignalMonitor
 * Method:    signal_wait
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_org_jsn_signal_SignalMonitor_signal_1wait
  (JNIEnv *env, jobject obj, jint signum)
{
   signal_reached = 0;
   signal(signum, signal_handle);
   while ( signal_reached == 0 )
       ;
   /* CPU를 다소 점유할텐데, 더 좋은 방법 있나요? */
}

javaservice:/home/guest/source/signal2#
javaservice:/home/guest/source/signal2# cat cc
#!/bin/sh

gcc -shared -I/usr/java/include \
-I/usr/java/include/linux \
-o libsignalhandle2.so signalhandle2.c


javaservice:/home/guest/source/signal2#
javaservice:/home/guest/source/signal2# sh cc
javaservice:/home/guest/source/signal2# ls -alF
total 32
   4 drwxr-xr-x   3 root     root         4096 Jan  2 02:36 ./
   4 drwxrwxrwx   7 guest    users        4096 Jan  2 01:43 ../
   4 -rw-r--r--   1 root     root          112 Jan  2 02:35 cc
   8 -rwxr-xr-x   1 root     root         5299 Jan  2 02:36 libsignalhandle2.so*
   4 drwxr-xr-x   3 root     root         4096 Jan  2 01:43 org/
   4 -rw-r--r--   1 root     root          482 Jan  2 02:29 org_jsn_signal_SignalMonitor.h
   4 -rw-r--r--   1 root     root          283 Jan  2 02:36 signalhandle2.c


이제 실행시켜 보겠습니다.

javaservice:/home/guest/source/signal2# java org.jsn.signal.SignalTest2
signal listening
waiting...0
waiting...1
......



실행되고 있는 중에 다른 Terminal 창에서 다음과 같이 SIGTERM(15) 을 날립니다.

[Terminal B]
javaservice:/root# ps -ef|grep java|grep root
root     19104 15065  4 02:50 pts/4    00:00:00 /usr/java/bin/linux/native_threa
root     19112 19104  0 02:50 pts/4    00:00:00 /usr/java/bin/linux/native_threa
root     19113 19112  0 02:50 pts/4    00:00:00 /usr/java/bin/linux/native_threa
root     19114 19112  0 02:50 pts/4    00:00:00 /usr/java/bin/linux/native_threa
root     19115 19112 99 02:50 pts/4    00:00:05 /usr/java/bin/linux/native_threa
root     19117 15768  0 02:50 pts/3    00:00:00 grep java
javaservice:/root# kill -15 19104
javaservice:/root#


결과는 다음과 같습니다.

javaservice:/home/guest/source/signal2# java org.jsn.signal.SignalTest2
signal listening
waiting...0
waiting...1
I've got SIGTERM signal
program terminated gracefully
javaservice:/home/guest/source/signal2#


원하시는 답변이 되었기를 바랍니다.




----------------------------------------------------------------------------------
2000.1.4 CPU 점거현상 보완 추가

CPU를 점거하는 문제를 해결하였습니다. 아래 문서를 참조하세요.

"CPU 점거현상 보완 추가"
http://www.javaservice.net/~java/bbs/read.cgi?m=devtip&b=javatip&c=r_p&n=978538886



[첨부A signal.h : Linux]

/* Signals.  */
#define SIGHUP      1   /* Hangup (POSIX).  */
#define SIGINT      2   /* Interrupt (ANSI).  */
#define SIGQUIT     3   /* Quit (POSIX).  */
#define SIGILL      4   /* Illegal instruction (ANSI).  */
#define SIGTRAP     5   /* Trace trap (POSIX).  */
#define SIGABRT     6   /* Abort (ANSI).  */
#define SIGIOT      6   /* IOT trap (4.2 BSD).  */
#define SIGBUS      7   /* BUS error (4.2 BSD).  */
#define SIGFPE      8   /* Floating-point exception (ANSI).  */
#define SIGKILL     9   /* Kill, unblockable (POSIX).  */
#define SIGUSR1     10  /* User-defined signal 1 (POSIX).  */
#define SIGSEGV     11  /* Segmentation violation (ANSI).  */
#define SIGUSR2     12  /* User-defined signal 2 (POSIX).  */
#define SIGPIPE     13  /* Broken pipe (POSIX).  */
#define SIGALRM     14  /* Alarm clock (POSIX).  */
#define SIGTERM     15  /* Termination (ANSI).  */
#define SIGSTKFLT   16  /* Stack fault.  */
#define SIGCLD      SIGCHLD /* Same as SIGCHLD (System V).  */
#define SIGCHLD     17  /* Child status has changed (POSIX).  */
#define SIGCONT     18  /* Continue (POSIX).  */
#define SIGSTOP     19  /* Stop, unblockable (POSIX).  */
#define SIGTSTP     20  /* Keyboard stop (POSIX).  */
#define SIGTTIN     21  /* Background read from tty (POSIX).  */
#define SIGTTOU     22  /* Background write to tty (POSIX).  */
#define SIGURG      23  /* Urgent condition on socket (4.2 BSD).  */
#define SIGXCPU     24  /* CPU limit exceeded (4.2 BSD).  */
#define SIGXFSZ     25  /* File size limit exceeded (4.2 BSD).  */
#define SIGVTALRM   26  /* Virtual alarm clock (4.2 BSD).  */
#define SIGPROF     27  /* Profiling alarm clock (4.2 BSD).  */
#define SIGWINCH    28  /* Window size change (4.3 BSD, Sun).  */
#define SIGPOLL     SIGIO   /* Pollable event occurred (System V).  */
#define SIGIO       29  /* I/O now possible (4.2 BSD).  */
#define SIGPWR      30  /* Power failure restart (System V).  */
#define SIGUNUSED   31


-------------------------------------------------------  
  본 문서는 자유롭게 배포/복사 할 수 있으나 반드시
  이 문서의 저자에 대한 언급을 삭제하시면 안됩니다
================================================
  자바서비스넷 이원영
  E-mail: javaservice@hanmail.net
  PCS:019-310-7324
================================================

제목 : Re: CPU 점거 보완
글쓴이: 까막(guest) 2001/01/02 09:56:52 조회수:1756 줄수:10
안녕하세요 첨뵙겠습니다 ^^
Splenit의 까막이라고 합니다.
while문에 의한 부하문제는 sleep()으로 재운다음에
raise(SIGARLM)으로 깨우면 될 듯 합니다.
즉 signal_reached = 1;
대신에 raise(SIGALRM)
while(signal_reached == 0) 이 아니라 sleep(0)
가 되겠죠 ^^
이러면 while문에의한 CPU점거문제는 해결될듯 합니다.
Java는 아니고 C로 데몬짤때 썼던 코드입니당~~
제목 : CPU 점거현상 보완 추가
글쓴이: 이원영(javaservice) 2001/01/04 01:21:26 조회수:3744 줄수:119
2000.1.4 CPU 점거현상 보완 추가

까막님(whitecrw@orgio.net)이 raise(SIGALRM)과 sleep() 을 이용해
보라고 하셨는데, 막상 해 보니 sleep() 이 완전한 blocking 에 빠지지 않고 대략
8초 후에 그냥 빠져나와 버리더군요... 테스트한 소스는 다음과 같습니다.

---------------------------------------
void signal_handle(signum)
int signum;
{
   raise(SIGALRM);  
}

NIEXPORT void JNICALL Java_org_jsn_signal_SignalMonitor_signal_1wait
  (JNIEnv *env, jobject obj, jint signum)
{
    signal(signum, signal_handle);
    sleep(0);
}
---------------------------------------



GNU의 signal 처리기법에 관련한 문서에 보면 그와 같은 문제가 있다고 지적되어
있으며, 다음과 같이 하라고 명시되어 있습니다.

Sample 1:
---------------------------------------
int signal_reached = 0;
void signal_handle(signum)
int signum;
{
   signal_reached = 1;
}

JNIEXPORT void JNICALL Java_org_jsn_signal_SignalMonitor_signal_1wait
  (JNIEnv *env, jobject obj, jint signum)
{
    signal_reached = 0;
    signal(signum, signal_handle);
    while( ! signal_reached )
       sleep(1);
}
---------------------------------------

이 예제는 제대로 잘 동작합니다. 그러나, 그 문서에는 이러한 프로그래밍 보다는
아래와 같은 방법을 사용하도록 권하고 있습니다.

Sample 2:

---------------------------------------
....
int signal_reached = 0;

void signal_handle(signum)
int signum;
{
   signal_reached = 1;
}

JNIEXPORT void JNICALL Java_org_jsn_signal_SignalMonitor_signal_1wait
  (JNIEnv *env, jobject obj, jint signum)
{
    sigset_t mask, oldmask;

    signal_reached = 0;
    signal(signum, signal_handle);

    sigemptyset (&mask);
    sigaddset (&mask, SIGUSR1);
    sigprocmask (SIG_BLOCK, &mask, &oldmask);
    while(!signal_reached)
       sigsuspend (&oldmask);
    sigprocmask (SIG_UNBLOCK, &mask, NULL);
}
---------------------------------------

이 방법이 답일 듯 합니다.


GNU 관련 문서는 아래에 있습니다.
http://www.gnu.org/manual/glibc-2.0.6/html_chapter/libc_toc.html
http://www.gnu.org/manual/glibc-2.0.6/html_chapter/libc_21.html#SEC381



NOTE: 이 경우, JDK THREADS_FLAG  가 native 로 되어 있을 경우는 kill 명령어를 
날릴 때 잘 찾아서 날려야 합니다. native thread  모드에서는 여러개의 프로세스들이
나타납니다. 예를 들면,

javaservice:/root# ps -ef|grep java|grep root
root     24430 23282  0 00:50 pts/3    00:00:00 /usr/java/bin/linux/native_threa
root     24438 24430  0 00:50 pts/3    00:00:00 /usr/java/bin/linux/native_threa
root     24439 24438  0 00:50 pts/3    00:00:00 /usr/java/bin/linux/native_threa
root     24440 24438  0 00:50 pts/3    00:00:00 /usr/java/bin/linux/native_threa
root     24441 24438  0 00:50 pts/3    00:00:00 /usr/java/bin/linux/native_threa
root     24467 23416  0 00:51 pts/4    00:00:00 grep java
javaservice:/root# kill -15 24441

처럼, 제일 마지막 프로세스가 JNI 관련한 thread 처럼 보이며, 해당 프로세스 ID 에
signal 을 날려야 되더군요...

반면 THREADS_FLAG=green 일 경우는 아래 처럼 프로세스가 하나이니 별 혼선이 없네요.

javaservice:/root# ps -ef|grep java|grep root
root     24565 23282  5 00:53 pts/3    00:00:00 /usr/java/bin/i686/green_threads
root     24582 23416  0 00:53 pts/4    00:00:00 grep java
javaservice:/root# kill -15 24565

-------------------------------------------------------  
  본 문서는 자유롭게 배포/복사 할 수 있으나 반드시
  이 문서의 저자에 대한 언급을 삭제하시면 안됩니다
================================================
  자바서비스넷 이원영
  E-mail: javaservice@hanmail.net
  PCS:019-310-7324
================================================

댓글 없음:

댓글 쓰기