From bdb91fe07fb50bc109cd0300a6a0298995c0857b Mon Sep 17 00:00:00 2001 From: Nathan Henderson Date: Thu, 19 Dec 2024 14:35:49 -0800 Subject: [PATCH] Fix VM snapshot class loader initialization The code for initializing the persisted applicationClassLoader and extensionClassLoader from a VM snapshot was in an unreachable path. On restore runs, neither of those class loaders will be null, but there was a null check guarding the initialization. This patch reorders some of those checks, and ensures that the class loaders are initialized properly. Signed-off-by: Nathan Henderson --- runtime/jcl/common/stdinit.c | 68 +++++++++++++++++------------------- 1 file changed, 32 insertions(+), 36 deletions(-) diff --git a/runtime/jcl/common/stdinit.c b/runtime/jcl/common/stdinit.c index b1bb3bd2144..4bb2b012eb8 100644 --- a/runtime/jcl/common/stdinit.c +++ b/runtime/jcl/common/stdinit.c @@ -465,35 +465,33 @@ internalInitializeJavaLangClassLoader(JNIEnv * env) vmFuncs->internalEnterVMFromJNI(vmThread); +#if defined(J9VM_OPT_SNAPSHOT) /* Always use the persisted applicationClassLoader in restore runs. */ - if (!IS_RESTORE_RUN(vm)) { + if (IS_RESTORE_RUN(vm)) { + vmFuncs->initializeSnapshotClassLoaderObject(vm, vm->applicationClassLoader, J9_JNI_UNWRAP_REFERENCE(appClassLoader)); + } else +#endif /* defined(J9VM_OPT_SNAPSHOT) */ + { vm->applicationClassLoader = J9VMJAVALANGCLASSLOADER_VMREF(vmThread, J9_JNI_UNWRAP_REFERENCE(appClassLoader)); - } - if (NULL == vm->applicationClassLoader) { - /* CMVC 201518 - * applicationClassLoader may be null due to lazy classloader initialization. Initialize - * the applicationClassLoader now or vm will start throwing NoClassDefFoundException. - */ -#if defined(J9VM_OPT_SNAPSHOTS) - if (IS_RESTORE_RUN(vm)) { - vmFuncs->initializeSnapshotClassLoaderObject(vm, vm->applicationClassLoader, J9_JNI_UNWRAP_REFERENCE(appClassLoader)); - } else -#endif /* defined(J9VM_OPT_SNAPSHOTS) */ - { + if (NULL == vm->applicationClassLoader) { + /* CMVC 201518 + * applicationClassLoader may be null due to lazy classloader initialization. Initialize + * the applicationClassLoader now or vm will start throwing NoClassDefFoundException. + */ vm->applicationClassLoader = (void *)(UDATA)(vmFuncs->internalAllocateClassLoader(vm, J9_JNI_UNWRAP_REFERENCE(appClassLoader))); - } - if (NULL != vmThread->currentException) { - /* while this exception check and return statement seem un-necessary, it is added to prevent - * oversights if anybody adds more code in the future. - */ - goto exitVM; + if (NULL != vmThread->currentException) { + /* While this exception check and return statement seem un-necessary, it is added to prevent + * oversights if anybody adds more code in the future. + */ + goto exitVM; + } } } /* Set up extension class loader in VM */ - if (NULL == vm->extensionClassLoader) { + if (NULL != vm->applicationClassLoader) { j9object_t classLoaderObject = vm->applicationClassLoader->classLoaderObject; j9object_t classLoaderParentObject = classLoaderObject; @@ -502,26 +500,24 @@ internalInitializeJavaLangClassLoader(JNIEnv * env) classLoaderParentObject = J9VMJAVALANGCLASSLOADER_PARENT(vmThread, classLoaderObject); } - /* Restore runs use the persisted extensionClassLoader. */ - if (!IS_RESTORE_RUN(vm)) { - vm->extensionClassLoader = J9VMJAVALANGCLASSLOADER_VMREF(vmThread, classLoaderObject); - } - - if (NULL == vm->extensionClassLoader) { #if defined(J9VM_OPT_SNAPSHOTS) - if (IS_RESTORE_RUN(vm)) { - vmFuncs->initializeSnapshotClassLoaderObject(vm, vm->extensionClassLoader, classLoaderObject); - } else + /* Always use the persisted extensionClassLoader in restore runs. */ + if (IS_RESTORE_RUN(vm)) { + vmFuncs->initializeSnapshotClassLoaderObject(vm, vm->extensionClassLoader, classLoaderObject); + } else #endif /* defined(J9VM_OPT_SNAPSHOTS) */ - { + if (NULL == vm->extensionClassLoader) { + vm->extensionClassLoader = J9VMJAVALANGCLASSLOADER_VMREF(vmThread, classLoaderObject); + + if (NULL == vm->extensionClassLoader) { vm->extensionClassLoader = (void *)(UDATA)(vmFuncs->internalAllocateClassLoader(vm, classLoaderObject)); - } - if (NULL != vmThread->currentException) { - /* while this exception check and return statement seem un-necessary, it is added to prevent - * oversights if anybody adds more code in the future. - */ - goto exitVM; + if (NULL != vmThread->currentException) { + /* While this exception check and return statement seem un-necessary, it is added to prevent + * oversights if anybody adds more code in the future. + */ + goto exitVM; + } } } }