RFR(S): 8205946: JVM crash after call to ClassLoader::setup_bootstrap_search_path()
Calvin Cheung
calvin.cheung at oracle.com
Tue Jul 10 21:17:06 UTC 2018
Hi Jiangli,
Thanks for reviewing.
On 7/10/18, 12:18 PM, Jiangli Zhou wrote:
> Hi Calvin,
>
> The error handling code in platform specific code are identical. I
> like Lois’ suggestion to check and exit in os::set_boot_path() to
> avoid duplicating the code.
If you want changes in os::set_boot_path() instead of in platform
specific code, I'm proposing the following:
diff --git a/src/hotspot/share/runtime/os.cpp
b/src/hotspot/share/runtime/os.cpp
--- a/src/hotspot/share/runtime/os.cpp
+++ b/src/hotspot/share/runtime/os.cpp
@@ -1270,7 +1270,7 @@
return file;
}
-bool os::set_boot_path(char fileSep, char pathSep) {
+void os::set_boot_path(char fileSep, char pathSep) {
const char* home = Arguments::get_java_home();
int home_len = (int)strlen(home);
@@ -1278,26 +1278,30 @@
// modular image if "modules" jimage exists
char* jimage = format_boot_path("%/lib/" MODULES_IMAGE_NAME, home,
home_len, fileSep, pathSep);
- if (jimage == NULL) return false;
+ if (jimage == NULL) {
+ vm_exit_during_initialization("Failed setting boot class path.", NULL);
+ }
bool has_jimage = (os::stat(jimage, &st) == 0);
if (has_jimage) {
Arguments::set_sysclasspath(jimage, true);
FREE_C_HEAP_ARRAY(char, jimage);
- return true;
+ return;
}
FREE_C_HEAP_ARRAY(char, jimage);
// check if developer build with exploded modules
char* base_classes = format_boot_path("%/modules/" JAVA_BASE_NAME,
home, home_len, fileSep, pathSep);
- if (base_classes == NULL) return false;
+ if (base_classes == NULL) {
+ vm_exit_during_initialization("Failed setting boot class path.", NULL);
+ }
if (os::stat(base_classes, &st) == 0) {
Arguments::set_sysclasspath(base_classes, false);
FREE_C_HEAP_ARRAY(char, base_classes);
- return true;
+ return;
}
FREE_C_HEAP_ARRAY(char, base_classes);
-
- return false;
+ vm_exit_during_initialization("Failed setting boot class path.", NULL);
+ return;
}
The function fails if os::stat() fails or allocation of buffer for
"jimage" or "base_classes" fails.
Since vm should exit on failure in the above function, it is unnecessary
for the function to return a bool.
>
> Also, under low memory condition, set_value() might fail to allocate
> and not trigger any error with a release binary. os::set_boot_path()
> probably should also check and make sure sys path is not NULL after
> Arguments::set_sysclasspath().
The AllocateHeap() you listed below will call into the following which
will exit on out of memory. So I don' think we need to do NULL check again.
// allocate using malloc; will fail if no memory available
char* AllocateHeap(size_t size,
MEMFLAGS flags,
const NativeCallStack& stack,
AllocFailType alloc_failmode /* =
AllocFailStrategy::EXIT_OOM*/) {
char* p = (char*) os::malloc(size, flags, stack);
if (p == NULL && alloc_failmode == AllocFailStrategy::EXIT_OOM) {
vm_exit_out_of_memory(size, OOM_MALLOC_ERROR, "AllocateHeap");
}
return p;
}
thanks,
Calvin
>
> bool PathString::set_value(const char *value) {
> if (_value != NULL) {
> FreeHeap(_value);
> }
> _value = AllocateHeap(strlen(value)+1, mtArguments);
> assert(_value != NULL, "Unable to allocate space for new path value");
> if (_value != NULL) {
> strcpy(_value, value);
> } else {
> // not able to allocate
> return false;
> }
> returntrue;
> }
>
> Thanks,
> Jiangli
>
>> On Jul 10, 2018, at 10:31 AM, Calvin Cheung <calvin.cheung at oracle.com
>> <mailto:calvin.cheung at oracle.com>> wrote:
>>
>> Updated webrev with the changes mentioned below:
>> http://cr.openjdk.java.net/~ccheung/8205946/webrev.01/
>> <http://cr.openjdk.java.net/%7Eccheung/8205946/webrev.01/>
>>
>> I've rerun hs-tier{1,2,3} tests.
>>
>> thanks,
>> Calvin
>>
>> On 7/9/18, 1:43 PM, Calvin Cheung wrote:
>>> Hi Lois,
>>>
>>> Thanks for your review.
>>>
>>> On 7/9/18, 11:58 AM, Lois Foltan wrote:
>>>> On 7/9/2018 1:29 PM, Calvin Cheung wrote:
>>>>
>>>>> bug: https://bugs.openjdk.java.net/browse/JDK-8205946
>>>>>
>>>>> webrev: http://cr.openjdk.java.net/~ccheung/8205946/webrev.00/
>>>>> <http://cr.openjdk.java.net/%7Eccheung/8205946/webrev.00/>
>>>>>
>>>>> The JVM crash could be simulated by renaming/removing the modules
>>>>> file under the jdk/lib directory.
>>>>> The proposed simple fix is to perform a
>>>>> vm_exit_during_initialization().
>>>>
>>>> Hi Calvin,
>>>>
>>>> Some clarifying questions. Is this just an issue for exploded builds?
>>> I don't think so. As mentioned above, I could reproduce the crash
>>> with a regular jdk image build by renaming the modules file under
>>> the jdk/lib directory.
>>>> I would prefer the exit to occur if the os::stat() fails for the
>>>> system class path in os::set_boot_path().
>>> Instead of exiting in os::set_boot_path(), how about checking the
>>> return status of os::set_boot_path() in the caller and exiting there
>>> like the following:
>>> bash-4.2$ hg diff os_linux.cpp
>>> diff --git a/src/hotspot/os/linux/os_linux.cpp
>>> b/src/hotspot/os/linux/os_linux.cpp
>>> --- a/src/hotspot/os/linux/os_linux.cpp
>>> +++ b/src/hotspot/os/linux/os_linux.cpp
>>> @@ -367,7 +367,9 @@
>>> }
>>> }
>>> Arguments::set_java_home(buf);
>>> - set_boot_path('/', ':');
>>> + if (!set_boot_path('/', ':')) {
>>> + vm_exit_during_initialization("Failed setting boot class
>>> path.", NULL);
>>> + }
>>> }
>>>
>>> Note that before the above change, the return status of
>>> set_boot_path() isn't checked.
>>> The above would involve changing 5 of those os_*.cpp files, one for
>>> each O/S.
>>>
>>>> With certainly an added assert later in
>>>> ClassLoader::setup_bootstrap_search_path() to ensure that the
>>>> system class path is never NULL.
>>> Sure, I can add an assert there.
>>> I'll post updated webrev once I've made the change and done testing.
>>>
>>> thanks,
>>> Calvin
>>>>
>>>> Thanks,
>>>> Lois
>>>>
>>>>>
>>>>> Ran hs-tier{1,2,3} tests successfully including the new test case.
>>>>>
>>>>> thanks,
>>>>> Calvin
>>>>
>
More information about the hotspot-runtime-dev
mailing list