首页 > 解决方案 > 我可以在 OOM 上 JVM 调用的脚本中使用“kill %p”吗

问题描述

我仍在准备对此进行测试,但在继续之前我想要一些输入。我正在使用 JVM 在 gradle 中设置内存不足处理。其中一部分涉及创建一个重新启动脚本,以由 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', '\'"$1"\'')
    }
}

理论上,如果出现内存不足错误,将调用重新启动脚本:

#!/usr/bin/env sh

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

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

Unrecognized option: -9

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

我仍在为此设置一个测试用例,但我想问:

  1. 有人做过吗?你的经历是什么?
  2. 我有没有更好的方法来解决这个错误?

标签: javashellgradlejvmjvm-arguments

解决方案


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

现代 JVM 具有与(参见JDK-8152669ExitOnOutOfMemoryError )相同的选项。您可以将其与此答案中显示的 bash 脚本结合使用:OnOutOfMemoryError="kill -9 %p"

#!/bin/sh

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

推荐阅读