解析 java 结果 137

2022-09-03 17:09:14

我正在 Amazon ec2 上运行一个 java 进程。它运行了72分钟,然后突然我得到“java结果137”。仅此而已,没有异常或任何其他错误消息。我已经搜索了这个错误,但找不到任何有用的东西。它的原因可能是什么,如何解决它?请让我知道。


答案 1

高于 127 的退出代码通常表示进程因信号而停止。

然后,退出代码137解析为128 + 9,而信号9是SIGKILL,即进程被强行杀死。这可以是“杀死-9”命令。但是,在您的情况下,这可能是操作系统上的内存不足情况,这会导致称为“OOM Killer”的功能停止正在耗尽大部分内存的进程,以保持操作系统本身即使在这种情况下也稳定。

有关类似的讨论,请参阅此问题


答案 2

以防有人有兴趣知道这128个数字来自哪里;原因可以在OpenJDK源代码中找到。请参见:UNIXProcess_md.c

从Java_java_lang_UNIXProcess_waitForProcessExit方法中的注释中:

返回的最佳值是0x80 + 信号号,因为这是所有 Unix shell 所做的,并且因为它允许调用方通过信号区分进程退出和进程死亡。

因此,这就是为什么JVM开发人员决定在孩子因为信号而退出时将128添加到孩子的返回状态中的原因。

我在这里留下负责从子进程返回状态的方法:

 /* Block until a child process exits and return its exit code.
    Note, can only be called once for any given pid. */
 JNIEXPORT jint JNICALL
 Java_java_lang_UNIXProcess_waitForProcessExit(JNIEnv* env,
                                               jobject junk,
                                               jint pid)
 {
     /* We used to use waitid() on Solaris, waitpid() on Linux, but
      * waitpid() is more standard, so use it on all POSIX platforms. */
     int status;
     /* Wait for the child process to exit.  This returns immediately if
        the child has already exited. */
     while (waitpid(pid, &status, 0) < 0) {
         switch (errno) {
         case ECHILD: return 0;
         case EINTR: break;
         default: return -1;
         }
     }

     if (WIFEXITED(status)) {
         /*
          * The child exited normally; get its exit code.
          */
         return WEXITSTATUS(status);
     } else if (WIFSIGNALED(status)) {
         /* The child exited because of a signal.
          * The best value to return is 0x80 + signal number,
          * because that is what all Unix shells do, and because
          * it allows callers to distinguish between process exit and
          * process death by signal.
          * Unfortunately, the historical behavior on Solaris is to return
          * the signal number, and we preserve this for compatibility. */
 #ifdef __solaris__
         return WTERMSIG(status);
 #else
         return 0x80 + WTERMSIG(status);
 #endif
     } else {
         /*
          * Unknown exit code; pass it through.
          */
         return status;
     }
 }