8222334: java -Xss0 triggers StackOverflowError
Summary: Launcher to use the stack size decided by hotpot or system if -Xss is 0
Reviewed-by: dholmes, alanb
--- a/src/java.base/share/native/libjli/java.c Tue Apr 16 08:51:01 2019 +0200
+++ b/src/java.base/share/native/libjli/java.c Tue Apr 16 11:00:48 2019 +0000
@@ -204,11 +204,14 @@
*/
static jlong threadStackSize = 0; /* stack size of the new thread */
static jlong maxHeapSize = 0; /* max heap size */
-static jlong initialHeapSize = 0; /* inital heap size */
+static jlong initialHeapSize = 0; /* initial heap size */
/*
- * A minimum -Xss stack size suitable for all platforms.
- */
+ * A minimum initial-thread stack size suitable for most platforms.
+ * This is the minimum amount of stack needed to load the JVM such
+ * that it can reject a too small -Xss value. If this is too small
+ * JVM initialization would cause a StackOverflowError.
+ */
#ifndef STACK_SIZE_MINIMUM
#define STACK_SIZE_MINIMUM (64 * KB)
#endif
@@ -934,16 +937,18 @@
options[numOptions].optionString = str;
options[numOptions++].extraInfo = info;
+ /*
+ * -Xss is used both by the JVM and here to establish the stack size of the thread
+ * created to launch the JVM. In the latter case we need to ensure we don't go
+ * below the minimum stack size allowed. If -Xss is zero that tells the JVM to use
+ * 'default' sizes (either from JVM or system configuration, e.g. 'ulimit -s' on linux),
+ * and is not itself a small stack size that will be rejected. So we ignore -Xss0 here.
+ */
if (JLI_StrCCmp(str, "-Xss") == 0) {
jlong tmp;
if (parse_size(str + 4, &tmp)) {
threadStackSize = tmp;
- /*
- * Make sure the thread stack size is big enough that we won't get a stack
- * overflow before the JVM startup code can check to make sure the stack
- * is big enough.
- */
- if (threadStackSize < (jlong)STACK_SIZE_MINIMUM) {
+ if (threadStackSize > 0 && threadStackSize < (jlong)STACK_SIZE_MINIMUM) {
threadStackSize = STACK_SIZE_MINIMUM;
}
}
@@ -2322,38 +2327,38 @@
int argc, char **argv,
int mode, char *what, int ret)
{
-
- /*
- * If user doesn't specify stack size, check if VM has a preference.
- * Note that HotSpot no longer supports JNI_VERSION_1_1 but it will
- * return its default stack size through the init args structure.
- */
if (threadStackSize == 0) {
- struct JDK1_1InitArgs args1_1;
- memset((void*)&args1_1, 0, sizeof(args1_1));
- args1_1.version = JNI_VERSION_1_1;
- ifn->GetDefaultJavaVMInitArgs(&args1_1); /* ignore return value */
- if (args1_1.javaStackSize > 0) {
- threadStackSize = args1_1.javaStackSize;
- }
+ /*
+ * If the user hasn't specified a non-zero stack size ask the JVM for its default.
+ * A returned 0 means 'use the system default' for a platform, e.g., Windows.
+ * Note that HotSpot no longer supports JNI_VERSION_1_1 but it will
+ * return its default stack size through the init args structure.
+ */
+ struct JDK1_1InitArgs args1_1;
+ memset((void*)&args1_1, 0, sizeof(args1_1));
+ args1_1.version = JNI_VERSION_1_1;
+ ifn->GetDefaultJavaVMInitArgs(&args1_1); /* ignore return value */
+ if (args1_1.javaStackSize > 0) {
+ threadStackSize = args1_1.javaStackSize;
+ }
}
{ /* Create a new thread to create JVM and invoke main method */
- JavaMainArgs args;
- int rslt;
+ JavaMainArgs args;
+ int rslt;
- args.argc = argc;
- args.argv = argv;
- args.mode = mode;
- args.what = what;
- args.ifn = *ifn;
+ args.argc = argc;
+ args.argv = argv;
+ args.mode = mode;
+ args.what = what;
+ args.ifn = *ifn;
- rslt = CallJavaMainInNewThread(threadStackSize, (void*)&args);
- /* If the caller has deemed there is an error we
- * simply return that, otherwise we return the value of
- * the callee
- */
- return (ret != 0) ? ret : rslt;
+ rslt = CallJavaMainInNewThread(threadStackSize, (void*)&args);
+ /* If the caller has deemed there is an error we
+ * simply return that, otherwise we return the value of
+ * the callee
+ */
+ return (ret != 0) ? ret : rslt;
}
}
--- a/test/hotspot/jtreg/runtime/Thread/TooSmallStackSize.java Tue Apr 16 08:51:01 2019 +0200
+++ b/test/hotspot/jtreg/runtime/Thread/TooSmallStackSize.java Tue Apr 16 11:00:48 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -187,12 +187,18 @@
checkMinStackAllowed("-XX:ThreadStackSize=", ThreadStackSizeString, "513");
/*
+ * Try with 0k which indicates that the default thread stack size from JVM will be used.
+ */
+ checkMinStackAllowed("-XX:ThreadStackSize=", ThreadStackSizeString, "0");
+
+ /*
* Now redo the same tests with the compiler thread stack size:
*/
checkStack("-XX:CompilerThreadStackSize=", CompilerThreadStackSizeString, "16");
min_stack_allowed = checkStack("-XX:CompilerThreadStackSize=", CompilerThreadStackSizeString, "64");
checkMinStackAllowed("-XX:CompilerThreadStackSize=", CompilerThreadStackSizeString, min_stack_allowed);
checkMinStackAllowed("-XX:CompilerThreadStackSize=", CompilerThreadStackSizeString, "513");
+ checkMinStackAllowed("-XX:CompilerThreadStackSize=", CompilerThreadStackSizeString, "0");
/*
* Now redo the same tests with the VM thread stack size:
@@ -201,5 +207,6 @@
min_stack_allowed = checkStack("-XX:VMThreadStackSize=", VMThreadStackSizeString, "64");
checkMinStackAllowed("-XX:VMThreadStackSize=", VMThreadStackSizeString, min_stack_allowed);
checkMinStackAllowed("-XX:VMThreadStackSize=", VMThreadStackSizeString, "513");
+ checkMinStackAllowed("-XX:VMThreadStackSize=", VMThreadStackSizeString, "0");
}
}
--- a/test/jdk/tools/launcher/TooSmallStackSize.java Tue Apr 16 08:51:01 2019 +0200
+++ b/test/jdk/tools/launcher/TooSmallStackSize.java Tue Apr 16 11:00:48 2019 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 6762191
+ * @bug 6762191 8222334
* @summary Setting stack size to 16K causes segmentation fault
* @compile TooSmallStackSize.java
* @run main TooSmallStackSize
@@ -171,5 +171,11 @@
* asserts added for 8176768 are not triggered.
*/
checkMinStackAllowed("513k");
+
+ /*
+ * Try with 0k which indicates that the default thread stack size either from JVM or system
+ * will be used, this should always succeed.
+ */
+ checkMinStackAllowed("0k");
}
}