Могу ли я использовать «убить% p» в сценарии, вызываемом JVM на OOM

Я все еще готовлюсь проверить это, но я хотел бы получить некоторые комментарии, прежде чем идти дальше. Я настраиваю обработку нехватки памяти с помощью JVM в gradle. Часть этого включает создание сценария перезапуска, который будет вызываться в OOM с помощью параметров JVM.

Как это работает, я сначала

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. Есть ли лучший способ сделать это, чтобы обойти ошибку?

🤔 А знаете ли вы, что...
Java поддерживает многопоточность, что позволяет создавать многозадачные приложения.


1
310
1

Ответ:

Решено

%p заполнитель разрешается JVM при выполнении OnOutOfMemoryError. Вам нужно будет использовать в команде -XX:OnOutOfMemoryError=./restart.sh %p, а затем прочитать ее из $1 в restart.sh.

У современной JVM есть опция ExitOnOutOfMemoryError, которая ведет себя так же, как OnOutOfMemoryError = "kill -9 %p" (см. JDK-8152669). Вы можете комбинировать это с скриптом bash, показанным в этом ответе:

#!/bin/sh

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