diff --git a/runtime/bcutil/dynload.c b/runtime/bcutil/dynload.c index d78feb2e655..05a10940ee7 100644 --- a/runtime/bcutil/dynload.c +++ b/runtime/bcutil/dynload.c @@ -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); diff --git a/runtime/jcl/common/stdinit.c b/runtime/jcl/common/stdinit.c index 378d68be92e..b1bb3bd2144 100644 --- a/runtime/jcl/common/stdinit.c +++ b/runtime/jcl/common/stdinit.c @@ -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. @@ -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 @@ -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) @@ -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; @@ -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 diff --git a/runtime/oti/j9port_generated.h b/runtime/oti/j9port_generated.h index ffd094eed48..fdba90d894c 100644 --- a/runtime/oti/j9port_generated.h +++ b/runtime/oti/j9port_generated.h @@ -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) diff --git a/runtime/util/cphelp.c b/runtime/util/cphelp.c index 9b7c8e85cb8..2db38a8b759 100644 --- a/runtime/util/cphelp.c +++ b/runtime/util/cphelp.c @@ -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; @@ -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 @@ -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; @@ -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 { @@ -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); } diff --git a/runtime/vm/VMSnapshotImpl.cpp b/runtime/vm/VMSnapshotImpl.cpp index 3d3a19883c0..3b5e6455014 100644 --- a/runtime/vm/VMSnapshotImpl.cpp +++ b/runtime/vm/VMSnapshotImpl.cpp @@ -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); @@ -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; @@ -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() @@ -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; } @@ -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) */ diff --git a/runtime/vm/VMSnapshotImpl.hpp b/runtime/vm/VMSnapshotImpl.hpp index 84c831740cf..cd44977c55b 100644 --- a/runtime/vm/VMSnapshotImpl.hpp +++ b/runtime/vm/VMSnapshotImpl.hpp @@ -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(); diff --git a/runtime/vm/classallocation.c b/runtime/vm/classallocation.c index 27b6245cc54..1c64575a532 100644 --- a/runtime/vm/classallocation.c +++ b/runtime/vm/classallocation.c @@ -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; } diff --git a/runtime/vm/jvmfree.c b/runtime/vm/jvmfree.c index 560c2ecfcde..0128bacee05 100644 --- a/runtime/vm/jvmfree.c +++ b/runtime/vm/jvmfree.c @@ -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); @@ -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); @@ -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); @@ -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) { diff --git a/runtime/vm/jvminit.c b/runtime/vm/jvminit.c index eb6b7fc8b24..f0a57ee5154 100644 --- a/runtime/vm/jvminit.c +++ b/runtime/vm/jvminit.c @@ -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; @@ -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 { @@ -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; }