一,背景
当我们运行的WebLogic JVM发生Fatal Error时,会造成JVM crash掉,进而造成进程终止。一般来说crash的时间我们是无法估计在什么时候的,它具有很大的偶然性,因此理论上有时我们希望自动产生Core dump文件来提供我们事后分析的信息记录。默认我们的系统是没有enable这个功能的,因此我们可以尝试开启。
1.1 core dump说明
core文件简介
core文件其实就是内存的映像,当程序崩溃时,存储内存的相应信息,主用用于对程序进行调试。当程序崩溃时便会产生core文件,其实准确的应该说是core dump 文件,默认生成位置与可执行程序位于同一目录下,文件名为core.***,其中***是某一数字。
核心转储(core dump),在汉语中有时戏称为吐核,是操作系统在进程收到某些信号而终止运行时,将此时进程地址空间的内容以及有关进程状态的其他信息写出的一个磁盘文件。这种信息往往用于调试。当一个进程要异常终止时,可以选择把进程的用户空间内存数据全部保存到磁盘上,文件名通常是core,这叫做Core Dump。进程异常终止通常是因为程序错误,比如非法内存访问导致段错误, 事后可以用调试器检查core文件以查清错误原因,这叫做Post-mortem Debug(事后调试)。
一个进程允许 产生多大的core文件取决于进程的Resource Limit(这个信息保在PCB中)。默认是不允许产生core文件的, 因为core文件中可能包含用户密码等敏感信息,不安全。在开发调试阶段可以用ulimit命令改变这个限制,允许产生core文件。
一个core文件里,包含了程序运行时的内存,寄存器状态,堆栈指针,内存管理等信息,也就是把程序当时工作的状态存储成一个文件。不仅仅是在出错的时候会生成core dump文件,在系统卡住或者cpu使用率很高的时候也可以手动触发生成core dump文件。
1.2 手动模拟crash
Kill -11 <PID>
信号11(SIGSEGV)是当一个进程执行了一个无效的内存引用,或发生段错误时发送给它的信号。
二,开启JVM crash自动产生Java core dump
2.1 测试环境:
OS: Red Hat Enterprise Linux Server release 6.7 (Santiago)
WebLogic Server 版本: 12.2.1.2.0
2.2 开启JVM crash自动产生Java core dump
core dump文件生成开关其实是通过对生成的文件大小进行控制达到的,默认大小是0,也就是说默认是不生成core dump文件的,可以通过命令ulimit -c进行查看。将此参数修改成unlimited就可以生成core dump文件了,但值得注意的一点是,每个应用进程都会读取自己的一套系统参数,可以查看进程对应的内存文件/proc/<pid>/limits中的信息来判断修改后的参数值是否对此应用进程生效了,limits文件中的信息如下:
查看core文件生成功能是否打开,如下若是0,则表示没有打开。
$ ulimit -c
0
修改为可以生成core dump文件:
1)临时设置
示例1:如下设置4G,单位为kbyte。
如果生成的信息超过此大小,将会被裁剪,最终生成一个不完整的core文件。在调试此core文 件的时候,gdb会提示错误。
# ulimit -c 4194304
示例2:不限制大小。
$ ulimit -c unlimited
$ ulimit -c
unlimited
2)永久设置
# echo " * soft core unlimited" >> /etc/security/limits.conf
# echo " * hard core unlimited" >> /etc/security/limits.conf
然后重启服务器或重新登录即可生效。
查看具体应用进程的core dump参数设置:
$ ps -ef |grep Server1
weblogic 13463 13412 99 01:40 ? 00:00:34 /usr/java/jdk1.8.0_144/bin/java -server -Xms256m -Xmx512m -Dweblogic.Name=Server1 -Djava.security.policy=/home/weblogic/Oracle/Middleware/Oracle_Home/wlserver/server/lib/weblogic.policy -Dweblogic.ProductionModeEnabled=true -Dweblogic.system.BootIdentityFile=/home/weblogic/Oracle/Middleware/Oracle_Home/user_projects/domains/base_domain/servers/Server1/data/nodemanager/boot.properties -Dweblogic.nodemanager.ServiceEnabled=true -Dweblogic.nmservice.RotationEnabled=true -Djava.system.class.loader=com.oracle.classloader.weblogic.LaunchClassLoader -javaagent:/home/weblogic/Oracle/Middleware/Oracle_Home/wlserver/server/lib/debugpatch-agent.jar -da -Dwls.home=/home/weblogic/Oracle/Middleware/Oracle_Home/wlserver/server -Dweblogic.home=/home/weblogic/Oracle/Middleware/Oracle_Home/wlserver/server -Dweblogic.management.server=http://127.0.0.1:7001 -Dweblogic.ext.dirs=/home/weblogic/Oracle/Middleware/Oracle_Home/user_projects/domains/base_domain/ext_lib weblogic.Server
weblogic 13546 12140 0 01:41 pts/1 00:00:00 grep Server1
$ cd /proc/13463
$ cat limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 8388608 unlimited bytes
Max core file size unlimited unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 1024 38877 processes
Max open files 4096 4096 files
Max locked memory 65536 65536 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 38877 38877 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
Hard Limit和Soft Limit的区别:
-H :hard limit ,严格的设定,必定不能超过这个设定的数值
-S :soft limit ,警告的设定,可以超过这个设定值,但是若超过则有警告信息
在设定上,通常soft会比hard小,举例来说,soft可以设置为80,而hard设定为100,那么你可以使用到90(没有超过100),但介于80~100之间时,系统会有警告信息通知你。
2.3 测试产生core file
通过kill -11 <PID>命令模拟Server1 服务器Crash掉了。
这时查看WebLogic域目录,产生了core文件:
我们看到此文件是比较大的有760MB,如果是生产环境,JVM内存可能更大,超过10GB的情况都有可能。这对磁盘空间是很大的开销。
查看相应的日志记录:
After file rotation: ServerLog-0 /home/weblogic/Oracle/Middleware/Oracle_Home/user_projects/domains/base_domain/servers/Server1/logs/Server1.log to /home/weblogic/Oracle/Middleware/Oracle_Home/user_projects/domains/base_domain/servers/Server1/logs/Server1.log00081
Realigning 0 iterators for: ServerLog-0
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00000030716082fb, pid=3342, tid=0x00007f2eecc29700
#
# JRE version: Java(TM) SE Runtime Environment (8.0_144-b01) (build 1.8.0_144-b01)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.144-b01 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# C [libpthread.so.0+0x82fb] pthread_join+0x10b
#
# Core dump written. Default location: /home/weblogic/Oracle/Middleware/Oracle_Home/user_projects/domains/base_domain/core or core.3342
#
# An error report file with more information is saved as:
# /home/weblogic/Oracle/Middleware/Oracle_Home/user_projects/domains/base_domain/hs_err_pid3342.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
#
/home/weblogic/Oracle/Middleware/Oracle_Home/user_projects/domains/base_domain/bin/startWebLogic.sh: line 197: 3342 Aborted (core dumped) ${JAVA_HOME}/bin/java ${JAVA_VM} ${MEM_ARGS} -Dweblogic.Name=${SERVER_NAME} -Djava.security.policy=${WLS_POLICY_FILE} ${JAVA_OPTIONS} ${PROXY_SETTINGS} ${SERVER_CLASS}
Stopping Derby server...
Derby server stopped.
<Nov 26, 2022 2:08:18 AM CST> <INFO> <NodeManager> <The server 'Server1' with process id 3288 is no longer alive; waiting for the process to die.>
<Nov 26, 2022 2:08:18 AM CST> <FINEST> <NodeManager> <Process died.>
<Nov 26, 2022 2:08:18 AM CST> <FINEST> <NodeManager> <get latest startup configuration before deciding/trying to restart the server>
<Nov 26, 2022 2:08:18 AM CST> <FINEST> <NodeManager> <caught exception attempting to save state: java.io.IOException: No space left on device>
<Nov 26, 2022 2:08:18 AM CST> <SEVERE> <NodeManager> <Unexpected error while monitoring server>
java.io.IOException: No space left on device
说明:本地磁盘空间不够了。
at sun.nio.ch.FileDispatcherImpl.write0(Native Method)
at sun.nio.ch.FileDispatcherImpl.write(FileDispatcherImpl.java:60)
at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
at sun.nio.ch.IOUtil.write(IOUtil.java:65)
at sun.nio.ch.FileChannelImpl.write(FileChannelImpl.java:205)
at weblogic.nodemanager.util.ConcurrentUnixFile.write(ConcurrentUnixFile.java:43)
at weblogic.nodemanager.common.StateInfoWriter.writeStateInfo(StateInfoWriter.java:46)
at weblogic.nodemanager.common.StateInfo.save(StateInfo.java:187)
at weblogic.nodemanager.server.ServerMonitor.saveStateFile(ServerMonitor.java:602)
at weblogic.nodemanager.server.ServerMonitor.runMonitor(ServerMonitor.java:576)
at weblogic.nodemanager.server.ServerMonitor.run(ServerMonitor.java:476)
at java.lang.Thread.run(Thread.java:745)
<Nov 26, 2022 2:08:18 AM CST> <FINEST> <NodeManager> <runMonitor returned, setting finished=true and notifying waiters>
<Nov 26, 2022 2:08:54 AM CST> <FINEST> <NodeManager> <previous state saving failed, need to rebuild the state file>
三,关闭JVM crash自动产生Java core dump
正如开篇所诉,为了节省disk空间,很多时候我们并不希望产生core dump文件。那么可以尝试禁止掉。
3.1修改ulimit参数
临时:如果只是临时禁止
$ ulimit -c 0
$ ulimit -c
0
永久:如果要永久禁止
[root@goya ~]# echo " * soft core 0" >> /etc/security/limits.conf
[root@goya ~]# echo " * hard core 0" >> /etc/security/limits.conf
[root@goya ~]# tail /etc/security/limits.conf
......
# End of file
* soft core 0
* hard core 0
然后重启服务器或重新登录即可生效
[weblogic@goya ~]$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
......
3.2 测试不产生core file
1) 查看WebLogic的测试被管节点的core参数设置。
2)通过kill -11 <PID>命令模拟Server1 服务器Crash掉。
[weblogic@goya 3375]$ kill -11 3375
如上图所示,没有core.3375文件产生。只有一个An error report 文件产生。
3)查看相应的日志记录
[weblogic@goya logs]$ pwd
/home/weblogic/Oracle/Middleware/Oracle_Home/user_projects/domains/base_domain/servers/Server1/logs
[weblogic@goya logs]$ view Server1.out00009
......
After file rotation: ServerLog-0 /home/weblogic/Oracle/Middleware/Oracle_Home/user_projects/domains/base_domain/servers/Server1/logs/Server1.log to /home/weblogic/Oracle/Middleware/Oracle_Home/user_projects/domains/base_domain/servers/Server1/logs/Server1.log00095
Realigning 0 iterators for: ServerLog-0
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00000030716082fb, pid=3375, tid=0x00007f768a01b700
#
# JRE version: Java(TM) SE Runtime Environment (8.0_144-b01) (build 1.8.0_144-b01)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.144-b01 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# C [libpthread.so.0+0x82fb] pthread_join+0x10b
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/weblogic/Oracle/Middleware/Oracle_Home/user_projects/domains/base_domain/hs_err_pid3375.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
#
/home/weblogic/Oracle/Middleware/Oracle_Home/user_projects/domains/base_domain/bin/startWebLogic.sh: line 197: 3375 Aborted (core dumped) ${JAVA_HOME}/bin/java ${JAVA_VM} ${MEM_ARGS} -Dweblogic.Name=${SERVER_NAME} -Djava.security.policy=${WLS_POLICY_FILE} ${JAVA_OPTIONS} ${PROXY_SETTINGS} ${SERVER_CLASS}
Stopping Derby server...
Derby server stopped.
<Nov 26, 2022 2:42:56 AM CST> <INFO> <NodeManager> <The server 'Server1' with process id 3323 is no longer alive; waiting for the process to die.>
<Nov 26, 2022 2:42:56 AM CST> <FINEST> <NodeManager> <Process died.>
四,从JDK参数CreateCoredumpOnCrash来控制
如果不想在操作系统层面设置,就可以修改JVM参数来实现。不过,这个是JDK 9之后版本才有的参数,因此jdk 8或者更低的JDK版本是 不可以的。
1)验证参数版本有效性:
JDK1.8:
[root@goya ~]# java -version
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)
[root@goya ~]# java -XX:-CreateCoredumpOnCrash -version
Unrecognized VM option 'CreateCoredumpOnCrash'
Did you mean '(+/-)CreateMinidumpOnCrash'?
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
说明没有这个参数。
JDK 17:
[root@localhost ~]# java -version
openjdk version "17.0.2" 2022-01-18
OpenJDK Runtime Environment Temurin-17.0.2+8 (build 17.0.2+8)
OpenJDK 64-Bit Server VM Temurin-17.0.2+8 (build 17.0.2+8, mixed mode, sharing)
[root@localhost ~]# java -XX:-CreateCoredumpOnCrash -version
openjdk version "17.0.2" 2022-01-18
OpenJDK Runtime Environment Temurin-17.0.2+8 (build 17.0.2+8)
OpenJDK 64-Bit Server VM Temurin-17.0.2+8 (build 17.0.2+8, mixed mode, sharing)
2)验证core dump文件
$ java -XX:-CreateCoredumpOnCrash -version
java version "11.0.14" 2022-01-18 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.14+8-LTS-263)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.14+8-LTS-263, mixed mode)
简单测试一个Java程序测试:
$ java -XX:-CreateCoredumpOnCrash xxx.java
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007faab8754015, pid=25223, tid=25223
#
# JRE version: Java(TM) SE Runtime Environment 18.9 (11.0.14+8) (build 11.0.14+8-LTS-263)
# Java VM: Java HotSpot(TM) 64-Bit Server VM 18.9 (11.0.14+8-LTS-263, mixed mode, tiered, compressed oops, g1 gc, linux-amd64)
# Problematic frame:
# C [libpthread.so.0+0x9015] pthread_join+0xa5
#
# CreateCoredumpOnCrash turned off, no core file dumped
...
Weblogic可以在控制台内,或者setDomainEnv.sh里设置。
示例:
示例:
JAVA_OPTIONS="${JAVA_OPTIONS} -XX:-CreateCoredumpOnCrash"
export JAVA_OPTIONS
说明:
目前 JDK 1.8 版本只能通过 core file size 配置为0,来disable core dump功能。
对于WebLogic高版本比如 14.1.x 支持的 JDK 9 及以上的JDK可以通过设置 -XX:-CreateCoredumpOnCrash来达到目的。