触发JVM fatal error并配置相关JVM参数(配置存在问题,期待交流)

1. 絮絮叨叨

  • 工作中,Java服务因为fatal error(致命错误,笔者称其为jvm crash),在服务运行日志中出现了致命错误的概要信息:

    #
    # A fatal error has been detected by the Java Runtime Environment:
    #
    #  SIGSEGV (0xb) at pc=0x000000010a7d52e8, pid=47989, tid=11011
    #
    # JRE version: OpenJDK Runtime Environment Temurin-17.0.6+10 (17.0.6+10) (build 17.0.6+10)
    # Java VM: OpenJDK 64-Bit Server VM Temurin-17.0.6+10 (17.0.6+10, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, bsd-amd64)
    # Problematic frame:
    # V  [libjvm.dylib+0xada2e8]  Unsafe_GetByte(JNIEnv_*, _jobject*, _jobject*, long)+0xd8
    #
    # No core dump will be written. 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:
    # /Users/xxx/IdeaProjects/study/hs_err_pid47989.log
    #
    # If you would like to submit a bug report, please visit:
    #   https://github.com/adoptium/adoptium-support/issues
    #
    
  • 服务运行在k8s中,由于未提前设置fatal error日志的路径(挂载到宿主机目录),容器重启后该日志会丢失,无法深入排查原因

  • 因此,需要查询jvm的配置,将fatal error日志写入指定目录,保证该日志持久化存储到宿主机磁盘

2. 配置jvm参数,实现日志的持久化存储

2.1 -XX:ErrorFile配置fatal error路径

  • 通过查阅资料,了解到可以通过-XX:ErrorFile=filename配置hs_err日志的路径

  • 下面的示例中,将fatal error的日志写入指定目录,文件名的%p会动态替换成改Java程序的PID(进程id)

    -XX:ErrorFile=/var/log/java/java_error%p.log
    
  • 默认将fatal error日志写入Java程序的working directory,且文件名为hs_err_pid.log;如果空间不足、权限不够等原因,fatal error日志将被写入系统的临时目录

  • 详情见JDK官网的说明:

2.2 笔者的错误配置

  • 考虑到服务每次重启的pid基本一致,如果多次出现fatal error,只使用pid的日志会被覆盖。

  • 笔者结合之前配置heap dump的经验,添加了%t以生成类似2023-08-16_23-33-08的时间戳

    -XX:ErrorFile=/data_path/var/log/hs_err_pid%p_%t.log
    
  • 当再一次发生fatal error时,发现日志文件名为hs_err_pid6_%t.log,即%t未按照预期进行解析

2.3 -XX:OnError配置更新文件名

  • 受问题(How to specify a unique name for the JVM crash log files?)启发,配置-XX:OnError:在日志生成后,执行shell命令为其添加时间戳

    -XX:ErrorFile=/data_path/var/log/hs_err.log
    -XX:OnError="time=`date +%Y%m%d_%H%M%S` && mv /data_path/var/log/hs_err.log /data_path/var/log/hs_err_\${time}.log"
    

3. 如何触发fatal error?

  • 不管是验证相关JVM参数的配置,还是学习查看fatal error日志的内容,学会如何触发fatal error是非常必要的

  • 参考:Write Java code to crash the java virtual machine,通过如下代码可以成功在本地触发fatal error

    import sun.misc.Unsafe;
    import java.lang.reflect.Field;
    
    public class CrashTest {
        public static void main(String... args) throws Exception {
            getUnsafe().getByte(0);
        }
    
        private static Unsafe getUnsafe() throws NoSuchFieldException, IllegalAccessException {
            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true);
            return (Unsafe) theUnsafe.get(null);
        }
    }
    

4. 待交流的问题

4.1 本地验证OK

  • 按照上面的描述,笔者为CrashTest配置了如下JVM参数

    -XX:ErrorFile=/data_path/study/hs_err.log
    -XX:OnError="time=`date +%Y%m%d_%H%M%S` && echo $time && mv /data_path/hs_err.log /data_path//hs_err_${time}.log"
    
  • 程序运行起来后,打印如下信息:

    #
    # A fatal error has been detected by the Java Runtime Environment:
    #
    #  SIGSEGV (0xb) at pc=0x000000010a49e2e8, pid=56245, tid=11011
    #
    # JRE version: OpenJDK Runtime Environment Temurin-17.0.6+10 (17.0.6+10) (build 17.0.6+10)
    # Java VM: OpenJDK 64-Bit Server VM Temurin-17.0.6+10 (17.0.6+10, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, bsd-amd64)
    # Problematic frame:
    # V  [libjvm.dylib+0xada2e8]  Unsafe_GetByte(JNIEnv_*, _jobject*, _jobject*, long)+0xd8
    #
    # No core dump will be written. 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:
    # /data_path/hs_err.log
    #
    # If you would like to submit a bug report, please visit:
    #   https://github.com/adoptium/adoptium-support/issues
    #
    #
    # -XX:OnError="time=`date +%Y%m%d_%H%M%S` && mv /data_path/hs_err.log /data_path/hs_err_${time}.log"
    #   Executing /bin/sh -c "time=`date +%Y%m%d_%H%M%S` && mv /data_path/hs_err.log /data_path/hs_err_${time}.log" ...
    
  • 最终,fatal error日志的文件名为hs_err_20230827_202458.log符合预期

4.2 测试环境验证失败

  • 将此配置移动到测试环境,却发现fatal error日志的文件名为hs_err_.log不符合预期

  • 怀疑: 未能正确解析${time}

  • 一个问答: How to add the timestamp of the fatal error occurrence to Java fatal error log filename,遇到了与笔者类似的问题

    -XX:ErrorFile=/data_path/hs_err.log
    -XX:OnError="mv /data_path/var/log/hs_err.log /data_path/var/log/hs_err_\$(date +%Y%m%d_%H%M%S).log"
    
  • 虽然更新了配置,但是由于引发fatal error的错误已被修复,无法验证该配置的效果

  • 要么等到后面出现fatal error时验证效果,要么回退镜像版本触发fatal error

  • 若后续有机会验证该配置,笔者会更新结果,暂时在此记录可能的可行解决方案

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: idea的JVM参数可以在运行/调试配置中进行配置。 具体步骤如下: 1. 打开IntelliJ IDEA。 2. 点击菜单栏的"Run",选择"Edit Configurations"(或者按下Shift + Alt + F10)。 3. 在左侧的配置列表中选择你要配置JVM参数配置项,例如"Application"。 4. 在右侧的配置面板中,找到"VM options"(或者"VM options"),点击右侧的"+"图标添加JVM参数。 5. 在弹出的对话框中,输入你想要配置JVM参数,例如"-Xmx512m"(表示设置最大堆内存为512MB)。 6. 点击"OK"保存配置。 这样,在运行或者调试你的应用程序时,IDEA会使用你配置JVM参数。 需要注意的是,不同的配置项可能有不同的配置方式,具体的JVM参数配置取决于你使用的配置项类型。所以建议在配置JVM参数之前,先了解清楚你要配置的那个配置项的具体配置方式。 ### 回答2: 在Java虚拟机(JVM)中,可以通过命令行参数配置文件来配置JVM参数。具体来说,可以在以下位置配置JVM参数: 1. 命令行参数:可以在命令行中使用"-D"选项来配置JVM参数。例如,可以使用"java -D参数名=参数值"的命令来配置JVM参数。这些参数会直接传递给JVM,并在程序运行时生效。 2. 环境变量:可以通过设置JVM相关的环境变量来配置JVM参数。例如,可以使用"export 参数名=参数值"的命令来设置环境变量,在程序启动时JVM会读取这些环境变量并加载对应的参数。 3. 配置文件:可以通过修改JVM配置文件来配置JVM参数。不同的JVM实现可能有不同的配置文件,常见的包括"jvm.ini"、"jvm.conf"或"jvm.properties"等。通过编辑这些文件并添加或修改相应的参数,可以配置JVM的行为。 需要注意的是,JVM参数可以根据具体的需求进行不同的配置。其中一些常见的JVM参数包括堆内存大小、垃圾回收策略、类路径、编译优化等。这些参数配置可以对程序的性能和行为产生重要影响,因此需要根据实际情况进行合理的调整和配置。 ### 回答3: Idea的JVM参数可以在其安装目录下的bin目录中的idea64.exe.vmoptions或idea.exe.vmoptions文件中配置。 可以按照以下步骤进行配置: 1. 首先,找到你的Idea安装目录,进入bin目录。 2. 在该目录下,你可以看到两个文件:idea64.exe.vmoptions和idea.exe.vmoptions。前者适用于64位操作系统,后者适用于32位操作系统。 3. 打开适用于你系统的文件(通过右键单击并选择"编辑"或使用任何文本编辑器打开)。 4. 在打开的文件中,你可以看到一系列以"-D"开头的行,每行都表示一个JVM参数。在这里你可以添加、修改或删除参数。 5. 添加/修改参数后,保存文件并重新启动Idea,新的JVM参数将生效。 请注意,修改JVM参数可能对Idea的性能和行为产生重大影响,因此在修改之前建议备份原始文件。同时,确保你理解所做更改的含义和影响,以免引起其他问题

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值