我可以在 OOM 上由 JVM 调用的脚本中使用 "kill %p"

Can I use "kill %p" in a script being called by JVM on OOM

我仍在准备对此进行测试,但在我继续之前我需要一些输入。我正在 gradle 中使用 JVM 设置内存不足处理。其中一部分涉及创建一个重启脚本,以通过 JVM 选项在 OOM 上调用。

它的工作方式是我先

task appStartScripts(type: CreateStartScripts) {
    def tplName = 'startBinTemplate.sh'
    assert project.file(tplName).exists()
    unixStartScriptGenerator.template = resources.text.fromFile(tplName)
    defaultJvmOpts = [
                      "-XX:+HeapDumpOnOutOfMemoryError",
                      "-XX:HeapDumpPath=$HOME/apps/log/",
                      "-XX:OnOutOfMemoryError=./restart.sh",

                      "-Xms1G", "-Xmx2G",
                      "-Dapp.name=${rootProject.name}"]

    dependsOn shadowJar
    applicationName = 'start'
    defaultJvmOpts += ["-Dspring.profiles.active=ENV_VARIABLE"]
    classpath = startShadowScripts.classpath
    mainClassName = startShadowScripts.mainClassName
    outputDir = new File(project.buildDir, 'scriptsShadow')

    doLast {
        unixScript.text = unixScript.text.replace('\$HOME', '\'"$HOME"\'')
        unixScript.text = unixScript.text.replace('ENV_VARIABLE', '\'""\'')
    }
}

理论上,在出现内存不足错误时,将调用重启脚本:

#!/usr/bin/env sh

kill -9 %p
sleep 5
./start.sh

这将杀死进程,休眠 5 秒,然后使用启动脚本重新启动它。我的问题是关于 kill 的 %p 参数。我可以在此上下文中的脚本中使用它,而不是 JVM 参数本身吗?我的理解是,它应该传递给 JVM 参数,然后 JVM 参数将使用它传递服务 PID 以终止服务。就我而言,我在脚本中使用它,因为试图将 kill -9 %p 传递给 $JVM_ARGS 会导致启动时出错:

Unrecognized option: -9

而传入要调用的脚本似乎不会引起任何问题。

我还在为此设置测试用例,但我想问:

  1. 有人做过吗?您的体验如何?
  2. 我有没有更好的方法来解决这个错误?

%p 占位符在执行 OnOutOfMemoryError 时由 JVM 解析。您必须在命令中使用 -XX:OnOutOfMemoryError=./restart.sh %p,然后在 restart.sh.

中从 </code> 读取它 <p>现代 JVM 具有 <code>ExitOnOutOfMemoryError 选项,其行为与 OnOutOfMemoryError="kill -9 %p" 相同(参见 JDK-8152669). You can combine this with a bash script shown in this answer:

#!/bin/sh

while true ; do
  java -XX:+ExitOnOutOfMemoryError -jar application.jar
  sleep 5
done