Skip to content

Commit bac2eb9

Browse files
authored
Merge pull request #22289 from lzhou2025/moduleClassLoader
RCP: Restore immortal classloaders using persisted state
2 parents a8b6035 + 8f2ef1e commit bac2eb9

File tree

15 files changed

+237
-71
lines changed

15 files changed

+237
-71
lines changed

jcl/src/java.base/share/classes/com/ibm/oti/vm/VM.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ public final class VM {
119119
public static final int J9_CLASSLOADER_TYPE_OTHERS;
120120
public static final int J9_CLASSLOADER_TYPE_BOOT;
121121
public static final int J9_CLASSLOADER_TYPE_PLATFORM;
122+
public static final int J9_CLASSLOADER_TYPE_APP;
122123

123124
/* Lock reservation */
124125
public static final int J9CLASS_RESERVABLE_LOCK_WORD_INIT;
@@ -201,6 +202,7 @@ public final class VM {
201202
J9_CLASSLOADER_TYPE_OTHERS = 0;
202203
J9_CLASSLOADER_TYPE_BOOT = 0;
203204
J9_CLASSLOADER_TYPE_PLATFORM = 0;
205+
J9_CLASSLOADER_TYPE_APP = 0;
204206

205207
J9CLASS_RESERVABLE_LOCK_WORD_INIT = 0;
206208
OBJECT_HEADER_LOCK_RESERVED = 0;
@@ -262,12 +264,29 @@ private VM() {
262264
* @param loaderType
263265
* J9_CLASSLOADER_TYPE_BOOT - bootstrap classloader
264266
* J9_CLASSLOADER_TYPE_PLATFORM - platform classloader
265-
* J9_CLASSLOADER_TYPE_OTHERS - other classloader
267+
* J9_CLASSLOADER_TYPE_APP - application classloader
268+
* J9_CLASSLOADER_TYPE_OTHERS - other classloaders
266269
* @param parallelCapable
267270
* true if the loader has registered as parallel capable
268271
*/
269272
public final static native void initializeClassLoader(ClassLoader loader, int loaderType, boolean parallelCapable);
270273

274+
/*[IF RAM_CLASS_CACHE_SUPPORT] */
275+
/**
276+
* RCP: Link java Classloader to the internal VM classloader.
277+
* Currently, only Boot, Platform and App classloaders are supported.
278+
*
279+
* @param loader
280+
* ClassLoader the ClassLoader instance
281+
* @param id
282+
* J9_CLASSLOADER_TYPE_BOOT - bootstrap classloader
283+
* J9_CLASSLOADER_TYPE_PLATFORM - platform classloader
284+
* J9_CLASSLOADER_TYPE_APP - application classloader
285+
* J9_CLASSLOADER_TYPE_OTHERS - other classloaders
286+
*/
287+
public final static native void rcpAssignClassLoader(ClassLoader loader, int id);
288+
/*[ENDIF] RAM_CLASS_CACHE_SUPPORT */
289+
271290
public final static native long getProcessId();
272291
public final static native long getUid();
273292
/**
@@ -588,6 +607,15 @@ public static int markCurrentThreadAsSystem()
588607
*/
589608
public static native boolean isJVMInSingleThreadedMode();
590609

610+
/*[IF RAM_CLASS_CACHE_SUPPORT] */
611+
/**
612+
* Queries whether the JVM is running in RCP restore run.
613+
*
614+
* @return true if JVM is in RCP restore run, false otherwise
615+
*/
616+
public static native boolean isRCPRestoreRun();
617+
/*[ENDIF] RAM_CLASS_CACHE_SUPPORT */
618+
591619
/**
592620
* A J9ConstantPool* is appended to anntation parameter byte arrays
593621
* so it will be consistent with annotation data if the class is redefined.

jcl/src/java.base/share/classes/java/lang/ClassLoader.java

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ public abstract class ClassLoader {
102102
private final static String DELEGATING_CL = "sun.reflect.DelegatingClassLoader"; //$NON-NLS-1$
103103
/*[ENDIF] JAVA_SPEC_VERSION >= 9 */
104104
private boolean isDelegatingCL = false;
105+
/*[IF JAVA_SPEC_VERSION > 8]*/
106+
private static boolean applicationClassLoaderInited;
107+
/*[ENDIF] JAVA_SPEC_VERSION > 8 */
105108

106109
/*
107110
* This is the application ClassLoader
@@ -163,7 +166,9 @@ private static final class ClassNameBasedLock { ClassNameBasedLock() {} }
163166
private NativeLibraries nativelibs = null;
164167
/*[ENDIF] JAVA_SPEC_VERSION >= 15 */
165168
private static native void initAnonClassLoader(InternalAnonymousClassLoader anonClassLoader);
166-
169+
/*[IF RAM_CLASS_CACHE_SUPPORT] */
170+
private static final boolean isRCPRestoreRun = VM.isRCPRestoreRun();
171+
/*[ENDIF] RAM_CLASS_CACHE_SUPPORT */
167172
/*[PR JAZZ 73143]: ClassLoader incorrectly discards class loading locks*/
168173
static final class ClassNameLockRef extends WeakReference<Object> implements Runnable {
169174
private static final ReferenceQueue<Object> queue = new ReferenceQueue<>();
@@ -425,8 +430,21 @@ private ClassLoader(Void staticMethodHolder, String classLoaderName, ClassLoader
425430
specialLoaderInited = (bootstrapClassLoader != null);
426431
/*[ENDIF] JAVA_SPEC_VERSION == 8 */
427432
if (specialLoaderInited) {
428-
if (!lazyClassLoaderInit) {
429-
VM.initializeClassLoader(this, VM.J9_CLASSLOADER_TYPE_OTHERS, isParallelCapable);
433+
/*[IF JAVA_SPEC_VERSION > 8]*/
434+
/*
435+
* Assuming the 3rd classloader initialized is application class loader as the order
436+
* to initialize builtin class loaders is defined in the static block of
437+
* openjdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java.
438+
*/
439+
if (!applicationClassLoaderInited) {
440+
assignImmortalClassLoader(VM.J9_CLASSLOADER_TYPE_APP, isParallelCapable);
441+
applicationClassLoaderInited = true;
442+
} else
443+
/*[ENDIF] JAVA_SPEC_VERSION > 8 */
444+
{
445+
if (!lazyClassLoaderInit) {
446+
VM.initializeClassLoader(this, VM.J9_CLASSLOADER_TYPE_OTHERS, isParallelCapable);
447+
}
430448
}
431449
/*[IF JAVA_SPEC_VERSION > 8]*/
432450
unnamedModule = new Module(this);
@@ -438,10 +456,10 @@ private ClassLoader(Void staticMethodHolder, String classLoaderName, ClassLoader
438456
// BootstrapClassLoader.unnamedModule is set by JVM_SetBootLoaderUnnamedModule
439457
unnamedModule = null;
440458
bootstrapClassLoader = this;
441-
VM.initializeClassLoader(bootstrapClassLoader, VM.J9_CLASSLOADER_TYPE_BOOT, false);
459+
assignImmortalClassLoader(VM.J9_CLASSLOADER_TYPE_BOOT, false);
442460
} else {
443461
// Assuming the second classloader initialized is platform classloader
444-
VM.initializeClassLoader(this, VM.J9_CLASSLOADER_TYPE_PLATFORM, false);
462+
assignImmortalClassLoader(VM.J9_CLASSLOADER_TYPE_PLATFORM, false);
445463
specialLoaderInited = true;
446464
unnamedModule = new Module(this);
447465
}
@@ -2646,4 +2664,24 @@ static NativeLibraries nativeLibrariesFor(ClassLoader loader) {
26462664
return (loader == null) ? BootLoader.getNativeLibraries() : loader.nativelibs;
26472665
}
26482666
/*[ENDIF] JAVA_SPEC_VERSION >= 24 */
2667+
2668+
/*[IF JAVA_SPEC_VERSION > 8]*/
2669+
/**
2670+
* Assign immortal class loaders for restore run.
2671+
*
2672+
* @param id class loader type
2673+
* @param isParallelCapable true if the loader has registered as parallel capable
2674+
*/
2675+
private final void assignImmortalClassLoader(int id, boolean isParallelCapable) {
2676+
/*[IF RAM_CLASS_CACHE_SUPPORT] */
2677+
if (isRCPRestoreRun) {
2678+
VM.rcpAssignClassLoader(this, id);
2679+
} else
2680+
/*[ENDIF] RAM_CLASS_CACHE_SUPPORT */
2681+
{
2682+
VM.initializeClassLoader(this, id, isParallelCapable);
2683+
}
2684+
}
2685+
/*[ENDIF] JAVA_SPEC_VERSION > 8 */
2686+
26492687
}

runtime/jcl/common/jclcinit.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@ static const J9IntConstantMapping intVMConstants[] = {
416416
{ J9VMCONSTANTPOOL_COMIBMOTIVMVM_J9_CLASSLOADER_TYPE_OTHERS, J9_CLASSLOADER_TYPE_OTHERS },
417417
{ J9VMCONSTANTPOOL_COMIBMOTIVMVM_J9_CLASSLOADER_TYPE_BOOT, J9_CLASSLOADER_TYPE_BOOT },
418418
{ J9VMCONSTANTPOOL_COMIBMOTIVMVM_J9_CLASSLOADER_TYPE_PLATFORM, J9_CLASSLOADER_TYPE_PLATFORM },
419+
{ J9VMCONSTANTPOOL_COMIBMOTIVMVM_J9_CLASSLOADER_TYPE_APP, J9_CLASSLOADER_TYPE_APP },
419420
{ J9VMCONSTANTPOOL_COMIBMOTIVMVM_J9CLASS_RESERVABLE_LOCK_WORD_INIT, J9ClassReservableLockWordInit },
420421
{ J9VMCONSTANTPOOL_COMIBMOTIVMVM_OBJECT_HEADER_LOCK_RESERVED, OBJECT_HEADER_LOCK_RESERVED },
421422
{ J9VMCONSTANTPOOL_COMIBMOTIVMVM_OBJECT_HEADER_LOCK_LEARNING, OBJECT_HEADER_LOCK_LEARNING },

runtime/jcl/common/jclvm.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,3 +582,22 @@ Java_com_ibm_oti_vm_VM_getjfrCMDLineOption(JNIEnv *env, jclass clazz)
582582
return jfrOption;
583583
}
584584
#endif /* defined(J9VM_OPT_JFR) */
585+
586+
/*
587+
* Check if VM is RCP restore run.
588+
*
589+
* @return JNI_TRUE: restore run, otherwise JNI_FALSE
590+
*/
591+
jboolean JNICALL
592+
Java_com_ibm_oti_vm_VM_isRCPRestoreRun(JNIEnv *env, jclass clazz)
593+
{
594+
jboolean result = JNI_FALSE;
595+
#if defined(J9VM_OPT_SNAPSHOTS)
596+
J9VMThread *currentThread = (J9VMThread *)env;
597+
J9JavaVM *vm = currentThread->javaVM;
598+
if (IS_RESTORE_RUN(vm)) {
599+
result = JNI_TRUE;
600+
}
601+
#endif /* defined(J9VM_OPT_SNAPSHOTS) */
602+
return result;
603+
}

runtime/jcl/common/stdinit.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,9 @@ internalInitializeJavaLangClassLoader(JNIEnv * env)
468468
#if defined(J9VM_OPT_SNAPSHOTS)
469469
/* Always use the persisted applicationClassLoader in restore runs. */
470470
if (IS_RESTORE_RUN(vm)) {
471+
#if JAVA_SPEC_VERSION == 8
471472
vmFuncs->initializeSnapshotClassLoaderObject(vm, vm->applicationClassLoader, J9_JNI_UNWRAP_REFERENCE(appClassLoader));
473+
#endif /* JAVA_SPEC_VERSION == 8 */
472474
} else
473475
#endif /* defined(J9VM_OPT_SNAPSHOTS) */
474476
{
@@ -503,7 +505,9 @@ internalInitializeJavaLangClassLoader(JNIEnv * env)
503505
#if defined(J9VM_OPT_SNAPSHOTS)
504506
/* Always use the persisted extensionClassLoader in restore runs. */
505507
if (IS_RESTORE_RUN(vm)) {
508+
#if JAVA_SPEC_VERSION == 8
506509
vmFuncs->initializeSnapshotClassLoaderObject(vm, vm->extensionClassLoader, classLoaderObject);
510+
#endif /* JAVA_SPEC_VERSION == 8 */
507511
} else
508512
#endif /* defined(J9VM_OPT_SNAPSHOTS) */
509513
if (NULL == vm->extensionClassLoader) {

runtime/jcl/exports.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ omr_add_exports(jclse
304304
Java_com_ibm_oti_vm_VM_setCommonData
305305
Java_com_ibm_oti_vm_VM_getJ9ConstantPoolFromJ9Class
306306
Java_com_ibm_oti_vm_VM_isJVMInSingleThreadedMode
307+
Java_com_ibm_oti_vm_VM_isRCPRestoreRun
307308
Java_com_ibm_rmi_io_IIOPInputStream_00024LUDCLStackWalkOptimizer_LUDCLMarkFrame
308309
Java_com_ibm_rmi_io_IIOPInputStream_00024LUDCLStackWalkOptimizer_LUDCLUnmarkFrameImpl
309310
Java_com_ibm_virtualization_management_internal_GuestOS_retrieveMemoryUsageImpl

runtime/oti/VMHelpers.hpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2301,6 +2301,44 @@ class VM_VMHelpers
23012301
#endif /* JAVA_SPEC_VERSION >= 19 */
23022302
return oldState;
23032303
}
2304+
2305+
/**
2306+
* Common function to initialize boot class loader.
2307+
*
2308+
* @param[in] currentThread the current J9VMThread
2309+
* @param[in] classLoaderObject class loader object
2310+
* @param[in] parallelCapable if true parallel capable, default false not capable (or ignored)
2311+
* @return true if successful, false if failed
2312+
*/
2313+
static VMINLINE bool
2314+
initializeBootClassLoader(J9VMThread *currentThread, j9object_t classLoaderObject, bool parallelCapable = false)
2315+
{
2316+
J9JavaVM *vm = currentThread->javaVM;
2317+
2318+
/* If called with bootLoader, assign the system one to this instance. */
2319+
J9ClassLoader *classLoaderStruct = vm->systemClassLoader;
2320+
j9object_t loaderObject = J9CLASSLOADER_CLASSLOADEROBJECT(currentThread, classLoaderStruct);
2321+
if (NULL != loaderObject) {
2322+
return false;
2323+
}
2324+
J9CLASSLOADER_SET_CLASSLOADEROBJECT(currentThread, classLoaderStruct, classLoaderObject);
2325+
if (parallelCapable) {
2326+
classLoaderStruct->flags |= J9CLASSLOADER_PARALLEL_CAPABLE;
2327+
}
2328+
VM_AtomicSupport::writeBarrier();
2329+
J9VMJAVALANGCLASSLOADER_SET_VMREF(currentThread, classLoaderObject, classLoaderStruct);
2330+
TRIGGER_J9HOOK_VM_CLASS_LOADER_INITIALIZED(vm->hookInterface, currentThread, classLoaderStruct);
2331+
2332+
J9ClassWalkState classWalkState;
2333+
J9Class *clazz = allClassesStartDo(&classWalkState, vm, classLoaderStruct);
2334+
while (NULL != clazz) {
2335+
J9VMJAVALANGCLASS_SET_CLASSLOADER(currentThread, clazz->classObject, classLoaderObject);
2336+
clazz = allClassesNextDo(&classWalkState);
2337+
}
2338+
allClassesEndDo(&classWalkState);
2339+
return true;
2340+
}
2341+
23042342
};
23052343

23062344
#endif /* VMHELPERS_HPP_ */

runtime/oti/j9consts.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,7 @@ extern "C" {
884884
#define J9_CLASSLOADER_TYPE_OTHERS 0
885885
#define J9_CLASSLOADER_TYPE_BOOT 1
886886
#define J9_CLASSLOADER_TYPE_PLATFORM 2
887+
#define J9_CLASSLOADER_TYPE_APP 3
887888

888889
/* Flag for Nestmates invokeVirtual on private methods */
889890
#define J9_VTABLE_INDEX_DIRECT_METHOD_FLAG 0x1

runtime/oti/vmconstantpool.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,7 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-ex
582582
<staticfieldref class="com/ibm/oti/vm/VM" name="J9_CLASSLOADER_TYPE_OTHERS" signature="I"/>
583583
<staticfieldref class="com/ibm/oti/vm/VM" name="J9_CLASSLOADER_TYPE_BOOT" signature="I"/>
584584
<staticfieldref class="com/ibm/oti/vm/VM" name="J9_CLASSLOADER_TYPE_PLATFORM" signature="I"/>
585+
<staticfieldref class="com/ibm/oti/vm/VM" name="J9_CLASSLOADER_TYPE_APP" signature="I"/>
585586

586587
<staticfieldref class="com/ibm/oti/vm/VM" name="J9CLASS_RESERVABLE_LOCK_WORD_INIT" signature="I"/>
587588
<staticfieldref class="com/ibm/oti/vm/VM" name="OBJECT_HEADER_LOCK_RESERVED" signature="I"/>

runtime/vm/BytecodeInterpreter.hpp

Lines changed: 12 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4937,45 +4937,22 @@ class INTERPRETER_CLASS
49374937
goto done;
49384938
}
49394939
if (J9_CLASSLOADER_TYPE_BOOT == loaderType) {
4940-
/* if called with bootLoader, assign the system one to this instance */
4941-
J9ClassLoader *classLoaderStruct = _vm->systemClassLoader;
4942-
j9object_t loaderObject = J9CLASSLOADER_CLASSLOADEROBJECT(_currentThread, classLoaderStruct);
4943-
if (NULL != loaderObject) {
4940+
if (!VM_VMHelpers::initializeBootClassLoader(_currentThread, classLoaderObject, 0 != parallelCapable)) {
49444941
goto internalError;
49454942
}
4946-
J9CLASSLOADER_SET_CLASSLOADEROBJECT(_currentThread, classLoaderStruct, classLoaderObject);
4947-
if (parallelCapable) {
4948-
classLoaderStruct->flags |= J9CLASSLOADER_PARALLEL_CAPABLE;
4949-
}
4950-
VM_AtomicSupport::writeBarrier();
4951-
J9VMJAVALANGCLASSLOADER_SET_VMREF(_currentThread, classLoaderObject, classLoaderStruct);
4952-
TRIGGER_J9HOOK_VM_CLASS_LOADER_INITIALIZED(_vm->hookInterface, _currentThread, classLoaderStruct);
4953-
4954-
J9ClassWalkState classWalkState;
4955-
J9Class* clazz = allClassesStartDo(&classWalkState, _vm, classLoaderStruct);
4956-
while (NULL != clazz) {
4957-
J9VMJAVALANGCLASS_SET_CLASSLOADER(_currentThread, clazz->classObject, classLoaderObject);
4958-
clazz = allClassesNextDo(&classWalkState);
4959-
}
4960-
allClassesEndDo(&classWalkState);
49614943
} else {
49624944
updateVMStruct(REGISTER_ARGS);
4963-
#if defined(J9VM_OPT_SNAPSHOTS)
4964-
if (IS_RESTORE_RUN(_vm) && (J9_CLASSLOADER_TYPE_PLATFORM == loaderType)) {
4965-
_vm->internalVMFunctions->initializeSnapshotClassLoaderObject(_vm, _vm->extensionClassLoader, classLoaderObject);
4966-
} else
4967-
#endif /* defined(J9VM_OPT_SNAPSHOTS) */
4968-
{
4969-
J9ClassLoader *result = internalAllocateClassLoader(_vm, classLoaderObject);
4970-
VMStructHasBeenUpdated(REGISTER_ARGS); // likely unnecessary - no code runs in internalAllocateClassLoader
4971-
if (NULL == result) {
4972-
rc = GOTO_THROW_CURRENT_EXCEPTION;
4973-
goto done;
4974-
}
4975-
if (J9_CLASSLOADER_TYPE_PLATFORM == loaderType) {
4976-
/* extensionClassLoader holds the platform class loader in Java 11+ */
4977-
_vm->extensionClassLoader = result;
4978-
}
4945+
J9ClassLoader *result = internalAllocateClassLoader(_vm, classLoaderObject);
4946+
VMStructHasBeenUpdated(REGISTER_ARGS);
4947+
if (NULL == result) {
4948+
rc = GOTO_THROW_CURRENT_EXCEPTION;
4949+
goto done;
4950+
}
4951+
if (J9_CLASSLOADER_TYPE_PLATFORM == loaderType) {
4952+
/* extensionClassLoader holds the platform class loader in Java 11+. */
4953+
_vm->extensionClassLoader = result;
4954+
} else if (J9_CLASSLOADER_TYPE_APP == loaderType) {
4955+
_vm->applicationClassLoader = result;
49794956
}
49804957
}
49814958
restoreInternalNativeStackFrame(REGISTER_ARGS);

0 commit comments

Comments
 (0)