IT/Tips

Binary Core 분석

싸후이 2007. 1. 15. 14:08

문제 설명
응용 프로그램이 잘못된 일부 native 코드(머신 코드)로 인해 WebLogic 서버 프로세스를 종료할 때 바이너리 코어 파일을 생성합니다.  서버 크래시, JVM 크래시, 시스템 크래시 또는 HotSpot 오류는 이러한 경우와 관련이 있을 수도 있습니다.  이 패턴은 다양한 플랫폼에서 코어 파일의 정보를 수집하는 데 필요한 단계를 설명합니다.


문제 해결
다음 항목을 모두 수행해야 하는 것은 아닙니다.  어떤 경우에는 다음 중 일부만 수행하여도 해결할 수 있습니다.

항목 바로가기:

문제 발생 원인
이러한 오류의 원인을 파악하기 위해 WebLogic 서버 프로세스에서 사용된 native 코드에서 오류가 발생할 가능성이 있는 부분을 모두 확인해야 합니다.  다음 항목을 중점적으로 확인합니다.

  1. WebLogic 서버 Performance Pack.  WebLogic 서버 Performance Pack은 native 코드이며 사용 시 이러한 오류가 발생할 가능성이 있습니다.  이 기능을 해제하여 이것이 문제의 원인인지 여부를 판별합니다. 콘솔이나 명령줄을 통해 이 작업을 수행할 수 있습니다.  콘솔을 사용하는 경우 NativeIOEnabled를 false로 설정한 다음 Servers 탭을 살펴 보십시오.   콘솔의 Servers 탭에서 각 단계의 정확한 순서는 Enabling Performance Packs 섹션을 참조하십시오.  WLS 8.1의 경우 http://e-docs.bea.com/wls/docs81/perform/WLSTuning.html#1142800에 있습니다. 각 단계는 다음과 같습니다.
    a.    Administration Server를 시작합니다(아직 실행하지 않은 경우).
    b.    도메인의 Administration Console에 액세스합니다.
    c.    왼쪽 창에서 서버 노드를 확장하여 도메인에 구성된 서버를 표시합니다.
    d.    구성할 서버 인스턴스의 이름을 클릭합니다.
    e.    Configuration> Tuning 탭을 선택합니다.
    f.    Enable Native IO 확인란이 선택되지 않은 경우 선택합니다.
    g.    Apply 를 클릭합니다.
    h.    서버를 다시 시작합니다.

    WebLogic 서버의 시작 명령에 대해 java 옵션을 사용하여 지정할 수도 있습니다.  명령줄에서 -Dweblogic.NativeIOEnabled=false로 설정한 다음 서버를 시작합니다.  명령줄의 명령은 콘솔을 통해 보내는 명령보다 우선합니다.

  2. 모든 Type 2 JDBC 드라이버는 native DBMS 라이브러리를 사용하므로 이러한 유형의 오류가 발생할 수 있습니다.  이 드라이버가 문제의 원인인지 판별하려면 pure java(Type 4) JDBC 드라이버로 전환합니다.
  1. JNI 호출을 사용하여 액세스하는 모든 native 라이브러리도 이러한 유형의 오류가 발생할 수 있습니다.  응용 프로그램에서 이러한 라이브러리를 사용하는 경우 신중하게 조사해야 합니다.  보통 이러한 라이브러리는 응용 프로그램에서 해당 기능을 필요로 하기 때문에 제외시키기 어렵습니다.  이것을 사용하는 방법이 코어 덤프 / Dr Watson 오류와 관련이 있는지 판별하려면 많은 데이터가 필요합니다.
  1. JVM 자체도 native 프로그램이며 이러한 오류가 발생할 수 있습니다.  JVM이 의심스러운 경우 인증된 다른 JVM 또는 상위 버전을 사용하여 JVM 버그가 오류의 원인인지 파악합니다.  많은 JVM 버그는 JIT 컴파일러 사용과 관련이 있으며 종종 이 기능을 해제하면 이러한 유형의 문제가 해결되기도 합니다.  이 기능을 해제하려면 대개 -Djava.compiler=none 명령 옵션을 사용합니다.
  1. 모두 그렇지는 않지만 JVM이 코어를 발생시킨 라이브러리에 관한 유용한 정보가 포함된 작은 로그 파일을 생성하는 경우가 있습니다.  이 파일은 WebLogic 서버가 시작된 디렉토리에서 생성되며 hs_err_pid<PID #>.log 형식입니다. 여기에서 <PID #>는 WebLogic 서버 프로세스의 프로세스 ID입니다.

이 과정을 통해 오류의 원인을 판별할 수 없는 경우 WebLogic 서버가 시작된 디렉토리에 생성된 코어 파일을 조사합니다.  코어의 원인을 파악하려면 바이너리 코어 파일에서 정확한 스택 트레이스를 가져와야 합니다.  이렇게 하려면 이 진단 패턴에 설명된 것처럼 운영 체제에 따라 dbx나 gdb와 같은 디버거를 실행합니다.

페이지 맨 위


SOLARIS 운영체제에서 코어 정보 수집

  1. file <full path>/core를 실행하여 코어 파일의 출처가 Java VM인지 여부를 확인합니다.
  1. 다음과 같이 dbx나 gdb를 사용하여 스택 트레이스를 가져옵니다.  gdb를 사용하면 더욱 유용한 정보를 얻을 수 있습니다.  Sun 기술 지원부에서는 코어 파일 분석에 dbx(1)를 사용할 것을 권장합니다.  dbx 라이센스가 있는 제품이 없는 경우 Sun(  http://wwws.sun.com/software/sundev/buy.html)에서 번들 형식의 30일 평가판을 다운로드할 수 있습니다.

코어 파일이 생성되지 않는 경우는 파일 사용 권한 문제나 코어 파일에 대한 제한 때문입니다.  코어 덤프 파일의 크기는 다음 요소의 영향을 받을 수 있습니다.

  • ulimit -a를 검사하여 자신의 환경에서 코어 파일을 생성할 수 있는지 확인합니다.
  • ulimit -c(코어 파일의 크기 제한을 나타냅니다.  이 항목을 ulimit -c unlimited로 수정합니다.)
  • 커널 제한(ulimit -c에 대해 hard limit).
  • 사용 가능한 사용자 디스크 공간(디스크 할당량이 있습니까?)
  • 참고 항목: 코어 파일 생성을 위해 검사해야 할 운영 체제 설정

생성된 코어 파일이 있으면 코어 파일에 대해 dbx 또는 gdb를 실행합니다.  다음은 dbx 및 gdb용 명령과 gdb에 의해 생성된 출력 예제입니다. (참고:  DEBUG_PROG는 Java 환경에서 실행할 디버거나 프로파일러를 지정할 수 있는 환경 변수입니다.)

a. dbx:


$ java -version  (need to use right version of jdk)
$ ls /opt/bin/dbx (need to know dbx location) or "which dbx"
$ export DEBUG_PROG=/opt/bin/dbx (or wherever "dbx" is located)

For JDK 1.3.X do the following:
   $ <path to java command>/java corefile
For JDK 1.4.X do the following:
   $ dbx <path to java command>/java corefile

Now you will be in the debugger.  Execute the following commands:
(dbx) where    ("shows a summary of the stack")
(dbx) threads    ("shows the state of the existing threads")
(dbx) quit


이 명령은 마지막으로 실행된 스레드의 스택 트레이스를 가져와서(where 명령) 코어 파일에 모든 스레드의 상태를 표시합니다(threads 명령).

b. gdb:


 $ java -version  (need to use right version of jdk)
$ ls /usr/local/bin/gdb (need to know gdb location) or "which gdb"
$ export DEBUG_PROG=/usr/local/bin/gdb  (or wherever "gdb" is located)

For JDK 1.3.X do the following:
   $ <path to java command>/java corefile
For JDK 1.4.X do the following:
   $ gdb <path to java command>/java corefile


Now you will be in the debugger.  Execute the following commands:
(gdb) where        ("shows a summary of the stack")
(gdb) thr    ("switch among threads or show the current thread")
(gdb) info thr        ("inquire about existing threads")
(gdb) thread apply 1 bt    ("apply a command to a list of threads, specifically the backtrace to thread #1")
(gdb) quit


where 명령을 사용하면 실행된 마지막 스레드의 스택 트레이스가 생성되고, thr 명령을 사용하면 현재 스레드가 표시되고, info thr 명령을 사용하면 모든 스레드의 상태가 표시되고, thread apply 1 bt 명령을 사용하면 코어 파일에 포함된 스레드 1의 스택 트레이스를 다른 방식으로 가져올 수 있습니다.  마지막 명령 thread apply # bt에서 #을 실제 스레드 번호로 바꾸어 개별 스레드의 스택 트레이스를 가져오거나 3을 "all"로 바꾸어 모든 스레드의 스택 트레이스를 가져올 수 있습니다.

다음 예제에서는 gdb 디버거에 나타나는 코어 파일(위의 명령 포함)을 보여 줍니다.  이 예제 코어는 응용 프로그램의 사용자 native 코드 오류로 인해 야기된 것입니다.  (굵게 서식이 지정된 항목을 참조하십시오.)  이 스택 트레이스에서 신호 처리기가 호출되기 전 마지막 줄을 살펴보십시오.  native 라이브러리 libhello.so에 포함된 displayHelloWorld 함수를 볼 수 있습니다.


$ export DEBUG_PROG=/usr/local/bin/gdb
    $ java core

    GNU gdb 5.0
    Copyright 2000 Free Software Foundation, Inc.
    GDB is free software, covered by the GNU General Public License, and you are
    welcome to change it and/or distribute copies of it under certain conditions.
    Type "show copying" to see the conditions.
    There is absolutely no warranty for GDB.  Type "show warranty" for details.
    This GDB was configured as "sparc-sun-solaris2.8"...
    (no debugging symbols found)...
    Core was generated by `/wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/bin/../bin/sparc/native_threads'.
    Program terminated with signal 9, Killed.
    Reading symbols from /usr/lib/libthread.so.1...(no debugging symbols found)...
    Loaded symbols for /usr/lib/libthread.so.1
    Reading symbols from /usr/lib/libdl.so.1...(no debugging symbols found)...done.
    Loaded symbols for /usr/lib/libdl.so.1
    Reading symbols from /usr/lib/libc.so.1...(no debugging symbols found)...done.
    Loaded symbols for /usr/lib/libc.so.1
    Reading symbols from /usr/platform/SUNW,UltraAX-i2/lib/libc_psr.so.1...
    (no debugging symbols found)...done.
    Loaded symbols for /usr/platform/SUNW,UltraAX-i2/lib/libc_psr.so.1
    Reading symbols from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/server/libjvm.so...(no debugging symbols found)... done.
    Loaded symbols for /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/server/libjvm.so
    Reading symbols from /usr/lib/libCrun.so.1...(no debugging symbols found)...
    Loaded symbols for /usr/lib/libCrun.so.1
    Reading symbols from /usr/lib/libsocket.so.1...(no debugging symbols found)...
    Loaded symbols for /usr/lib/libsocket.so.1
    Reading symbols from /usr/lib/libnsl.so.1...(no debugging symbols found)...
    Loaded symbols for /usr/lib/libnsl.so.1
    Reading symbols from /usr/lib/libm.so.1...(no debugging symbols found)...done.
    Loaded symbols for /usr/lib/libm.so.1
    Reading symbols from /usr/lib/libw.so.1...
     warning: Lowest section in /usr/lib/libw.so.1 is .hash at 00000074
    (no debugging symbols found)...done.
    Loaded symbols for /usr/lib/libw.so.1
    Reading symbols from /usr/lib/libmp.so.2...(no debugging symbols found)...
    Loaded symbols for /usr/lib/libmp.so.2
    Reading symbols from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/native_threads/libhpi.so...(no debugging symbols found)...done.
    Loaded symbols for /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/native_threads/libhpi.so
    Reading symbols from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/libverify.so...(no debugging symbols found)...done.
    Loaded symbols for /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/libverify.so
    Reading symbols from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/libjava.so...(no debugging symbols found)...done.
Loaded symbols for /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/libjava.so
    Reading symbols from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/libzip.so...(no debugging symbols found)...done.
    Loaded symbols for /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/libzip.so
    Reading symbols from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/libnet.so...(no debugging symbols found)...done.
    Loaded symbols for /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/libnet.so
    Reading symbols from /wwsl/sharedInstalls/solaris/wls70sp2/server/lib/solaris/libfilelock.so...(no debugging symbols found)...done.
    Loaded symbols for /wwsl/sharedInstalls/solaris/wls70sp2/server/lib/solaris/libfilelock.so
    Reading symbols from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/libioser12.so...(no debugging symbols found)...done.
    Loaded symbols for /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/libioser12.so
    Reading symbols from /usr/lib/nss_nis.so.1...(no debugging symbols found)...
    Loaded symbols for /usr/lib/nss_nis.so.1
    Reading symbols from /wwsl/sharedInstalls/solaris/wls70sp2/server/lib/solaris/libstackdump.so...(no debugging symbols found)...done.
    Loaded symbols for /wwsl/sharedInstalls/solaris/wls70sp2/server/lib/solaris/libstackdump.so
    Reading symbols from /usr/lib/libmd5.so.1...(no debugging symbols found)...
    Loaded symbols for /usr/lib/libmd5.so.1
    Reading symbols from /wwsl/sharedInstalls/solaris/wls70sp2/server/lib/solaris/libmuxer.so...(no debugging symbols found)...done.
    Loaded symbols for /wwsl/sharedInstalls/solaris/wls70sp2/server/lib/solaris/libmuxer.so
    Reading symbols from /usr/ucblib/libucb.so.1...(no debugging symbols found)...
    Loaded symbols for /usr/ucblib/libucb.so.1
    Reading symbols from /usr/lib/libresolv.so.2...(no debugging symbols found)...
    Loaded symbols for /usr/lib/libresolv.so.2
    Reading symbols from /usr/lib/libelf.so.1...(no debugging symbols found)...
    Loaded symbols for /usr/lib/libelf.so.1
    Reading symbols from /home/usera/wls70/solaris/projectWork/lib/libhello.so...
    (no debugging symbols found)...done.
    Loaded symbols for /home/usera/wls70/solaris/projectWork/lib/libhello.so

(gdb) where

    #0  0xff369764 in __sigprocmask () from /usr/lib/libthread.so.1
    #1  0xff35e978 in _resetsig () from /usr/lib/libthread.so.1
    #2  0xff35e118 in _sigon () from /usr/lib/libthread.so.1
    #3  0xff361158 in _thrp_kill () from /usr/lib/libthread.so.1
    #4  0xff24b908 in raise () from /usr/lib/libc.so.1
    #5  0xff2358f4 in abort () from /usr/lib/libc.so.1
    #6  0xfe3c6904 in __1cCosFabort6Fl_v_ ()
       from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/server/libjvm.so
    #7  0xfe3c59f8 in __1cCosbBhandle_unexpected_exception6FpnGThread_ipCpv_v_ ()
       from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/server/libjvm.so
    #8  0xfe20a8bc in JVM_handle_solaris_signal ()
       from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/server/libjvm.so
    #9  0xff36b82c in __sighndlr () from /usr/lib/libthread.so.1
    #10 <signal handler called>
    #11 0xe9f90420 in Java_HelloWorld_displayHelloWorld ()
       from /home/usera/wls70/solaris/projectWork/lib/libhello.so

    #12 0x90aec in ?? ()
    #13 0x8dc54 in ?? ()
    #14 0x8dc54 in ?? ()
    #15 0x8dc54 in ?? ()
    #16 0x8ddbc in ?? ()
    #17 0x8dde0 in ?? ()
    #18 0x8dc54 in ?? ()
    #19 0x8dc54 in ?? ()
    #20 0x8dde0 in ?? ()
    #21 0x8dc78 in ?? ()
    #22 0x8dc54 in ?? ()
    #23 0x8ddbc in ?? ()
    #24 0x8dc54 in ?? ()
    #25 0xfe5324f0 in __1cMStubRoutinesG_code1_ ()
       from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/server/libjvm.so
    #26 0xfe0cbe9c in
__1cJJavaCallsLcall_helper6FpnJJavaValue_pnMmethodHandle_pnRJavaCallArguments_pnGThread__v_ ()
       from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/server/libjvm.so
    #27 0xfe1f6dc4 in __1cJJavaCallsMcall_virtual6FpnJJavaValue_nLKlassHandle_nMsymbolHandle_4pnRJavaCallArguments_pnGThread__v_ ()
       from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/server/libjvm.so
    #28 0xfe1fcd94 in __1cJJavaCallsMcall_virtual6FpnJJavaValue_nGHandle_nLKlassHandle_nMsymbolHandle_5pnGThread__v_ ()
       from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/server/libjvm.so
    #29 0xfe21b708 in __1cMthread_entry6FpnKJavaThread_pnGThread__v_ ()
       from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/server/libjvm.so
    #30 0xfe216208 in __1cKJavaThreadDrun6M_v_ ()
       from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/server/libjvm.so
    #31 0xfe213ed0 in _start ()
       from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/server/libjvm.so

    (gdb) thr

    [Current thread is 1 (LWP    14        )]

    (gdb) info thr
      16 LWP    13          0xff29d194 in _poll () from /usr/lib/libc.so.1
      15 LWP    12          0xff29f008 in _lwp_sema_wait () from /usr/lib/libc.so.1
      14 LWP    11          0xff29f008 in _lwp_sema_wait () from /usr/lib/libc.so.1
      13 LWP    10          0xff29bc2c in _so_accept () from /usr/lib/libc.so.1
      12 LWP    9          0xff29bc2c in _so_accept () from /usr/lib/libc.so.1
      11 LWP    8          0xff29d194 in _poll () from /usr/lib/libc.so.1
      10 LWP    7          0xff29d194 in _poll () from /usr/lib/libc.so.1
      9 LWP    6          0xff29f008 in _lwp_sema_wait () from /usr/lib/libc.so.1
      8 LWP    5          0xff29f008 in _lwp_sema_wait () from /usr/lib/libc.so.1
      7 LWP    4          0xff29f008 in _lwp_sema_wait () from /usr/lib/libc.so.1
      6 LWP    3          0xff29d194 in _poll () from /usr/lib/libc.so.1
      5 LWP    2          0xff29e958 in _signotifywait () from /usr/lib/libc.so.1
      4 LWP    1          0xff29d194 in _poll () from /usr/lib/libc.so.1
      3 LWP    16          0xff29c4fc in door_restart () from /usr/lib/libc.so.1
      2 LWP    15          0xff369774 in private___lwp_cond_wait ()
       from /usr/lib/libthread.so.1
    * 1 LWP    14          0xff369764 in __sigprocmask ()
       from /usr/lib/libthread.so.1
    (gdb) thread apply 1 bt

Thread 1 (LWP    14        ):
    #0  0xff369764 in __sigprocmask () from /usr/lib/libthread.so.1
    #1  0xff35e978 in _resetsig () from /usr/lib/libthread.so.1
    #2  0xff35e118 in _sigon () from /usr/lib/libthread.so.1
    #3  0xff361158 in _thrp_kill () from /usr/lib/libthread.so.1
    #4  0xff24b908 in raise () from /usr/lib/libc.so.1
    #5  0xff2358f4 in abort () from /usr/lib/libc.so.1
    #6  0xfe3c6904 in __1cCosFabort6Fl_v_ ()
       from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/server/libjvm.so
    #7  0xfe3c59f8 in __1cCosbBhandle_unexpected_exception6FpnGThread_ipCpv_v_ ()
       from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/server/libjvm.so
    #8  0xfe20a8bc in JVM_handle_solaris_signal ()
       from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/server/libjvm.so
    #9  0xff36b82c in __sighndlr () from /usr/lib/libthread.so.1
    #10 <signal handler called>
    #11 0xe9f90420 in Java_HelloWorld_displayHelloWorld ()
       from /home/usera/wls70/solaris/projectWork/lib/libhello.so    #12 0x90aec in ?? ()
    #13 0x8dc54 in ?? ()
    #14 0x8dc54 in ?? ()
    #15 0x8dc54 in ?? ()
    #16 0x8ddbc in ?? ()
    #17 0x8dde0 in ?? ()
    #18 0x8dc54 in ?? ()
    #19 0x8dc54 in ?? ()
    #20 0x8dde0 in ?? ()
    #21 0x8dc78 in ?? ()
    #22 0x8dc54 in ?? ()
    #23 0x8ddbc in ?? ()
    #24 0x8dc54 in ?? ()
    #25 0xfe5324f0 in __1cMStubRoutinesG_code1_ ()
       from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/server/libjvm.so
    #26 0xfe0cbe9c in __1cJJavaCallsLcall_helper6FpnJJavaValue_pnMmethodHandle_pnRJavaCallArguments_pnGThread__v_ ()
       from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/server/libjvm.so
    #27 0xfe1f6dc4 in __1cJJavaCallsMcall_virtual6FpnJJavaValue_nLKlassHandle_nMsymbolHandle_4pnRJavaCallArguments_pnGThread__v_ ()
       from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/server/libjvm.so
    #28 0xfe1fcd94 in __1cJJavaCallsMcall_virtual6FpnJJavaValue_nGHandle_nLKlassHandle_nMsymbolHandle_5pnGThread__v_ ()
       from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/server/libjvm.so
    #29 0xfe21b708 in __1cMthread_entry6FpnKJavaThread_pnGThread__v_ ()
       from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/server/libjvm.so
    #30 0xfe216208 in __1cKJavaThreadDrun6M_v_ ()
       from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/server/libjvm.so
    #31 0xfe213ed0 in _start ()
       from /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/jre/lib/sparc/server/libjvm.so

    (gdb) quit

페이지 맨 위

LINUX 운영체제에서 코어 정보 수집 LINUX
GDB는 Linux의 기본 디버거로 사용되며 강력하고 안정적입니다.  다양한 비주얼 디버거를 사용할 수도 있지만 코어에서 스택 트레이스를 가져올 경우 간단한 명령줄 디버거면 충분합니다.

  1. file <full path>/core를 실행하여 코어 파일의 출처가 Java VM인지 여부를 확인합니다.
  2. Linux에서 알려진 버그를 방지하려면 최신 버전의 GNU GDB를 사용해야 합니다. 
  3. 참고: http://ftp.gnu.org/gnu/gdb/
  4. 또한 Linux에서 코어 파일에 대해 ulimit가 설정되어 있는지 확인합니다 (예: ulimit -c unlimited).  
  5. Linux에서는 기본적으로 코어 덤프가 오프되어 있습니다.  RedHat Advanced Server 2.1에서는 코어 파일이 /etc/security에 있고  limits.conf라는 파일이 있어야 합니다. 이 파일에서 설정 사항을 확인할 수 있습니다. "core"라는 단어를 찾아보십시오.  0으로 설정되어 있으면 coredump를 사용할 수 없습니다. 
  6. 참고 항목: 코어 파일 생성을 위해 검사해야 할 운영 체제 구성
  7. 다음과 같이 gdb를 사용하여 스택 트레이스를 가져옵니다(이전 과정과 동일).

$ java -version  (need to use right version of jdk)
$ ls /usr/local/bin/gdb (need to know gdb location) or "which gdb"
$ export DEBUG_PROG=/usr/local/bin/gdb  (or wherever "gdb" is located)

For JDK 1.3.X do the following:
   $ <path to java command>/java corefile
For JDK 1.4.X do the following:
   $ gdb <path to java command>/java corefile


Now you will be in the debugger.  Execute the following commands:
(gdb) where        ("shows a summary of the stack")
(gdb) thr    ("switch among threads or show the current thread")
(gdb) info thr        ("inquire about existing threads")
(gdb) thread apply 1 bt    ("apply a command to a list of threads, specifically the backtrace to thread #1")
(gdb) quit


where 명령을 사용하면 실행된 마지막 스레드의 스택 트레이스가 생성되고, thr 명령을 사용하면 현재 스레드가 표시되고, info thr 명령을 사용하면 모든 스레드의 상태가 표시되고, thread apply 1 bt 명령을 사용하면 코어 파일에 포함된 스레드 1의 스택 트레이스를 다른 방식으로 가져올 수 있습니다.  마지막 명령 thread apply # bt에서 #을 실제 스레드 번호로 바꾸어 개별 스레드의 스택 트레이스를 가져오거나 3을 "all"로 바꾸어 모든 스레드의 스택 트레이스를 가져올 수 있습니다.

페이지 맨 위

HPUX 운영체제에서 코어 정보 수집
일반적으로 사용되는 명령줄 디버거는 GDB 및 ADB입니다.
  GDB:
    gdb를 사용할 수 있고 아래와 같은 사항이 제공되는 경우 이전과 동일한 과정을 따릅니다.


$ java -version  (need to use right version of jdk)
$ ls /usr/local/bin/gdb (need to know gdb location) or "which gdb"
$ export DEBUG_PROG=/usr/local/bin/gdb  (or wherever "gdb" is located)

For JDK 1.3.X do the following:
   $ <path to java command>/java corefile
For JDK 1.4.X do the following:
   $ gdb <path to java command>/java corefile


Now you will be in the debugger.  Execute the following commands:
(gdb) where        ("shows a summary of the stack")
(gdb) thr    ("switch among threads or show the current thread")
(gdb) info thr        ("inquire about existing threads")
(gdb) thread apply 1 bt    ("apply a command to a list of threads, specifically the backtrace to thread #1")
(gdb) quit


ADB:
    다음 과정을 수행하여 스택 트레이스를 가져올 수 있습니다.


    $ java -version  (need to use right version of jdk)
    $ ls /usr/local/bin/adb (need to know adb location) or "which adb"
    $ export DEBUG_PROG=/usr/local/bin/adb (or wherever "adb" is located)
    $ <path to java command>/java corefile

    Now you will be in the debugger.  Execute the following commands:
    adb> $C        ("shows a summary of the stack and you may get an error at this point, see below")
    adb> $r            ("shows the state of the registers")
    adb> $q        ("the command to quit adb")

adb에서 $C 명령을 실행할 때 "can't unwind -- no_entry"와 같은 메시지가 나타나면 대부분 adb가 공유 라이브러리를 인식하지 못하는 경우입니다.  이러한 경우에는 gdb나 wdb를 사용하는 것이 좋습니다.  WDB는   http://h21007.www2.hp.com/dspp/tech/tech_TechSoftwareDetailPage_IDX/1,1703,1665,00.html에서 구할 수 있습니다.

페이지 맨 위

AIX 운영체제에서 코어 정보 수집

  1. gdb를 사용할 수 있고 실제 바이너리 코어 파일이 생성되는 경우 이전과 동일한 과정을 따릅니다.

$ java -version  (need to use right version of jdk)
$ ls /usr/local/bin/gdb (need to know gdb location) or "which gdb"
$ export DEBUG_PROG=/usr/local/bin/gdb  (or wherever "gdb" is located)

For JDK 1.3.X do the following:
   $ <path to java command>/java corefile
For JDK 1.4.X do the following:
   $ gdb <path to java command>/java corefile


Now you will be in the debugger.  Execute the following commands:
(gdb) where        ("shows a summary of the stack")
(gdb) thr    ("switch among threads or show the current thread")
(gdb) info thr        ("inquire about existing threads")
(gdb) thread apply 1 bt    ("apply a command to a list of threads, specifically the backtrace to thread #1")
(gdb) quit


  1. 그러나 AIX에서 JVM은 대개 응용 프로그램 디버깅용으로 javacore<PID>.<ID Number>.txt 파일을 출력합니다.  이 파일에는 매우 유용한 정보가 포함되어 있으며 코어가 발생했을 때 실행 중이던 현재 스레드를 보여줍니다.  예를 들어, 다음은 사용자가 생성한 displayHelloWorld() native 메서드에서 발생한 문제를 알려줍니다.  코어 발생 원인을 파악하려면 해당 native 코드를 살펴보십시오.
javacore<PID>.<ID Number>.txt 파일의 샘플 정보:

Current Thread Details:
"ExecuteThread: '10' for queue: 'default'" (TID:0x31c70ad0, sys_thread_t:0x3e52df68, state:R, native ID:0xf10) prio=5
    at HelloWorld.displayHelloWorld(Native Method)
    at servlets.NativeServlet.doGet(NativeServlet.java:85)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:740)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
    at weblogic.servlet.internal.ServletStubImpl$ServletInvocationAction.run(ServletStubImpl.java:1058)
    at weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:401)
    at weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:306)
    at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:5445)
    at weblogic.security.service.SecurityServiceManager.runAs(SecurityServiceManager.java:780)
    at weblogic.servlet.internal.WebAppServletContext.invokeServlet(WebAppServletContext.java:3105)
    at weblogic.servlet.internal.ServletRequestImpl.execute(ServletRequestImpl.java:2588)
    at weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:213)
    at weblogic.kernel.ExecuteThread.run(ExecuteThread.java:189)

  1. Current Thread Details에서 문제의 원인을 찾을 수 있습니다.  예를 들어, 다음은 ExecuteThread 24에서 코어가 생성되었지만 그 당시에 JVM이 일부 JIT를 실행 중이었음을 보여줍니다.  따라서 IBM의 이 JVM 버전에서 JIT 컴파일러에 문제가 있는 것 같습니다.

Current Thread Details
    "ExecuteThread: '24' for queue: 'default'" sys_thread_t:0x781
        Native Stack
          at 0xD0F15924 in get_invoke_op
          at 0xD0F1535C in resolve_a_method
          at 0xD0F1E610 in resolve_method_call_graph
          at 0xD0F29C40 in jit_compiler_entry
          at 0xD0F2A404 in _jit_fast_compile

페이지 맨 위

WINDOWS 운영체제에서 코어 정보 수집

  1. drwtsn32.log 파일은 Unix의 코어 파일과 유사합니다.  Windows 2000에서 이 파일은 다음 디렉토리에 있습니다. C:\Documents and Settings\All Users\Documents\DrWatson.  drwtsn32를 커맨드에서 실행하면 Windows 2000용 Dr. Watson이 나타납니다.  DrWatson 로그 파일 옵션은 drwtsn32.log 파일의 형식을 설명하는 화면을 표시합니다.
  2. 오류가 발생할 당시의 JVM에 대한 유용한 정보가 포함된hs_err_pid<#>.log가 생성되기도 합니다.

Dr. Watson 설정/해제:
기본적으로 Dr. Watson은 Windows NT를 설치할 때 설정됩니다. 

  1. 다음 레지스트리 키를 검사하여 Dr. Watson이 설정되어 있는지 여부를 확인할 수 있습니다(0=설정됨, 1=해제됨).
  \HKEY_LOCAL_MACHINE\SOFTWARE \Microsoft\Windows NT\CurrentVersion\AeDebug
  1. Dr. Watson의 시작 방법에 해당하는 "Auto"라는 항목이 있습니다.  이 항목은 Debugger 레지스트리 값에 있는 디버거나 응용 프로그램을 실행합니다. 
  2. Dr. Watson의 경우 Debugger 값에 다음 내용이 포함되어야 합니다.

drwtsn32 -p %ld -e %ld -g

페이지 맨 위

디버거가 없는 경우

  1. 디버거에 액세스할 수 없는 경우 운영 체제에 pstackpmap 유틸리티가 있는지 확인합니다. 
  2. 이러한 유틸리티가 있는 경우(일부 운영 체제는 이러한 유틸리티를 별도로 다운로드해야 함) 시스템 코어 파일에서 해당 명령을 실행하여 Support의 정보를 수집합니다. 

명령 구문은 다음과 유사합니다.   

    $ /usr/proc/bin/pstack core
    $ /usr/proc/bin/pmap core


다음은 운영 체제별 명령입니다.

    Solaris:
        pstack 명령 = pstack
        pmap 명령 = pmap

    IBM의 추가 기능이 있는 AIX 5.2 이상(이전 버전에서는 사용할 수 없음)
        pstack 명령 = procstack
        pmap 명령 = procmap
        참고: http://www-106.ibm.com/developerworks/eserver/articles/AIX5.2PerfTools.html

    Linux:
        pstack = lsstack
        pmap = pmap

        참고: http://sourceforge.net/projects/lsstack/에서 lsstack을 가져와서 Linux 플랫폼에서 빌드할 수 있습니다. 

 이 명령은 Solaris의 pstack에 해당합니다.

        http://web.hexapodia.org/~adi/pmap.c에서 pmap 소스를 가져와서 Linux 플랫폼에서 빌드할 수 있습니다.

    HPUX: (찾을 수 없음)

다음은 gdb/dbx 출력의 동일한 코어 파일에 나오는 pstackpmap 데이터의 코드 부분입니다.  이 코드를 사용하여 오류가 발생한 라이브러리의 범위를 좁힐 수 있습니다.  이 예제에서는 libhello.so에서 오류가 발생한 것이 분명합니다.

pstack 출력:


core 'core' of 20956:   /wwsl/sharedInstalls/solaris/wls70sp2/jdk131_06/bin/../bin/sparc/nativ
-----------------  lwp# 14 / thread# 25  --------------------
 ff369764 __sigprocmask (ff36bf60, 0, 0, e6181d70, ff37e000, 0) + 8
 ff35e110 _sigon   (e6181d70, ff385930, 6, e6180114, e6181d70, 6) + d0
 ff361150 _thrp_kill (0, 19, 6, ff37e000, 19, ff2c0450) + f8
 ff24b900 raise    (6, 0, 0, ffffffff, ff2c03bc, 4) + 40
 ff2358ec abort    (ff2bc000, e6180268, 0, fffffff8, 4, e6180289) + 100
 fe3c68fc __1cCosFabort6Fl_v_ (1, fe4c8000, 1, e61802e8, 0, e9f90420) + b8
 fe3c59f0 __1cCosbBhandle_unexpected_exception6FpnGThread_ipCpv_v_ (ff2c02ac, fe53895c, fe4dc164, fe470ab4, fe4c8000, e6180308) + 254
 fe20a8b4 JVM_handle_solaris_signal (0, 25d5b8, e6180d90, fe4c8000, b, e6181048) + 8ec
 ff36b824 __sighndlr (b, e6181048, e6180d90, fe20a8cc, e6181e14, e6181e04) + c
 ff3684d8 sigacthandler (b, e6181d70, 0, 0, 0, ff37e000) + 708
 --- called from signal handler with signal 11 (SIGSEGV) ---
 e9f90420 Java_HelloWorld_displayHelloWorld (25d644, e6181224, e61819b8, 0, 2, 0) + 30

 00090ae4 ???????? (e6181224, e61819b8, 25d5b8, fe4c8000, 0, 109a0)
 0008dc4c ???????? (e61812c4, ffffffff, ffffffff, 97400, 4, e61811b8)
 0008dc4c ???????? (e618135c, e61819b8, fe4c8000, 99600, c, e6181250)
 0008dc4c ???????? (e61813ec, f76a2f90, e618147c, 99600, c, e61812f8)
 0008ddb4 ???????? (e618147c, f68578b8, 0, 99974, c, e6181388)
 0008ddd8 ???????? (e618154c, e61815c8, e61815cc, 99974, 4, e6181410)

......

pmap 출력 코드 부분:


........
E9500000   1184K read
E9680000   1392K read
E9800000   4608K read
E9F60000    136K read/write/exec
E9F90000      8K read/exec         /home/usera/wls70/solaris/projectWork/lib/libhello.so
E9FA0000      8K read/write/exec   /home/usera/wls70/solaris/projectWork/lib/libhello.so

E9FB4000      8K read/write/exec
E9FC0000    120K read/exec         /usr/lib/libelf.so.1
E9FEE000      8K read/write/exec   /usr/lib/libelf.so.1

.......

pstack 출력에서 오류가 발생한 주소는 e9f90420입니다.  pmap 출력 코드 부분에서 e9f90420은 E9F90000-E9FA0000 사이이므로 libhello.so 공유 개체 내부에서 오류가 발생했습니다.

페이지 맨 위


코어 파일 생성을 위해 검사해야 할 운영 체제 구성

  1. 시스템 또는 사용자 별 ulimit -c(코어 파일의 설정된 크기)를 검사합니다.
  2. 사용 가능한 사용자 디스크 공간을 검사합니다(예: 디스크 할당량이 있습니까?)
  3. Solaris에서는 /etc/system 파일에 다음 매개변수가 있는데 이 값에 따라 코어 파일이 생성되지 않을 수 있습니다. set sys:coredumpsize=0
  4. Linux에서는 기본적으로 코더 덤프가 오프로 있습니다.  RedHat Advanced Server 2.1에서는 구성 정보 파일이 /etc/security에 있습니다.  limits.conf라는 파일에서 설정 사항을 확인할 수 있습니다. "core"라는 단어를 찾아보십시오.  0으로 설정되어 있으면 coredump를 만들 수 없습니다.
  5. HP OS 설정 커널 매개변수 maxdsiz(max_per_proc_data_size는 사용자 프로세스의 데이터 세그멘트 크기를 늘림) 64M에서 134M 이상으로 변경합니다.

페이지 맨 위

JVM을 중지하여 스레드 덤프 가져오기
다음 플래그를 설정하여 코어가 해당 순간의 스레드 상태를 가져오기 직전에 서버의 스레드 덤프를 가져오도록 할 수 있습니다.

Sun JVM
이 옵션은 SUN JVM에서 -XX:+ShowMessageBoxOnError입니다. (이 옵션은 SUN 웹 사이트에서 공식적으로 설명되어 있지 않습니다.)  JVM이 크래시되면 프로그램은 다음과 같은 메시지를 표시합니다. Do you want to debug the problem?  그러면 JVM의 스레드 덤프를 가져올 수 있습니다. 

JRockit JVM
이와 동일한 기능의 옵션은 서비스팩 8.1 SP2 버전에 포함된 JRockit에서부터 사용할 수 있습니다.  JRockit의 옵션은   -Djrockit.waitonerror입니다.

페이지 맨 위


온라인 디버거 설명서

다음과 같이 코어 파일 분석에 사용되는 디버거에 대한 설명서를 구할 수 있습니다.

페이지 맨 위

추가 도움말이 필요하십니까?

패턴대로 작업했지만 추가 도움말이 필요한 경우 다음과 같이 할 수 있습니다.

  1. http://support.bea.com의 AskBEA에서 "core file"로 문제를 조회하여 게시된 다른 해결 방법을 찾아봅니다.
  2. http://newsgroups.bea.com 사이트에서 BEA 뉴스그룹에 대한 보다 자세한 내용을 질문합니다.

이렇게 해도 문제를 해결할 수 없는 경우 유효한 유지보수 계약이 되어 있다면 http://support.bea.com/에 로그인하여 Support Case를 신청할 수 있습니다.

'IT > Tips' 카테고리의 다른 글

mysql 기본 명령어  (0) 2007.01.15
Linux 한글 깨질때  (0) 2007.01.15
awk, sed  (0) 2007.01.15
diff, patch, cvs  (0) 2007.01.15
Shell programming  (0) 2007.01.15