我有一些应用程序只能在增加堆栈大小(java 选项 -Xss1M)的情况下才能正常运行,否则会出现段错误。如果我在命令行中使用 -Xss1M 选项,它就可以工作。要将这个解决方案集成到我的 Jenkins 工作中,我更喜欢使用 _JAVA_OPTIONS 环境变量方法而不是脚本修改。
令我惊讶的是,如果我说“export _JAVA_OPTIONS=-Xss1M”,它就不起作用。我还尝试设置 JAVA_OPTS 和 JAVA_TOOL_OPTIONS,使用单引号和双引号。结果总是一样的。特别奇怪的是,Java 写了“选择”选项,尽管它没有效果:
build@build-solaris-01:tests> /usr/jdk/instances/jdk1.6.0/bin/java -d32 -verbose:gc -classpath ../dist/solaris/forte/prod32mt/cpjdlib.jar: -Djava.library.path=../dist/solaris/forte/prod32mt/dll intern_AFPMMD
Picked up JAVA_TOOL_OPTIONS: -Xss1M
Picked up _JAVA_OPTIONS: -Xss1M
try load: cpjdlib
Successfully loaded library: 'cpjdlib'
License Valid? true
Segmentation Fault (core dumped)
如果我使用 -Xss1M 作为命令行选项运行相同的命令,它可以工作:
build@build-solaris-01:tests> /usr/jdk/instances/jdk1.6.0/bin/java -Xss1M -d32 -verbose:gc -classpath ../dist/solaris/forte/prod32mt/cpjdlib.jar: -Djava.library.path=../dist/solaris/forte/prod32mt/dll intern_AFPMMD
Picked up JAVA_TOOL_OPTIONS: -Xss1M
Picked up _JAVA_OPTIONS: -Xss1M
try load: cpjdlib
Successfully loaded library: 'cpjdlib'
License Valid? true
Success.
在 SunOS 5.10 和 CentOS 4 机器上,我确实有相同的行为。在两者上我都使用 JDK 6。我使用了https://docs.oracle.com/javase/6/docs/platform/jvmti/jvmti.html#tooloptions和https://docs.oracle.com/cd/E14592_01/ doc.10142/e14608/app_orminweblogic.htm作为参考和_JAVA_OPTIONS JAVA_TOOL_OPTIONS 和 JAVA_OPTS 之间的区别,以查看 _JAVA_OPTIONS 用法的示例。我没有发现任何提及好像 _JAVA_OPTIONS 不接受某些选项等。所以我想它也应该与 -Xss 一起使用。谁能指出,我的错误在哪里,请?
更新 1:我确信命令行选项规范与 _JAVA_OPTIONS 真的不是等价的东西。不仅适用于 -Xss,还适用于其他选项。
我在我的 Ubuntu 14.04 上使用了 Java 7 和 -XshowSettings:all 选项来查看这些选项是如何在“内部”Java 中看到的。我执行了 3 个命令并比较了它们的输出(不同之处在于第一行)。
$ java -XshowSettings:all -version 2>&1 | 头-5
VM settings:
Max. Heap Size (Estimated): 910.25M
Ergonomics Machine Class: server
Using VM: Java HotSpot(TM) Server VM
$ _JAVA_OPTIONS="-Xms2048m -Xmx2048m" java -XshowSettings:all -version 2>&1 | 头-5
Picked up _JAVA_OPTIONS: -Xms2048m -Xmx2048m
VM settings:
Max. Heap Size (Estimated): 1.92G
Ergonomics Machine Class: server
Using VM: Java HotSpot(TM) Server VM
$ java -Xms2048m -Xmx2048m -XshowSettings:all -version 2>&1 | 头-5
VM settings:
Min. Heap Size: 2.00G
Max. Heap Size: 2.00G
Ergonomics Machine Class: server
Using VM: Java HotSpot(TM) Server VM
这意味着相同的选项 -Xms、-Xmx 确实有,但当我们使用 _JAVA_OPTIONS 方法时效果有限。这同样适用于 -Xss:
$ _JAVA_OPTIONS="-Xss1m" java -XshowSettings:all -version 2>&1 | 头-5
Picked up _JAVA_OPTIONS: -Xss1m
VM settings:
Max. Heap Size (Estimated): 910.25M
Ergonomics Machine Class: server
Using VM: Java HotSpot(TM) Server VM
$ java -Xss1m -XshowSettings:all -version 2>&1 | 头-5
VM settings:
Stack Size: 1.00M
Max. Heap Size (Estimated): 910.25M
Ergonomics Machine Class: server
Using VM: Java HotSpot(TM) Server VM
不同之处在于它仅在 -Xss1m 是命令行选项时才指示“堆栈大小:1.00M”。但为什么!为什么不在 _JAVA_OPTIONS 下提供完全等效的命令行?
更新 2 :从http://hg.openjdk.java.net/jdk7/jdk7/hotspot/archive/tip.tar.gz和http下载了 Java 源代码的“片段”(“hotspot”和“jdk”) : //hg.openjdk.java.net/jdk7/jdk7/jdk/archive/tip.tar.gz。注入大量打印输出并设法从源代码构建 java 和所有相关库(libjvm.so、rt.jar),然后运行它。
根本原因是来自 _JAVA_OPTIONS 的选项存储在数组 _jvm_args_array 中,该数组不用于 jdk-9b8c96f96a0f/src/solaris/bin/java_md.c 中的 thr_create() 调用。
有一个地方我们尝试评估堆栈大小,它是从 ContinueInNewThread(...) 调用 JNI_GetDefaultJavaVMInitArgs(void *args_),但它只返回等于 320K 的默认堆栈大小值并且不使用 _JAVA_OPTIONS . _JAVA_OPTIONS 的解析稍后发生在看起来完全没有意义的已创建线程中。
我编写了下面的调用序列来说明可能对它感兴趣的人正在发生的事情(缩进对应于调用深度)。
[jdk-9b8c96f96a0f/src/share/bin/java.c]: JLI_Launch(...)
[jdk-9b8c96f96a0f/src/share/bin/java.c]: ContinueInNewThread(InvocationFunctions* ifn, int argc, char **argv, int mode, char *what, int ret) // threadStackSize=0 (not passed via command line)
[hotspot-9b0ca45cd756/src/share/vm/prims/jni.cpp]: JNI_GetDefaultJavaVMInitArgs(void *args_) // args->javaStackSize=320*1024 (default value is assigned), is called by pointer ifn->GetDefaultJavaVMInitArgs(&args1_1) from jdk-9b8c96f96a0f/src/share/bin/java.c
[jdk-9b8c96f96a0f/src/solaris/bin/java_md.c]: ContinueInNewThread0(int (JNICALL *continuation)(void *), jlong stack_size, void * args) // threadStackSize=320*1024
[jdk-9b8c96f96a0f/src/solaris/bin/java_md.c]: thr_create(NULL, stack_size, (void *(*)(void *))continuation, args, flags, &tid) // threadStackSize=320*1024
[jdk-9b8c96f96a0f/src/share/bin/java.c]: JavaMain(void * args) // called with no arguments (no stack size was passed)!
[jdk-9b8c96f96a0f/src/share/bin/java.c]: InitializeJVM(&vm, &env, &ifn)
[hotspot-9b0ca45cd756/src/share/vm/runtime/arguments.cpp]: Arguments::parse() // is called by pointer ifn->CreateJavaVM(pvm, (void **)penv, &args) from jdk-9b8c96f96a0f/src/share/bin/java.c
[hotspot-9b0ca45cd756/src/share/vm/runtime/arguments.cpp]: Arguments::parse_vm_init_args(args)
[hotspot-9b0ca45cd756/src/share/vm/runtime/arguments.cpp]: Arguments::parse_java_tool_options_environment_variable(&scp, &scp_assembly_required);
[hotspot-9b0ca45cd756/src/share/vm/runtime/arguments.cpp]: Arguments::parse_options_environment_variable("_JAVA_OPTIONS", scp_p, scp_assembly_required_p); // Here it writes "Picked up _JAVA_OPTIONS: -Xss1m"
[hotspot-9b0ca45cd756/src/share/vm/runtime/arguments.cpp]: Arguments::parse_each_vm_init_arg(&vm_args, scp_p, scp_assembly_required_p, ENVIRON_VAR))
[hotspot-9b0ca45cd756/src/share/vm/runtime/arguments.cpp]: Arguments::build_jvm_args(option->optionString); // puts the option to _jvm_args_array which is accessible later as jvm_args_array() or jvm_args()
(*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs); // <-Java *.class application execution
我现在正在检查如何向 OpenJDK 报告错误。即使 OpenJDK 认为这样的实现设计得当,在命令行帮助和文档中也应该清楚地说明 -Xss 不能在 _JAVA_OPTIONS 中工作。