Skip to content

Commit

Permalink
Add classPathEntries to the VM snapshot
Browse files Browse the repository at this point in the history
Related: eclipse-openj9#20612
Signed-off-by: Nathan Henderson <[email protected]>
  • Loading branch information
ThanHenderson committed Dec 10, 2024
1 parent 3f7abb5 commit cd9d0ed
Show file tree
Hide file tree
Showing 9 changed files with 161 additions and 31 deletions.
5 changes: 4 additions & 1 deletion runtime/bcutil/dynload.c
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,10 @@ readZip (J9JavaVM * javaVM, J9ClassPathEntry * cpEntry) {
U_32 size;
IDATA filenameLength;

zipFile = (VMIZipFile *) (cpEntry->extraInfo);
if (IS_RESTORE_RUN(javaVM) && (NULL == cpEntry->extraInfo)) {
javaVM->internalVMFunctions->initializeClassPathEntry(javaVM, cpEntry);
}
zipFile = (VMIZipFile *)(cpEntry->extraInfo);

/* Find the desired entry, if it is present. */
filenameLength = strlen((const char*)javaVM->dynamicLoadBuffers->searchFilenameBuffer);
Expand Down
27 changes: 22 additions & 5 deletions runtime/jcl/common/stdinit.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ static char * addEndorsedPath(J9PortLibrary *portLib, char *endorsedPath, char *

static J9Class jclFakeClass;

/* initializeBootstrapClassPath return values. */
#define INIT_BOOTSTRAP_CLASS_PATH_SUCCESS 0
#define INIT_BOOTSTRAP_CLASS_PATH_RESTORED 1
#define INIT_BOOTSTRAP_CLASS_PATH_ALREADY_SET -2
#define INIT_BOOTSTRAP_CLASS_PATH_FAILED -1

/**
* Compute the JCL runtime flags to be used during the initialization of
* known classes.
Expand Down Expand Up @@ -123,7 +129,13 @@ standardInit(J9JavaVM *vm, char *dllName)
}
}
/* Now create the classPathEntries */
if (initializeBootstrapClassPath(vm) && !IS_RESTORE_RUN(vm)) {
switch (initializeBootstrapClassPath(vm)) {
case INIT_BOOTSTRAP_CLASS_PATH_SUCCESS:
break;
case INIT_BOOTSTRAP_CLASS_PATH_RESTORED:
Assert_JCL_true(IS_RESTORE_RUN(vm));
break;
default:
goto _fail;
}
#endif
Expand Down Expand Up @@ -622,9 +634,14 @@ initializeBootstrapClassPath(J9JavaVM *vm)
}
(*VMI)->GetSystemProperty(VMI, BOOT_PATH_SEPARATOR_SYS_PROP, &classpathSeparator);

/* Fail if the classpath has already been set */
if (IS_RESTORE_RUN(vm)) {
Assert_JCL_true(J9_ARE_ALL_BITS_SET(loader->flags, J9CLASSLOADER_CLASSPATH_SET));
return INIT_BOOTSTRAP_CLASS_PATH_RESTORED;
}

/* Fail if the classpath has already been set. */
if (J9_ARE_ALL_BITS_SET(loader->flags, J9CLASSLOADER_CLASSPATH_SET)) {
return -2;
return INIT_BOOTSTRAP_CLASS_PATH_ALREADY_SET;
}

#if defined(J9VM_OPT_SHARED_CLASSES)
Expand All @@ -639,7 +656,7 @@ initializeBootstrapClassPath(J9JavaVM *vm)
loader->classPathEntryCount = vmFuncs->initializeClassPath(vm, path, classpathSeparator[0], CPE_FLAG_BOOTSTRAP, initClassPathEntry, &loader->classPathEntries);

if (-1 == (IDATA)loader->classPathEntryCount) {
return -1;
return INIT_BOOTSTRAP_CLASS_PATH_FAILED;
} else {
omrthread_rwmutex_init(&loader->cpEntriesMutex, 0, "classPathEntries Mutex");
loader->initClassPathEntryCount = loader->classPathEntryCount;
Expand All @@ -649,7 +666,7 @@ initializeBootstrapClassPath(J9JavaVM *vm)
TRIGGER_J9HOOK_VM_CLASS_LOADER_CLASSPATH_ENTRIES_INITIALIZED(vm->hookInterface, vm, loader);
}

return 0;
return INIT_BOOTSTRAP_CLASS_PATH_SUCCESS;
}

static UDATA
Expand Down
2 changes: 2 additions & 0 deletions runtime/oti/j9port_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,8 @@ typedef struct VMSnapshotImplPortLibrary {
VMSNAPSHOTIMPL_OMRPORT_FROM_VMSNAPSHOTIMPLPORT(privateImagePortLibrary)->mem_allocate_memory32(VMSNAPSHOTIMPL_OMRPORT_FROM_VMSNAPSHOTIMPLPORT(privateImagePortLibrary), param1, J9_GET_CALLSITE(), category)
#define vmsnapshot_free_memory32(param1) \
VMSNAPSHOTIMPL_OMRPORT_FROM_VMSNAPSHOTIMPLPORT(privateImagePortLibrary)->mem_free_memory32(VMSNAPSHOTIMPL_OMRPORT_FROM_VMSNAPSHOTIMPLPORT(privateImagePortLibrary), param1)
#define vmsnapshot_reallocate_memory(param1, param2, category) \
VMSNAPSHOTIMPL_OMRPORT_FROM_VMSNAPSHOTIMPLPORT(privateImagePortLibrary)->mem_reallocate_memory(VMSNAPSHOTIMPL_OMRPORT_FROM_VMSNAPSHOTIMPLPORT(privateImagePortLibrary), param1, param2, J9_GET_CALLSITE(), category)
#endif /* defined(J9VM_OPT_SNAPSHOTS) */

#if defined(OMR_OPT_CUDA)
Expand Down
32 changes: 26 additions & 6 deletions runtime/util/cphelp.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,15 @@ addJarToSystemClassLoaderClassPathEntries(J9JavaVM *vm, const char *filename)
J9ClassPathEntry *cpEntry = NULL;

PORT_ACCESS_FROM_JAVAVM(vm);
cpEntry = (J9ClassPathEntry*) j9mem_allocate_memory(newMemSize, OMRMEM_CATEGORY_VM);
#if defined(J9VM_OPT_SNAPSHOTS)
VMSNAPSHOTIMPLPORT_ACCESS_FROM_JAVAVM(vm);
if (IS_SNAPSHOTTING_ENABLED(vm)) {
cpEntry = (J9ClassPathEntry *)vmsnapshot_allocate_memory(newMemSize, OMRMEM_CATEGORY_VM);
} else
#endif /* defined(J9VM_OPT_SNAPSHOTS) */
{
cpEntry = (J9ClassPathEntry *)j9mem_allocate_memory(newMemSize, OMRMEM_CATEGORY_VM);
}
if (NULL != cpEntry) {
J9ClassPathEntry **cpePtrArray = NULL;
UDATA entryCount = 0;
Expand All @@ -219,8 +227,7 @@ addJarToSystemClassLoaderClassPathEntries(J9JavaVM *vm, const char *filename)
cpEntry->type = CPE_TYPE_UNKNOWN;
cpEntry->flags = CPE_FLAG_BOOTSTRAP;

#if defined(J9VM_OPT_SHARED_CLASSES)
if (J9_ARE_ALL_BITS_SET(classLoader->flags, J9CLASSLOADER_SHARED_CLASSES_ENABLED)) {
if (J9_ARE_ALL_BITS_SET(classLoader->flags, J9CLASSLOADER_SHARED_CLASSES_ENABLED) || IS_RESTORE_RUN(vm)) {
/*
* Warm up the classpath entry so that the Classpath stored in the cache has the correct info.
* This is required because when we are finding classes in the cache, initializeClassPathEntry is not called
Expand All @@ -229,7 +236,6 @@ addJarToSystemClassLoaderClassPathEntries(J9JavaVM *vm, const char *filename)
goto done;
}
}
#endif
omrthread_rwmutex_enter_write(classLoader->cpEntriesMutex);
entryCount = classLoader->classPathEntryCount;
cpePtrArray = classLoader->classPathEntries;
Expand All @@ -239,7 +245,14 @@ addJarToSystemClassLoaderClassPathEntries(J9JavaVM *vm, const char *filename)
/* class path entry pointer array needs to be incremented */
UDATA count = ROUND_UP_TO(CPE_COUNT_INCREMENT, entryCount + 1);
newMemSize = sizeof(J9ClassPathEntry*) * count;
cpePtrArray = (J9ClassPathEntry **)j9mem_reallocate_memory(cpePtrArray, newMemSize, OMRMEM_CATEGORY_VM);
#if defined(J9VM_OPT_SNAPSHOTS)
if (IS_SNAPSHOTTING_ENABLED(vm)) {
cpePtrArray = (J9ClassPathEntry **)vmsnapshot_reallocate_memory(cpePtrArray, newMemSize, OMRMEM_CATEGORY_VM);
} else
#endif /* defined(J9VM_OPT_SNAPSHOTS) */
{
cpePtrArray = (J9ClassPathEntry **)j9mem_reallocate_memory(cpePtrArray, newMemSize, OMRMEM_CATEGORY_VM);
}
if (NULL == cpePtrArray) {
goto done;
} else {
Expand All @@ -257,7 +270,14 @@ addJarToSystemClassLoaderClassPathEntries(J9JavaVM *vm, const char *filename)
done:
/* If any error occurred, discard any allocated memory and throw OutOfMemoryError */
if (0 == newCount) {
j9mem_free_memory(cpEntry);
#if defined(J9VM_OPT_SNAPSHOTS)
if (IS_SNAPSHOTTING_ENABLED(vm)) {
vmsnapshot_free_memory(cpEntry);
} else
#endif /* defined(J9VM_OPT_SNAPSHOTS) */
{
j9mem_free_memory(cpEntry);
}
} else {
TRIGGER_J9HOOK_VM_CLASS_LOADER_CLASSPATH_ENTRY_ADDED(vm->hookInterface, vm, classLoader, cpEntry);
}
Expand Down
34 changes: 29 additions & 5 deletions runtime/vm/VMSnapshotImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

void snapshot_mem_free_memory(struct OMRPortLibrary *portLibrary, void *memoryPointer);
void *snapshot_mem_allocate_memory(struct OMRPortLibrary *portLibrary, uintptr_t byteAmount, const char *callSite, uint32_t category);
void *snapshot_mem_reallocate_memory(struct OMRPortLibrary *portLibrary, void *memoryPointer, uintptr_t byteAmount, const char *callSite, uint32_t category);
void snapshot_mem_free_memory32(struct OMRPortLibrary *portLibrary, void *memoryPointer);
void *snapshot_mem_allocate_memory32(struct OMRPortLibrary *portLibrary, uintptr_t byteAmount, const char *callSite, uint32_t category);

Expand Down Expand Up @@ -507,7 +508,6 @@ VMSnapshotImpl::fixupClassLoaders()
pool_state classLoaderWalkState = {0};
J9ClassLoader *currentClassLoader = (J9ClassLoader *)pool_startDo(_vm->classLoaderBlocks, &classLoaderWalkState);
while (NULL != currentClassLoader) {
currentClassLoader->classPathEntries = NULL;
currentClassLoader->sharedLibraries = NULL;
currentClassLoader->librariesHead = NULL;
currentClassLoader->librariesTail = NULL;
Expand All @@ -524,12 +524,23 @@ VMSnapshotImpl::fixupClassLoaders()
#endif /* J9VM_NEEDS_JNI_REDIRECTION */
currentClassLoader->gcRememberedSet = 0;
currentClassLoader->jitMetaDataList = NULL;
/* TODO: In the future persist these as well. */
currentClassLoader->flags &= ~J9CLASSLOADER_CLASSPATH_SET;

fixupClassPathEntries(currentClassLoader);
currentClassLoader = (J9ClassLoader *)pool_nextDo(&classLoaderWalkState);
}
}

void
VMSnapshotImpl::fixupClassPathEntries(J9ClassLoader *classLoader)
{
J9ClassPathEntry **cpEntries = classLoader->classPathEntries;
UDATA classPathEntryCount = classLoader->classPathEntryCount;

for (UDATA i = 0; i < classPathEntryCount; i++) {
cpEntries[i]->extraInfo = NULL;
}
}

/* TODO: Once all class loaders are supported, this won't be needed. */
void
VMSnapshotImpl::removeUnpersistedClassLoaders()
Expand Down Expand Up @@ -836,11 +847,15 @@ VMSnapshotImpl::restoreJ9JavaVMStructures()
restorePrimitiveAndArrayClasses();
restoreHiddenInstanceFields();

if (omrthread_monitor_init_with_name(&_vm->classMemorySegments->segmentMutex, 0, "VM class mem segment list")) {
if (J9THREAD_RWMUTEX_OK != omrthread_rwmutex_init(&_vm->systemClassLoader->cpEntriesMutex, 0, "classPathEntries Mutex")) {
success = false;
}

if (omrthread_monitor_init_with_name(&_vm->memorySegments->segmentMutex, 0, "VM mem segment list")) {
if (0 != omrthread_monitor_init_with_name(&_vm->classMemorySegments->segmentMutex, 0, "VM class mem segment list")) {
success = false;
}

if (0 != omrthread_monitor_init_with_name(&_vm->memorySegments->segmentMutex, 0, "VM mem segment list")) {
success = false;
}

Expand Down Expand Up @@ -1165,4 +1180,13 @@ snapshot_mem_free_memory(struct OMRPortLibrary *portLibrary, void *memoryPointer
vmSnapshotImpl->freeSubAllocatedMemory(memoryPointer, false);
}

void *
snapshot_mem_reallocate_memory(struct OMRPortLibrary *portLibrary, void *memoryPointer, uintptr_t byteAmount, const char *callSite, uint32_t category)
{
VMSnapshotImpl *vmSnapshotImpl = (VMSnapshotImpl *)((VMSnapshotImplPortLibrary *)portLibrary)->vmSnapshotImpl;
Assert_VM_notNull(vmSnapshotImpl);

return vmSnapshotImpl->reallocateMemory(memoryPointer, byteAmount, false);
}

#endif /* defined(J9VM_OPT_SNAPSHOTS) */
2 changes: 1 addition & 1 deletion runtime/vm/VMSnapshotImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class VMSnapshotImpl
void fixupArrayClass(J9ArrayClass *clazz);
void fixupMethodRunAddresses(J9Class *ramClass);
void fixupConstantPool(J9Class *ramClass);
void fixupClassPathEntries();
void fixupClassPathEntries(J9ClassLoader *classLoader);
void removeUnpersistedClassLoaders();
void saveJ9JavaVMStructures();
void restorePrimitiveAndArrayClasses();
Expand Down
10 changes: 9 additions & 1 deletion runtime/vm/classallocation.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,15 @@ freeClassLoader(J9ClassLoader *classLoader, J9JavaVM *javaVM, J9VMThread *vmThre
if (javaVM->systemClassLoader == classLoader) {
if (NULL != classLoader->classPathEntries) {
freeClassLoaderEntries(vmThread, classLoader->classPathEntries, classLoader->classPathEntryCount, classLoader->initClassPathEntryCount);
j9mem_free_memory(classLoader->classPathEntries);
#if defined(J9VM_OPT_SNAPSHOTS)
VMSNAPSHOTIMPLPORT_ACCESS_FROM_JAVAVM(javaVM);
if (IS_SNAPSHOTTING_ENABLED(javaVM)) {
vmsnapshot_free_memory(classLoader->classPathEntries);
} else
#endif /* defined(J9VM_OPT_SNAPSHOTS) */
{
j9mem_free_memory(classLoader->classPathEntries);
}
classLoader->classPathEntryCount = 0;
classLoader->classPathEntries = NULL;
}
Expand Down
41 changes: 37 additions & 4 deletions runtime/vm/jvmfree.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ freeClassLoaderEntries(J9VMThread * vmThread, J9ClassPathEntry **entries, UDATA
U_32 i = 0;
J9ClassPathEntry *cpEntry = NULL;
PORT_ACCESS_FROM_VMC(vmThread);
#if defined(J9VM_OPT_SNAPSHOTS)
VMSNAPSHOTIMPLPORT_ACCESS_FROM_JAVAVM(vm);
#endif /* defined(J9VM_OPT_SNAPSHOTS) */

Trc_VM_freeClassLoaderEntries_Entry(vmThread, entries, count);

Expand Down Expand Up @@ -85,12 +88,26 @@ freeClassLoaderEntries(J9VMThread * vmThread, J9ClassPathEntry **entries, UDATA
cpEntry->pathLength = 0;
if (i >= initCount) {
/* Additional entries are appended after initial entries, allocated separately. */
j9mem_free_memory(cpEntry);
#if defined(J9VM_OPT_SNAPSHOTS)
if (IS_SNAPSHOTTING_ENABLED(vm)) {
vmsnapshot_free_memory(cpEntry);
} else
#endif /* defined(J9VM_OPT_SNAPSHOTS) */
{
j9mem_free_memory(cpEntry);
}
}
}
/* Initial entries are allocated together, free them together. */
if (count > 0) {
j9mem_free_memory(entries[0]);
#if defined(J9VM_OPT_SNAPSHOTS)
if (IS_SNAPSHOTTING_ENABLED(vm)) {
vmsnapshot_free_memory(entries[0]);
} else
#endif /* defined(J9VM_OPT_SNAPSHOTS) */
{
j9mem_free_memory(entries[0]);
}
}

Trc_VM_freeClassLoaderEntries_Exit(vmThread);
Expand Down Expand Up @@ -122,7 +139,15 @@ freeSharedCacheCLEntries(J9VMThread * vmThread, J9ClassLoader * classloader)
}
pool_removeElement(cpCachePool, (void *)cachePoolItem);
}
j9mem_free_memory(classloader->classPathEntries);
#if defined(J9VM_OPT_SNAPSHOTS)
if (IS_SNAPSHOTTING_ENABLED(vm)) {
VMSNAPSHOTIMPLPORT_ACCESS_FROM_JAVAVM(vm);
vmsnapshot_free_memory(classloader->classPathEntries);
} else
#endif /* defined(J9VM_OPT_SNAPSHOTS) */
{
j9mem_free_memory(classloader->classPathEntries);
}
classloader->classPathEntries = NULL;
classloader->classPathEntryCount = 0;
omrthread_monitor_exit(sharedClassConfig->jclCacheMutex);
Expand Down Expand Up @@ -418,7 +443,15 @@ cleanUpClassLoader(J9VMThread *vmThread, J9ClassLoader* classLoader)
PORT_ACCESS_FROM_VMC(vmThread);
/* Free the class path entries in system class loader */
freeClassLoaderEntries(vmThread, classLoader->classPathEntries, classLoader->classPathEntryCount, classLoader->initClassPathEntryCount);
j9mem_free_memory(classLoader->classPathEntries);
#if defined(J9VM_OPT_SNAPSHOTS)
VMSNAPSHOTIMPLPORT_ACCESS_FROM_JAVAVM(javaVM);
if (IS_SNAPSHOTTING_ENABLED(javaVM)) {
vmsnapshot_free_memory(classLoader->classPathEntries);
} else
#endif /* defined(J9VM_OPT_SNAPSHOTS) */
{
j9mem_free_memory(classLoader->classPathEntries);
}
classLoader->classPathEntryCount = 0;
classLoader->classPathEntries = NULL;
if (NULL != classLoader->cpEntriesMutex) {
Expand Down
39 changes: 31 additions & 8 deletions runtime/vm/jvminit.c
Original file line number Diff line number Diff line change
Expand Up @@ -1524,6 +1524,9 @@ initializeClassPath(J9JavaVM *vm, char *classPath, U_8 classPathSeparator, U_16
BOOLEAN lastWasSeparator = TRUE;

PORT_ACCESS_FROM_JAVAVM(vm);
#if defined(J9VM_OPT_SNAPSHOTS)
VMSNAPSHOTIMPLPORT_ACCESS_FROM_JAVAVM(vm);
#endif /* defined(J9VM_OPT_SNAPSHOTS) */

if (NULL == classPath) {
*classPathEntries = NULL;
Expand Down Expand Up @@ -1555,16 +1558,36 @@ initializeClassPath(J9JavaVM *vm, char *classPath, U_8 classPathSeparator, U_16

cpePtrArraySize = ROUND_UP_TO(CPE_COUNT_INCREMENT, classPathEntryCount);
cpePtrArrayMemSize = sizeof(*classPathEntries) * cpePtrArraySize;
cpePtrArray = (J9ClassPathEntry**)j9mem_allocate_memory(cpePtrArrayMemSize, OMRMEM_CATEGORY_VM);
#if defined(J9VM_OPT_SNAPSHOTS)
if (IS_SNAPSHOTTING_ENABLED(vm)) {
cpePtrArray = (J9ClassPathEntry **)vmsnapshot_allocate_memory(cpePtrArrayMemSize, OMRMEM_CATEGORY_VM);
} else
#endif /* defined(J9VM_OPT_SNAPSHOTS) */
{
cpePtrArray = (J9ClassPathEntry **)j9mem_allocate_memory(cpePtrArrayMemSize, OMRMEM_CATEGORY_VM);
}
/* classPathEntryCount is for number of null characters */
classPathMemSize = (sizeof(J9ClassPathEntry) * classPathEntryCount) + classPathLength + classPathEntryCount;
cpEntries = j9mem_allocate_memory(classPathMemSize, OMRMEM_CATEGORY_VM);
#if defined(J9VM_OPT_SNAPSHOTS)
if (IS_SNAPSHOTTING_ENABLED(vm)) {
cpEntries = vmsnapshot_allocate_memory(classPathMemSize, OMRMEM_CATEGORY_VM);
} else
#endif /* defined(J9VM_OPT_SNAPSHOTS) */
{
cpEntries = j9mem_allocate_memory(classPathMemSize, OMRMEM_CATEGORY_VM);
}

if ((NULL == cpePtrArray)
|| (NULL == cpEntries)
) {
j9mem_free_memory(cpePtrArray);
j9mem_free_memory(cpEntries);
if ((NULL == cpePtrArray) || (NULL == cpEntries)) {
#if defined(J9VM_OPT_SNAPSHOTS)
if (IS_SNAPSHOTTING_ENABLED(vm)) {
vmsnapshot_free_memory(cpePtrArray);
vmsnapshot_free_memory(cpEntries);
} else
#endif /* defined(J9VM_OPT_SNAPSHOTS) */
{
j9mem_free_memory(cpePtrArray);
j9mem_free_memory(cpEntries);
}
*classPathEntries = NULL;
classPathEntryCount = -1;
} else {
Expand Down Expand Up @@ -1619,7 +1642,7 @@ initializeClassPathEntry (J9JavaVM * javaVM, J9ClassPathEntry *cpEntry)
int32_t attr = 0;

/* If we know what it is, then go for it */
if (CPE_TYPE_UNKNOWN != cpEntry->type) {
if ((CPE_TYPE_UNKNOWN != cpEntry->type) && !IS_RESTORE_RUN(javaVM)) {
return (IDATA)cpEntry->type;
}

Expand Down

0 comments on commit cd9d0ed

Please sign in to comment.