如何在 IBM i 上分析 J9 虚拟机崩溃问题

本文有针对性地介绍了 IBM i 上 J9 JVM 崩溃的上 J9 JVM 崩溃的常见原因,并介绍了在 IBM i 上如何利用 vlog, joblog, core dump -Xcheck:jni 等日志分析 JVM 崩溃问题。

张 大伟, 软件工程师, IBM

张大伟,软件工程师。2009 至 2012 年负责在 IBM i 上 J9 VM 的开发和技术支持工作。同时在电信业务,移动 IP 与类 Unix 平台开发方面有较多经验。



相 云, 高级软件工程师, IBM

相云,高级软件工程师。负责 IBM i 上 Java 类库的开发与技术支持。



高 山, 高级软件工程师, IBM

高山,高级软件工程师。负责 IBM i 上 Java 类库的开发与技术支持。



2013 年 7 月 04 日

J9 JVM 简介

IBM Technology for Java(IT4J,又名 J9) 是 IBM 自己开发的 Java 虚拟机,被发布在 IBM 的各个操作系统上。IBM i 从 5.4 版本中开始引入 J9,从 6.1 开始,系统默认的 Java 虚拟机 是 J9,从 7.1 开始,Classic JVM 不再被支持,J9 是 IBM i 上唯一的支持的 Java 虚拟机。

在 IBM i 上 ,PASE(Portable Application Solution Environment) 提供了一个仿 AIX 的运行时环境,使得 AIX 或 其他 UNIX/Linux 应用程序只要做很少的改动甚至不修改就能够在 IBM i 上运行。J9 在 IBM i 上发布的核心代码是 AIX 版本的,所以它是在 PASE 环境中运行的。另外,J9 在 IBM i 上还有虚拟机的启动,停止与管理等功能。这些是通过 IBM i 的 CL 命令界面和少量的 ILE 支撑程序来实现的。所以与 Classic JVM 不同,在 IBM i 上调试与解决 J9 的问题需要从 ILE 和 PASE 两个环境同时入手分析。


J9 产生的几种日志

当运行在 J9 上的 Java 应用程序出现问题时,最有效的分析问题方法是查看 J9 产生的各种日志。J9 通常会共产生 core dump, java core,snap trace 和 heap dump 四种日志。

Core dump 就是 Unix 或 Linux 系统上的内存转储文件,主要包括 J9 崩溃时的内存映像。

Java core 文件保存的是 java 应用程序在崩溃时或任一时刻关于 Java 运行环境的各种信息。包括 Java 虚拟机的参数,环境变量,内存段的分配情况,垃圾回收日志,各种内部锁的状态,各线程在当前时刻的运行栈,以及类加载状态等。

Snap trace 是 J9 记录 Java 虚拟机自身运行过程的日志,通常在 J9 崩溃时 Snap trace 中会包含崩溃前的部分日志。

Heap dump 文件是一个二进制文件,它保存了某一时刻在 Java 堆中所有对象的状态。这个文件最重要的作用就是分析 Java 堆内存泄露问题,heap analyzer,MAT 等工具都可以分析这种文件。

除了以上几种日志以外,当 J9 崩溃时,相应的会产生 IBM i 的日志:joblog 和 vlog。


导致 J9 崩溃的原因分析

Java 虚拟机非正常地停止运行可能是多种原因引起的,例如 Java 程序产生了无法处理的异常,虚拟机运行过程中产生不可恢复的错误,虚拟机所在的进程崩溃等。对于 Java 异常和虚拟机内部产生的错误,一般会有对应的错误消息指示发生了哪种问题,相对容易找到问题的根源。而对于虚拟机崩溃问题相对比较复杂。崩溃通常由以下几种原因产生:

在与 JNI 相关的本地代码中崩溃

JNI 是 Java Native Interface 的缩写,即 JAVA 本地调用。从 Java1.1 开始,Java Native Interface(JNI) 标准成为 java 平台的一部分,它允许 Java 代码和其他语言写的代码进行交互。

本地代码在多种情况下都会用到 JNI。 而 JNI 的使用中有许多需要注意的问题(详见”使用 Java Native Interface 的最佳实践“)。这些本地代码对 JNI 不正确的使用往往会造成 J9 所在的 JOB 崩溃。使用 JNI 的方式包括:

Java 本地方法

在 IBM i 上一个 Java 方法可以用 ILE 或者 PASE 环境下的其他语言来实现。

使用 Invocation API

Invocation API 是 JNI 的一部分,它可以用来将 Java 虚拟机(JVM)嵌入到本机应用程序中,从而允许程序员从本机代码内部调用 Java 代码。同时也可以用其他语言通过 JNI 函数接口来调用 Java 代码。

JVMTI agent

JVMTI(JVM Tool Interface)是 Java 虚拟机所提供的本地编程接口,是 JVMPI(Java Virtual Machine Profiler Interface)和 JVMDI(Java Virtual Machine Debug Interface)的更新版本。JVMTI 提供了可用于 debug 和 profiler 的接口;同时也支持监听(Monitoring),线程分析(Thread analysis)以及覆盖率分析(Coverage Analysis)等功能。JVMTI 提供一套本地代码接口,因此使用 JVMTI 需要我们与 C/C++ 以及 JNI 打交道。开发时一般采用建立一个 Agent 的方式来使用 JVMTI,它使用 JVMTI 函数,设置一些回调函数,并从 Java 虚拟机中得到当前的运行态信息,并作出自己的判断,最后还可能操作虚拟机的运行态。把 Agent 编译成一个动态链接库之后,我们就可以在 Java 程序启动的时候来加载它(启动加载模式),也可以在 Java 5 之后使用运行时加载(活动加载模式)。

在 J9 内部崩溃

J9 自身也可能存在 bug,从而导致虚拟机崩溃。

其他与 J9 无关的本地代码崩溃

IBM i 引入 Java 虚拟机后,许多程序通过增加 Java 代码来实现新功能。原有功能仍然由本地代码实现。这些本地代码中可能存在对内存的直接访问 ( 如 C/C++ 代码 ),不正确的指针访问可能导致 JVM 崩溃。

内存覆盖导致的崩溃

除了有可能造成直接崩溃以外,上面所提到的各种本地代码在对不正确的内存地址进行写入时,可能会覆盖正确的内存数据,从而导致后面访问了这些错误数据的代码崩溃。

收到异常信号

J9 内部安装了自己的信号处理函数,当收到某些信号比如 ABORT 时,J9 会产生 core dump 并使当前 JOB 退出。

本地内存耗尽

目前在 IBM i 上支持运行 32 位或 64 位的 J9 版本。对于 32 位的 J9 来说,由于地址模型的限制,J9 所使用的内存最多为 4GB。Java 堆以及本地内存都存放于这 4G 的地址空间中。当 Java 堆或本地内存地址耗尽时,一般情况下 J9 会抛出 java.lang.OutOfMemoryError 异常。但在本地内存不足时,有时也会造成 job 崩溃。例如创建线程或调用其他需要分配本地内存的 API 的时候。对于 64bit 的 J9,其地址空间达到 1 EB,因此一般没有地址空间耗尽的问题。仅在极少数情况下可能因系统物理内存不足导致问题。


查找导致 J9 崩溃的原因

对程序崩溃的问题,第一步应该首先检查崩溃时的程序运行栈。如果是在 ILE 代码中崩溃, 在 JOBLOG 中可能会产生代号为 MCH3601 或 MCH0601 的消息。例如

 MCH0601 Escape 40 06/28/11 09:33:31.391373 AM71021S16 
 QGPL *STMT AM71021S16 QGPL *STMT 
 From module . . . . . . . . : PLATFORM 
 From procedure . . . . . . : getPlatformTime 
 Statement . . . . . . . . . : 9 
 To module . . . . . . . . . : PLATFORM 
 To procedure . . . . . . . : getPlatformTime 
 Statement . . . . . . . . . : 9 
 Thread . . . . : 00004A06 
 Message . . . . : Space offset X'00000000' or X'0000FFFFFFFFFFFF'
  is outside 
 current limit for object SVCS2 QEJBSVR 599981. 
 Cause . . . . . : A program tried to set a space pointer, tried to use 
 storage outside a space, or tried to use an unallocated page in teraspace. 
 The space class is X'07'. The space class designates the type of space: 
 00-primary associated space (includes space objects). 01-secondary 
 associated space 0. 02-implicit process space for automatic storage. 
 03-implicit process space for static storage in activation group mark 
 X'0000000000000000'. 04-implicit process space for heap identifier 
 X'00000000' in activation group mark X'0000000000000000'. 05-constant space. 
 06-space for handle-based heap identifier X'00000000'. 07-teraspace offset 
 X'0000FFFFFFFFFFFF'. 08-teraspace for System i5 PASE memory address 
 X'0000FFFFFFFFFFFF'. Offset X'00000000' only applies to storage outside 
 teraspace. X'80000000000000000000FFFFFFFFFFFF' is a pointer to the teraspace 
 page or the start of the implicit process space for the allocation.

在 java core 里的当前线程部分可以看到错误发生的 Java 栈和本地栈。

 1XMCURTHDINFO Current thread 
 NULL ---------------------- 
 3XMTHREADINFO "test:1920" J9VMThread:0x00000000339FC500, 
 j9thread_t:0x0000000198A7AF80, java/lang/Thread:0x000000060AABDFB0, s
 tate:R, prio=10 
 3XMTHREADINFO1 (native thread ID:0x4D9005,
  native priority:0xA, native policy:UNKNOWN) 
 3XMTHREADINFO3 Java callstack: 
 4XESTACKTRACE at test/probe/testSystem.updatePlatformTime 
 (Native Method) 
 4XESTACKTRACE at test/probe/testSystem.getPlatformTime 
 (testSystem.java:896(Compiled Code)) 
 4XESTACKTRACE at test/probe/ProbeData.update 
 (ProbeData.java:125(Compiled Code)) 
 4XESTACKTRACE at test/kernel/util/JoinManager$JoinWorker.run 
 (JoinManager.java:249(Compiled Code)) 
 3XMTHREADINFO3 Native callstack: 
 4XENATIVESTACK getPlatformTime__FPv+0x1ec (0x09000000013A261C 
 [libam_ibm_16.a+0x2d61c]) 
 4XENATIVESTACK Java_test_probe_testSystem_updatePlatformTime+0x68 
 (0x09000000013E2F20 [libam_ibm_16.a+0x6df20]) 
 4XENATIVESTACK (0x00000001A4AC6EDC) 
 4XENATIVESTACK javaProtectedThreadProc+0xa8 (0x090000000068DE18
  [libj9vm24.so+0xce18]) 
 4XENATIVESTACK j9sig_protect+0x140 (0x0900000000734354
  [libj9prt24.so+0x2354]) 
 4XENATIVESTACK javaThreadProc+0x50 (0x090000000068DD24 
 [libj9vm24.so+0xcd24]) 
 4XENATIVESTACK thread_wrapper+0x12c (0x090000000071BEF0
  [libj9thr24.so+0x1ef0]) 
 4XENATIVESTACK _pthread_body+0x100 (0x09000000003CAD64 
 [libpthreads.a+0x3d64])

如果是在 PASE 代码中崩溃,则会产生如下的 MCH6801 和 MCH0601 的 joblog

 MCH6801 Escape 40 07/07/12 04:58:23.304330 < 
 000000 QP2USER2 QSYS *STMT 
 From Program . . . . . . . : tia_fault 
 To module . . . . . . . . . : QP2API 
 To procedure . . . . . . . : runpase_common__FiPvT2 
 Statement . . . . . . . . . : 5 
 Thread . . . . : 0005BABE 
 Message . . . . : Object domain or storage protection error for offset 
 X'0000000000000230' in object PRODV8 QEJBSVR 050365. 
 Cause . . . . . : A program tried to use a blocked instruction, access a 
 system domain object, or make invalid use of a protected page. The violation 
 type is 4. The violation type indicates the type of error: 1-Object domain 
 violation. 2-Test Pointer Target Addressability (TESTPTA) violation. 3-Read 
 protection error. 4-Write protection error. 5-Execute protection error. The 
 space class is X'08'. The space class designates the type of space for a 
 storage protection error or TESTPTA violation for a space pointer: 
 00-primary associated space (includes space objects). 01-secondary 
 associated space. 02-implicit process space for automatic storage. 
 03-implicit process space for static storage. 04-implicit process space for 
 activation group-based heap storage. 05-constant space. 06-space for 
 handle-based heap storage. 07-teraspace offset X'0000000000000230'. 
 08-teraspace for i5/OS PASE memory address X'0000000000000230'. 
 X'800000000000000000000401A0000230' is a pointer to the storage for a 
 protection error or TESTPTA violation for a space pointer. Some violations 
 may be suppressed at low system security levels.
 MCH0601 Escape 40 03/17/11 13:20:42.655544 < 
 000000 QP2USER2 QSYS *STMT 
 From Program . . . . . . . : tia_fault 
 To module . . . . . . . . . : QP2API 
 To procedure . . . . . . . : runpase_common__FiPvT2 
 Statement . . . . . . . . . : 2 
 Thread . . . . : 0000006F 
 Message . . . . : Space offset X'00000000' or X'00000000FFFFFFFE' is outside 
 current limit for object HTTP QNOTES 220860. 
 Cause . . . . . : A program tried to set a space pointer, tried to use 
 storage outside a space, or tried to use an unallocated page in teraspace. 
 The space class is X'08'. The space class designates the type of space: 
 00-primary associated space (includes space objects). 01-secondary 
 associated space 0. 02-implicit process space for automatic storage. 
 03-implicit process space for static storage in activation group mark 
 X'0000000000000000'. 04-implicit process space for heap identifier 
 X'00000000' in activation group mark X'0000000000000000'. 05-constant space. 
 06-space for handle-based heap identifier X'00000000'. 07-teraspace offset 
 X'00000000FFFFFFFE'. 08-teraspace for System i5 PASE memory address 
 X'00000000FFFFFFFE'. Offset X'00000000' only applies to storage outside 
 teraspace. X'8000000000000000000080010FFFFFFE' is a pointer to the teraspace 
 page or the start of the implicit process space for the allocation.

在这两个 JOBLOG 中,由于错误是发生在 PASE 环境里,所以只能看到错误产生于 runpase_common 函数。详细的 PASE 的崩溃栈需要从 core dump, vlog 或 javacore 中得到。当 PASE 崩溃时会产生编号为 4700 0012 的 vlog。下面是一个 vlog 里显示的崩溃栈:类型为 4700 0012。

 DUMP FOR ENTRY ID 0101A304 TYPE 4700 (i5/OS PASE) 0012
  DUMP SIZE 006B92 TIME STAMP 24/01/12 09:09:28 
 ISF=31FA8060 TS=800041FA8060 NIA=D0618EE8 J9DUMP_CREATE+0X190 
 ISF=31FA84F0 TS=800041FA84F0 NIA=D06AF8A8 DOSYSTEMDUMP+0XB0 
 ISF=31FA8750 TS=800041FA8750 NIA=D06B3118 PROTECTEDDUMPFUNCTION+0X24 
 ISF=31FA8790 TS=800041FA8790 NIA=D0617300 J9SIG_PROTECT+0X14C 
 ISF=31FA8910 TS=800041FA8910 NIA=D06B2FF0 RUNDUMPFUNCTION+0X44 
 ISF=31FA8970 TS=800041FA8970 NIA=D06B2EBC RUNDUMPAGENT+0X2D8 
 ISF=31FA8E10 TS=800041FA8E10 NIA=D06C62EC TRIGGERDUMPAGENTS?AF32_14+0X328 
 ISF=31FA90C0 TS=800041FA90C0 NIA=D06C4FDC TRIGGERDUMPAGENTS+0X1C 
 ISF=31FA9100 TS=800041FA9100 NIA=D05A02E4 DUMPCRASHDATA+0X214 
 ISF=31FAA170 TS=800041FAA170 NIA=D0617300 J9SIG_PROTECT+0X14C 
 ISF=31FAA2F0 TS=800041FAA2F0 NIA=D059FEB0 STRUCTUREDSIGNALHANDLER+0XCC 
 ISF=31FAA360 TS=800041FAA360 NIA=D0617DC8 MASTERSYNCHSIGNALHANDLER+0X184 
 ISF=31FAB1F0 TS=800041FAB1F0 NIA=00003680 <SIGREDRIVE> 
 ...

MASTERSYNCHSIGNALHANDLER 是 J9 内部的信号处理函数,当 J9 崩溃时它会调用 J9DUMP_CREATE 生成 core dump。

接下来列出的是触发崩溃的函数栈:

 ISF=31FAB610 TS=800041FAB610 NIA=D083C9F8 __CT__10TR_CFGEDGEFP10TR_CFGNODET117TR
 _ALLOCATIONKIND+0X78 
 ISF=31FAB660 TS=800041FAB660 NIA=D083ECF8 ADDEDGE__6TR_CFGFP10TR_CFGNODET117TR
 _ALLOCATIONKIND+0X78 
 ISF=31FAB6C0 TS=800041FAB6C0 NIA=D083F19C ADDSUCCESSOREDGES__6TR_CFGFP8TR_BLOCK+0X10C 
 ISF=31FAB720 TS=800041FAB720 NIA=D083F490 INSERTBEFORE__6TR_CFGFP8TR_BLOCKT1+0X34 
 ISF=31FAB770 TS=800041FAB770 NIA=D08D51C0 WALKER__14TR_ILGENERATORFP8TR_BLOCK+0X540 
 ISF=31FAB800 TS=800041FAB800 NIA=D08E6610 GENEXCEPTIONHANDLERS__14TR
 _ILGENERATORFP8TR_BLOCK+0X8A4 
 ISF=31FAB8C0 TS=800041FAB8C0 NIA=D08E4A5C GENILFROMBYTECODES__14TR_ILGENERATORFV+0X9C8 
 ISF=31FAB950 TS=800041FAB950 NIA=D08E3850 INTERNALGENIL__14TR_ILGENERATORFV+0X2BC 
 ISF=31FAB9B0 TS=800041FAB9B0 NIA=D08E352C GENIL__14TR_ILGENERATORFV+0X34

从崩溃栈中可以初步判断产生 J9 崩溃问题的原因,首先根据崩溃栈可以判断是否是 JVM 收到了异常信号,随后通过代码分析来查找引起崩溃的初始原因。一般来说如果多次出现不同的崩溃栈,应该考虑是否为本机内存耗尽或内存覆盖的问题。先根据 JVM 内存使用情况可以排查判断本机内存是否已经耗尽。如果本机内存没有耗尽,可以逐一尝试下列选项来检查是否存在某种原始错误导致了最后的内存覆盖问题。

“-Xcheck:jni”

J9 JVM 提供了一个非常有用的选项 “-Xcheck:jni”,用来检查 JNI 调用中的错误:

 java -Xcheck:jni:help QIBMHello 

 jnichk - JNI Check utility for J9, Version 2.4 
 (c) Copyright IBM Corp. 1991, 2011 All Rights Reserved 
 Usage: -Xcheck:jni:[option[,option[,...]]] 
 all check application and system classes 
 verbose trace certain JNI functions and activities 
 trace trace all JNI functions 
 nobounds do not perform bounds checking on strings and arrays 
 nonfatal do not exit when errors are detected 
 nowarn do not display warnings 
 noadvice do not display advice 
 novalist do not check for va_list reuse 
 valist check for va_list reuse 
 pedantic perform more thorough, but slower checks 
 help print this screen 
 Unable to create Java Virtual Machine.

首先利用"-Xcheck:jni:all,trace,valist,pedantic,nowarn,nonfatal"

(jdk626 和 jdk70 中使用"-Xcheck:jni:all,trace,advice,valist,pedantic,nonfatal"), 可以将 JNI 调用过程中产生的日志和错误打印出来。 这个选项可能会发现多个 JNI 使用的错误,而第一个 JNI 错误很可能是引起后面连续多个错误,乃至最后导致内存覆盖的原因。然后可以使用

"-Xcheck:jni:all,trace,valist,pedantic,nowarn" 以及 "-Xdump:system+java:events=vmstop"选项再次复现错误,这个选项使 JNI 发现第一个错误时就停止 J9 运行,同时产生 core dump 和 java dump(即使这时程序没有崩溃),从而帮助定位出错的代码行。下面是打印到标准错误输出的 JNI 信息,表明在调用 JNI 函数 DeleteLocalRef 时输入了不正确的参数。

 JVMJNCK001I JNI check utility installed. Use -Xcheck:jni:help for usage 
 JVMJNCK037E JNI error in DeleteLocalRef: Argument #2 (0x339d0b4c) is not a 
 local reference. Its type is: unknown 
 JVMJNCK080E Error detected in the outermost frame of an attached thread 
 JVMJNCK024E JNI error detected. Aborting. 
 JVMJNCK025I Use -Xcheck:jni:nonfatal to continue running when errors are detected. 
 Fatal error: JNI error 
 JVMDUMP039I Processing dump event "vmstop", detail "#00000457" 
 at 2012/04/24 06:31:33 - please wait. 
 JVMDUMP032I JVM requested System dump using 
'/NOTES/DATA/core.20120424.063133.781.0001.dmp' in response to an event 
 JVMDUMP010I System dump written to /NOTES/DATA/core.20120424.063133.781.0001.dmp 
 JVMDUMP032I JVM requested Java dump using 
'/NOTES/DATA/javacore.20120424.063133.781.0002.txt' in response to an even 
 JVMDUMP010I Java dump written to /NOTES/DATA/javacore.20120424.063133.781.0002.txt 
 JVMDUMP013I Processed dump event "vmstop", detail "#00000457".

环境变量 QIBM_XJ9_TRACE 以及 QIBM_XJ9_TRACE_FILE

使用这两个环境变量会打开 IBM i J9 代码中的日志。在 CL 命令行界面使用 ADDENVVAR,或者在 QSH 下使用 export 来设置它们。其中 %PID 代表文件名中的进程号。

 ADDENVVAR ENVVAR(QIBM_XJ9_TRACE) VALUE(ALL) 
 ADDENVVAR ENVVAR(QIBM_XJ9_TRACE_FILE) VALUE('/tmp/xj9trace_%PID.txt') 
 export QIBM_XJ9_TRACE=ALL 
 export QIBM_XJ9_TRACE_FILE=/tmp/xj9trace_%PID.txt

"-Xcheck:memory"

"-Xcheck:memory"( 在 jdk50 中是"-memorycheck") 是一个 J9 虚拟机的选项。用来检查 JVM 内部的内存使用是否存在泄漏问题。

MALLOCDEBUG

这是一个 AIX 以及 PASE 上 MALLOC 子系统支持调试的环境变量,支持很多的调试选项。

MALLOCDEBUG =

Align:n n 是内存对齐的数值。

catch_overflow 用来检查读写覆盖问题。

postfree_checking 使 MALLOCDEBUG 报告对已释放的内存进行访问的尝试,然后中止该程序。

validate_ptrs 如果向 free() 调用传递的指针并不是以前由 malloc 分配的,那么将会引发一个错误消息,而该程序将被中止。

allow_overreading 将忽略读取越界。

continue 继续报告错误,但它并不异常终止 (ABEND) 该程序。这是 AIX Version 5.3 中提供的一种非常有用的特性。

stack_depth:n stack_depth:n 将错误堆栈报告到第 n 层,而不是缺省的第 6 层。

report_allocations 检查内存泄漏。

override_signal_handling 当 MALLOCDEBUG 检测到内存错误,它会强迫该程序使用 SIGSEGV 或 SIGABRT 进行核心转储。设置 override_signal_handling 可以确保该程序终止并进行核心转储,即使应用程序已经对这些信号进行了处理。

对 JVM 崩溃问题可以采用以下的 MALLOCDEBUG 设置 :

 MALLOCDEBUG=align:2,catch_overflow,postfree_checking,
 validate_ptrs,output:/tmp/j9log.txt,continue

参考资料

学习

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=IBM i
ArticleID=936608
ArticleTitle=如何在 IBM i 上分析 J9 虚拟机崩溃问题
publish-date=07042013