diff --git a/runtime/j9vm/java11vmi.c b/runtime/j9vm/java11vmi.c index b4aab4f8a25..ecb4b67e4b3 100644 --- a/runtime/j9vm/java11vmi.c +++ b/runtime/j9vm/java11vmi.c @@ -61,7 +61,7 @@ extern J9JavaVM *BFUjavaVM; /* from jvm.c */ * b) If performing a hash operation, it assumes the caller has already locked vm->classLoaderModuleAndLocationMutex */ static UDATA hashPackageTableDelete(J9VMThread * currentThread, J9ClassLoader * classLoader, const char *packageName); -static J9Package * createPackage(J9VMThread * currentThread, J9Module * fromModule, const char *package); +static J9Package *createPackage(J9VMThread *currentThread, J9Module *fromModule, J9UTF8 *package); static void freePackageDefinition(J9VMThread * currentThread, J9ClassLoader * classLoader, const char *packageName); static BOOLEAN removePackageDefinition(J9VMThread * currentThread, J9Module * fromModule, const char *packageName); static BOOLEAN addPackageDefinition(J9VMThread * currentThread, J9Module * fromModule, const char *package); @@ -80,9 +80,12 @@ static void trcModulesAddModuleExports(J9VMThread * currentThread, J9Module * fr static void trcModulesAddModulePackage(J9VMThread *currentThread, J9Module *j9mod, const char *package); static UDATA hashTableAtPut(J9HashTable * table, void * value, BOOLEAN collisionIsFailure); static void throwExceptionHelper(J9VMThread * currentThread, UDATA errCode); -static void freePackage(J9VMThread * currentThread, J9Package * j9package); +static void freePackage(J9VMThread *currentThread, J9Package *j9package); static J9ClassLoader * getModuleObjectClassLoader(J9VMThread * currentThread, j9object_t moduleObject); static J9Module *createModule(J9VMThread *currentThread, j9object_t moduleObject, J9ClassLoader *classLoader, J9UTF8 *moduleName); +#if defined(J9VM_OPT_SNAPSHOTS) +static J9Module *restoreModule(J9VMThread *currentThread, J9ClassLoader *classLoader, J9UTF8 *moduleName, j9object_t moduleObject, jstring moduleVersion); +#endif /* defined(J9VM_OPT_SNAPSHOTS) */ static J9Module * getJ9Module(J9VMThread * currentThread, jobject module); static BOOLEAN isModuleNameValid(j9object_t moduleName); static BOOLEAN isModuleJavaBase(j9object_t moduleName); @@ -200,37 +203,41 @@ throwExceptionHelper(J9VMThread *currentThread, UDATA errCode) } static void -freePackage(J9VMThread * currentThread, J9Package * j9package) +freePackage(J9VMThread *currentThread, J9Package *j9package) { if (NULL != j9package) { - J9JavaVM * const vm = currentThread->javaVM; + J9JavaVM *const vm = currentThread->javaVM; PORT_ACCESS_FROM_JAVAVM(vm); if (NULL != j9package->exportsHashTable) { hashTableFree(j9package->exportsHashTable); } - j9mem_free_memory((void *) j9package->packageName); +#if defined(J9VM_OPT_SNAPSHOTS) + if (IS_SNAPSHOTTING_ENABLED(vm)) { + VMSNAPSHOTIMPLPORT_ACCESS_FROM_JAVAVM(vm); + vmsnapshot_free_memory((void *)j9package->packageName); + } else +#endif /* defined(J9VM_OPT_SNAPSHOTS) */ + { + j9mem_free_memory((void *)j9package->packageName); + } pool_removeElement(vm->modularityPool, j9package); } } static J9Package * -createPackage(J9VMThread * currentThread, J9Module * fromModule, const char *package) +createPackage(J9VMThread *currentThread, J9Module *fromModule, J9UTF8 *packageName) { - J9JavaVM * const vm = currentThread->javaVM; - J9InternalVMFunctions const * const vmFuncs = vm->internalVMFunctions; - J9Package * retval = NULL; + J9JavaVM *const vm = currentThread->javaVM; + J9InternalVMFunctions const *const vmFuncs = vm->internalVMFunctions; + J9Package *retval = NULL; - J9ClassLoader * const classLoader = fromModule->classLoader; - J9Package * j9package = pool_newElement(vm->modularityPool); + J9Package *j9package = pool_newElement(vm->modularityPool); if (NULL != j9package) { j9package->module = fromModule; j9package->classLoader = fromModule->classLoader; - if (!addUTFNameToPackage(currentThread, j9package, package, NULL, 0)) { - freePackage(currentThread, j9package); - return retval; - } + j9package->packageName = packageName; j9package->exportsHashTable = vmFuncs->hashModulePointerTableNew(vm, INITIAL_INTERNAL_MODULE_HASHTABLE_SIZE); if (NULL != j9package->exportsHashTable) { retval = j9package; @@ -315,6 +322,107 @@ createModule(J9VMThread *currentThread, j9object_t moduleObject, J9ClassLoader * return retval; } +#if defined(J9VM_OPT_SNAPSHOTS) +static J9Module * +restoreModule(J9VMThread *currentThread, J9ClassLoader *classLoader, J9UTF8 *moduleName, j9object_t moduleObject, jstring moduleVersion) +{ + J9JavaVM *vm = currentThread->javaVM; + J9InternalVMFunctions const *const vmFuncs = vm->internalVMFunctions; + J9ClassLoader *systemClassLoader = vm->systemClassLoader; + BOOLEAN firstModule = J9_ARE_NO_BITS_SET(vm->runtimeFlags, J9_RUNTIME_JAVA_BASE_MODULE_CREATED); + J9Module *ret = NULL; + PORT_ACCESS_FROM_VMC(currentThread); + + J9Module *module = hashModuleTableAtWithUTF8Name(currentThread, classLoader, moduleName); + + if (NULL != module) { + const char *moduleNameData = (const char *)J9UTF8_DATA(moduleName); + module->moduleObject = moduleObject; + /* Bind J9Module and module object via the hidden field. */ + J9OBJECT_ADDRESS_STORE(currentThread, moduleObject, vm->modulePointerOffset, module); + + if (NULL != moduleVersion) { + module->version = J9_JNI_UNWRAP_REFERENCE(moduleVersion); + } + + if (firstModule) { + /* The first module must be "java.base". */ + J9ClassWalkState classWalkState = {0}; + J9Class *clazz = NULL; + + Assert_SC_true(0 == strcmp(moduleNameData, JAVA_BASE_MODULE)); + + clazz = vmFuncs->allClassesStartDo(&classWalkState, vm, systemClassLoader); + /* TODO: There are clazz objects from systemClassLoader that are not in the java.base + * module (e.g. other modules include openj9.jvm and jdk.proxy1). For now, rather than + * asserting like the non-persisted path, do a string compare with the moduleName so + * that only the proper clazz->classObjects are being restored. + * Revisit this to ensure proper functionality. Also, clean this up. There is duplicated + * code with with non-restore (and else) path. + */ + while (NULL != clazz) { + J9Module *clazzModule = clazz->module; + + if (NULL != clazzModule) { + const char *clazzModuleName = (const char *)J9UTF8_DATA(clazzModule->moduleName); + + if (0 == strcmp(clazzModuleName, JAVA_BASE_MODULE)) { + J9VMJAVALANGCLASS_SET_MODULE(currentThread, clazz->classObject, moduleObject); + } else { + if (classLoader == systemClassLoader) { + const char *moduleName = "openj9.sharedclasses"; + + if (0 == strcmp(moduleNameData, moduleName)) { + J9VMDllLoadInfo *entry = FIND_DLL_TABLE_ENTRY(J9_SHARED_DLL_NAME); + + if ((NULL == entry) || (J9_ARE_ALL_BITS_SET(entry->loadFlags, FAILED_TO_LOAD))) { + j9nls_printf(PORTLIB, J9NLS_WARNING, J9NLS_VM_FAILED_TO_LOAD_MODULE_REQUIRED_DLL, J9_SHARED_DLL_NAME, moduleName); + } + } + } + } + } + clazz = vmFuncs->allClassesNextDo(&classWalkState); + } + vmFuncs->allClassesEndDo(&classWalkState); + + if (vm->anonClassCount > 0) { + J9ClassWalkState classWalkStateAnon = {0}; + J9Class *clazzAnon = NULL; + + Assert_SC_notNull(vm->anonClassLoader); + clazzAnon = vmFuncs->allClassesStartDo(&classWalkStateAnon, vm, vm->anonClassLoader); + while (NULL != clazzAnon) { + Assert_SC_true(clazzAnon->module == vm->javaBaseModule); + J9VMJAVALANGCLASS_SET_MODULE(currentThread, clazzAnon->classObject, moduleObject); + clazzAnon = vmFuncs->allClassesNextDo(&classWalkStateAnon); + } + vmFuncs->allClassesEndDo(&classWalkStateAnon); + } + vm->runtimeFlags |= J9_RUNTIME_JAVA_BASE_MODULE_CREATED; + Trc_MODULE_defineModule(currentThread, "java.base", module); + } else { + Trc_MODULE_defineModule(currentThread, moduleNameData, module); + if (classLoader == systemClassLoader) { + const char *moduleName = "openj9.sharedclasses"; + + if (0 == strcmp(moduleNameData, moduleName)) { + J9VMDllLoadInfo *entry = FIND_DLL_TABLE_ENTRY(J9_SHARED_DLL_NAME); + + if ((NULL == entry) || (J9_ARE_ALL_BITS_SET(entry->loadFlags, FAILED_TO_LOAD))) { + j9nls_printf(PORTLIB, J9NLS_WARNING, J9NLS_VM_FAILED_TO_LOAD_MODULE_REQUIRED_DLL, J9_SHARED_DLL_NAME, moduleName); + } + } + } + } + TRIGGER_J9HOOK_VM_MODULE_LOAD(vm->hookInterface, currentThread, module); + ret = module; + } + + return ret; +} +#endif /* defined(J9VM_OPT_SNAPSHOTS) */ + static void freePackageDefinition(J9VMThread * currentThread, J9ClassLoader * classLoader, const char *packageName) { @@ -348,13 +456,54 @@ trcModulesCreationPackage(J9VMThread *currentThread, J9Module *fromModule, const } static BOOLEAN -addPackageDefinition(J9VMThread * currentThread, J9Module * fromModule, const char *package) +addPackageDefinition(J9VMThread *currentThread, J9Module *fromModule, const char *package) { - J9ClassLoader * const classLoader = fromModule->classLoader; + J9JavaVM *vm = currentThread->javaVM; + J9InternalVMFunctions const *const vmFuncs = vm->internalVMFunctions; + J9ClassLoader *const classLoader = fromModule->classLoader; BOOLEAN retval = FALSE; - J9Package * j9package = createPackage(currentThread, fromModule, package); + PORT_ACCESS_FROM_VMC(currentThread); +#if defined(J9VM_OPT_SNAPSHOTS) + VMSNAPSHOTIMPLPORT_ACCESS_FROM_JAVAVM(vm); +#endif /* defined(J9VM_OPT_SNAPSHOTS) */ + J9Package *j9package = NULL; + J9UTF8 *packageName = NULL; + UDATA packageNameLength = strlen(package); + if (packageNameLength < J9VM_PACKAGE_NAME_BUFFER_LENGTH) { + UDATA packageNameJ9UTF8Size = packageNameLength + sizeof(J9UTF8) + 1; /* +1 for null-terminator. */ +#if defined(J9VM_OPT_SNAPSHOTS) + if (IS_SNAPSHOTTING_ENABLED(vm)) { + packageName = (J9UTF8 *)vmsnapshot_allocate_memory(packageNameJ9UTF8Size, OMRMEM_CATEGORY_VM); + } else +#endif /* defined(J9VM_OPT_SNAPSHOTS) */ + { + packageName = (J9UTF8 *)j9mem_allocate_memory(packageNameJ9UTF8Size, OMRMEM_CATEGORY_VM); + } + if (NULL == packageName) { + vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0); + return retval; + } + memcpy(J9UTF8_DATA(packageName), (void *)package, packageNameLength); + J9UTF8_DATA(packageName)[packageNameLength] = '\0'; + J9UTF8_SET_LENGTH(packageName, (U_16)packageNameLength); + } else { + vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL); + return retval; + } + +#if defined(J9VM_OPT_SNAPSHOTS) + if (IS_RESTORE_RUN(vm)) { + j9package = hashPackageTableAtWithUTF8Name(currentThread, classLoader, packageName); + if (NULL != j9package) { + vmsnapshot_free_memory(packageName); + return TRUE; + } + } +#endif /* defined(J9VM_OPT_SNAPSHOTS) */ + + j9package = createPackage(currentThread, fromModule, packageName); if (NULL != j9package) { Trc_MODULE_invokeHashTableAtPut(currentThread, "addPackageDefinition", classLoader, classLoader->packageHashTable, &j9package, j9package, "true"); @@ -810,8 +959,17 @@ JVM_DefineModule(JNIEnv * env, jobject module, jboolean isOpen, jstring version, /* An exception should be pending if classLoader is null */ Assert_SC_true(NULL != currentThread->currentException); } else { - J9UTF8 *moduleName = vmFuncs->copyStringToJ9UTF8WithMemAlloc( - currentThread, moduleNameObject, J9_STR_NULL_TERMINATE_RESULT, "", 0, NULL, 0); + J9UTF8 *moduleName = NULL; +#if defined(J9VM_OPT_SNAPSHOTS) + if (IS_SNAPSHOTTING_ENABLED(vm)) { + moduleName = vmFuncs->copyStringToJ9UTF8WithPortLib( + currentThread, moduleNameObject, J9_STR_NULL_TERMINATE_RESULT, "", 0, VMSNAPSHOTIMPL_OMRPORT_FROM_JAVAVM(vm)); + } else +#endif /* defined(J9VM_OPT_SNAPSHOTS) */ + { + moduleName = vmFuncs->copyStringToJ9UTF8WithMemAlloc( + currentThread, moduleNameObject, J9_STR_NULL_TERMINATE_RESULT, "", 0, NULL, 0); + } if (NULL == moduleName) { vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0); goto done; @@ -820,7 +978,18 @@ JVM_DefineModule(JNIEnv * env, jobject module, jboolean isOpen, jstring version, if ((classLoader != systemClassLoader) && (0 == strcmp(moduleNameData, JAVA_BASE_MODULE))) { vmFuncs->setCurrentExceptionNLS(currentThread, J9VMCONSTANTPOOL_JAVALANGLAYERINSTANTIATIONEXCEPTION, J9NLS_VM_ONLY_BOOTCLASSLOADER_LOAD_MODULE_JAVABASE); } else { - J9Module *j9mod = createModule(currentThread, modObj, classLoader, moduleName); + J9Module *j9mod = NULL; + +#if defined(J9VM_OPT_SNAPSHOTS) + if (IS_RESTORE_RUN(vm)) { + j9mod = restoreModule(currentThread, classLoader, moduleName, modObj, version); + if (NULL != j9mod) { + goto done; + } + } +#endif /* defined(J9VM_OPT_SNAPSHOTS) */ + + j9mod = createModule(currentThread, modObj, classLoader, moduleName); if (NULL != j9mod) { BOOLEAN success = FALSE; UDATA rc = addModuleDefinition(currentThread, j9mod, packages, (U_32) numPackages, version); @@ -1488,13 +1657,28 @@ JVM_SetBootLoaderUnnamedModule(JNIEnv *env, jobject module) } else if (NULL != unnamedModuleForSystemLoader->moduleObject) { vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, "module is already set in the unnamedModuleForSystemLoader"); } else { - J9Module *j9mod = createModule(currentThread, modObj, systemClassLoader, NULL /* NULL name field */); + J9Module *j9mod = NULL; + if (IS_RESTORE_RUN(vm)) { + j9mod = unnamedModuleForSystemLoader; + /* Bind J9Module and module object via the hidden field. */ + J9OBJECT_ADDRESS_STORE(currentThread, modObj, vm->modulePointerOffset, j9mod); + } else { + j9mod = createModule(currentThread, modObj, systemClassLoader, NULL /* NULL name field */); + } unnamedModuleForSystemLoader->moduleObject = modObj; Trc_MODULE_setUnnamedModuleForSystemLoaderModuleObject(currentThread, j9mod, unnamedModuleForSystemLoader); } #else /* JAVA_SPEC_VERSION >= 21 */ if (NULL == J9VMJAVALANGCLASSLOADER_UNNAMEDMODULE(currentThread, systemClassLoader->classLoaderObject)) { - J9Module *j9mod = createModule(currentThread, modObj, systemClassLoader, NULL /* NULL name field */); + J9Module *j9mod = NULL; + if (IS_RESTORE_RUN(vm)) { + j9mod = vm->unnamedModuleForSystemLoader; + vm->unnamedModuleForSystemLoader->moduleObject = modObj; + /* Bind J9Module and module object via the hidden field. */ + J9OBJECT_ADDRESS_STORE(currentThread, modObj, vm->modulePointerOffset, j9mod); + } else { + j9mod = createModule(currentThread, modObj, systemClassLoader, NULL /* NULL name field */); + } J9VMJAVALANGCLASSLOADER_SET_UNNAMEDMODULE(currentThread, systemClassLoader->classLoaderObject, modObj); Trc_MODULE_setBootloaderUnnamedModule(currentThread, j9mod); } else { diff --git a/runtime/oti/SnapshotFileFormat.h b/runtime/oti/SnapshotFileFormat.h index 141f032f05d..a457b974f59 100644 --- a/runtime/oti/SnapshotFileFormat.h +++ b/runtime/oti/SnapshotFileFormat.h @@ -57,6 +57,11 @@ typedef struct SavedJ9JavaVMStructures { J9ClassLoader *extensionClassLoader; J9ClassLoader *applicationClassLoader; J9HiddenInstanceField *hiddenInstanceFields; +#if JAVA_SPEC_VERSION > 8 + J9Pool *modularityPool; + J9Module *javaBaseModule; + J9Module *unnamedModuleForSystemLoader; +#endif /* JAVA_SPEC_VERSION > 8 */ } SavedJ9JavaVMStructures; /* diff --git a/runtime/oti/j9nonbuilder.h b/runtime/oti/j9nonbuilder.h index b43c55a3aa3..58a349c43dc 100644 --- a/runtime/oti/j9nonbuilder.h +++ b/runtime/oti/j9nonbuilder.h @@ -4859,8 +4859,10 @@ typedef struct J9InternalVMFunctions { IDATA ( *javaThreadProc)(void *entryarg) ; char* ( *copyStringToUTF8WithMemAlloc)(struct J9VMThread *currentThread, j9object_t string, UDATA stringFlags, const char *prependStr, UDATA prependStrLength, char *buffer, UDATA bufferLength, UDATA *utf8Length) ; J9UTF8* ( *copyStringToJ9UTF8WithMemAlloc)(struct J9VMThread *vmThread, j9object_t string, UDATA stringFlags, const char *prependStr, UDATA prependStrLength, char *buffer, UDATA bufferLength) ; + J9UTF8* ( *copyStringToJ9UTF8WithPortLib)(struct J9VMThread *vmThread, j9object_t string, UDATA stringFlags, const char *prependStr, UDATA prependStrLength, OMRPortLibrary *portLib) ; char* ( *copyJ9UTF8ToUTF8WithMemAlloc)(struct J9VMThread *vmThread, J9UTF8 *string, UDATA stringFlags, const char *prependStr, UDATA prependStrLength, char *buffer, UDATA bufferLength) ; J9UTF8* ( *copyJ9UTF8WithMemAlloc)(struct J9VMThread *vmThread, J9UTF8 *string, UDATA stringFlags, const char *prependStr, UDATA prependStrLength, char *buffer, UDATA bufferLength) ; + J9UTF8* ( *copyJ9UTF8WithPortLib)(struct J9VMThread *vmThread, J9UTF8 *string, UDATA stringFlags, const char *prependStr, UDATA prependStrLength, OMRPortLibrary *portLib) ; void ( *internalAcquireVMAccess)(struct J9VMThread * currentThread) ; void ( *internalAcquireVMAccessWithMask)(struct J9VMThread * currentThread, UDATA haltFlags) ; void ( *internalAcquireVMAccessNoMutexWithMask)(struct J9VMThread * vmThread, UDATA haltFlags) ; diff --git a/runtime/oti/util_api.h b/runtime/oti/util_api.h index d2b82515de8..73fdbf187e5 100644 --- a/runtime/oti/util_api.h +++ b/runtime/oti/util_api.h @@ -2912,6 +2912,31 @@ getPackageDefinition(J9VMThread * currentThread, J9Module * fromModule, const ch */ J9Package* hashPackageTableAt(J9VMThread * currentThread, J9ClassLoader * classLoader, const char *packageName); + +/** + * Look up a J9Package in a classloader's package hashtable based on the package name + * + * @param[in] currentThread the current J9VMThread + * @param[in] classLoader the classloader with the target package hashtable + * @param[in] packageName the package name for the query + * + * @return a pointer to the J9Package if found or NULL + */ +J9Package * +hashPackageTableAtWithUTF8Name(J9VMThread *currentThread, J9ClassLoader *classLoader, J9UTF8 *packageName); + +/** + * Look up a J9Module in a classloader's module hashtable based on the module name + * + * @param[in] currentThread the current J9VMThread + * @param[in] classLoader the classloader with the target module hashtable + * @param[in] moduleName the module name for the query + * + * @return a pointer to the J9Module if found or NULL + */ +J9Module * +hashModuleTableAtWithUTF8Name(J9VMThread *currentThread, J9ClassLoader *classLoader, J9UTF8 *moduleName); + /** * Add UTF package name to construct a J9Package for hashtable query * diff --git a/runtime/oti/vm_api.h b/runtime/oti/vm_api.h index 00897148e1b..8637c66971a 100644 --- a/runtime/oti/vm_api.h +++ b/runtime/oti/vm_api.h @@ -3524,6 +3524,26 @@ copyStringToUTF8WithMemAlloc(J9VMThread *vmThread, j9object_t string, UDATA stri J9UTF8* copyStringToJ9UTF8WithMemAlloc(J9VMThread *vmThread, j9object_t string, UDATA stringFlags, const char *prependStr, UDATA prependStrLength, char *buffer, UDATA bufferLength); +/** + * Copy a string object to a J9UTF8 allocated via a port library, and optionally prepend a string + * before it. + * + * @note The caller must free the memory from this pointer from the same port library memory allocator. + * + * @param[in] currentThread the current J9VMThread + * @param[in] string a string object to be copied + * it can't be NULL + * @param[in] stringFlags the flag to determine performing '.' --> '/' or NULL termination + * @param[in] prependStr the string to be prepended before the string object to be copied + * it can't be NULL but can be an empty string "" + * @param[in] prependStrLength the length of prependStr as computed by strlen + * @param[in] portLib the OMRPortLibrary from which to allocate the buffer + * + * @return a J9UTF8 pointer to the string + */ +J9UTF8 * +copyStringToJ9UTF8WithPortLib(J9VMThread *vmThread, j9object_t string, UDATA stringFlags, const char *prependStr, UDATA prependStrLength, OMRPortLibrary *portLib); + /** * Copy a J9UTF8 to a UTF8 data buffer, and optionally prepend a string before it. * @@ -3566,6 +3586,26 @@ copyJ9UTF8ToUTF8WithMemAlloc(J9VMThread *vmThread, J9UTF8 *string, UDATA stringF J9UTF8 * copyJ9UTF8WithMemAlloc(J9VMThread *vmThread, J9UTF8 *string, UDATA stringFlags, const char *prependStr, UDATA prependStrLength, char *buffer, UDATA bufferLength); +/** + * Creates a fresh copy of a J9UTF8 allocated via a specified port library, and optionally prepend + * a string it. + * + * @note The caller must free the memory from this pointer from the same port library memory allocator. + * + * @param[in] currentThread the current J9VMThread + * @param[in] string a J9UTF8 pointer to the data to be copied + * it can't be NULL + * @param[in] stringFlags the flag to determine performing '.' --> '/' or NULL termination + * @param[in] prependStr the string to be prepended before the string object to be copied + * it can't be NULL but can be an empty string "" + * @param[in] prependStrLength The length of prependStr as computed by strlen. + * @param[in] portLib the OMRPortLibrary from which to allocate the buffer + * + * @return a J9UTF8 pointer to the string + */ +J9UTF8 * +copyJ9UTF8WithPortLib(J9VMThread *vmThread, J9UTF8 *string, UDATA stringFlags, const char *prependStr, UDATA prependStrLength, OMRPortLibrary *portLib); + /** * Copy a Unicode String to a UTF8 data buffer. * diff --git a/runtime/util/cphelp.c b/runtime/util/cphelp.c index 4b2c5f3c378..f688845b9cd 100644 --- a/runtime/util/cphelp.c +++ b/runtime/util/cphelp.c @@ -128,6 +128,9 @@ getModuleJRTURL(J9VMThread *currentThread, J9ClassLoader *classLoader, J9Module J9UTF8 *jrtURL = NULL; J9ModuleExtraInfo info = {0}; PORT_ACCESS_FROM_JAVAVM(javaVM); +#if defined(J9VM_OPT_SNAPSHOTS) + VMSNAPSHOTIMPLPORT_ACCESS_FROM_JAVAVM(javaVM); +#endif /* defined(J9VM_OPT_SNAPSHOTS) */ if (NULL == classLoader->moduleExtraInfoHashTable) { classLoader->moduleExtraInfoHashTable = vmFuncs->hashModuleExtraInfoTableNew(javaVM, 1); @@ -154,8 +157,16 @@ getModuleJRTURL(J9VMThread *currentThread, J9ClassLoader *classLoader, J9Module /* Set jrt URL for the module. */ const char *prependStr = "jrt:/"; const size_t prependStrLen = strlen(prependStr); - jrtURL = vmFuncs->copyJ9UTF8WithMemAlloc( - currentThread, module->moduleName, J9_STR_NONE, prependStr, prependStrLen, NULL, 0); +#if defined(J9VM_OPT_SNAPSHOTS) + if (IS_SNAPSHOTTING_ENABLED(javaVM)) { + jrtURL = vmFuncs->copyJ9UTF8WithPortLib( + currentThread, module->moduleName, J9_STR_NONE, prependStr, prependStrLen, VMSNAPSHOTIMPL_OMRPORT_FROM_JAVAVM(javaVM)); + } else +#endif /* defined(J9VM_OPT_SNAPSHOTS) */ + { + jrtURL = vmFuncs->copyJ9UTF8WithMemAlloc( + currentThread, module->moduleName, J9_STR_NONE, prependStr, prependStrLen, NULL, 0); + } } if (NULL == jrtURL) { goto _exit; @@ -165,7 +176,14 @@ getModuleJRTURL(J9VMThread *currentThread, J9ClassLoader *classLoader, J9Module J9_DECLARE_CONSTANT_UTF8(jrtJavaBaseUrl, "jrt:/java.base"); const U_16 length = J9UTF8_LENGTH(&jrtJavaBaseUrl); const UDATA jrtURLSize = length + sizeof(J9UTF8); - jrtURL = (J9UTF8 *)j9mem_allocate_memory(jrtURLSize, OMRMEM_CATEGORY_VM); +#if defined(J9VM_OPT_SNAPSHOTS) + if (IS_SNAPSHOTTING_ENABLED(javaVM)) { + jrtURL = (J9UTF8 *)vmsnapshot_allocate_memory(jrtURLSize, OMRMEM_CATEGORY_VM); + } else +#endif /* defined(J9VM_OPT_SNAPSHOTS) */ + { + jrtURL = (J9UTF8 *)j9mem_allocate_memory(jrtURLSize, OMRMEM_CATEGORY_VM); + } if (NULL == jrtURL) { goto _exit; } @@ -176,11 +194,18 @@ getModuleJRTURL(J9VMThread *currentThread, J9ClassLoader *classLoader, J9Module } if (TRUE == newModuleInfo) { - /* Add moduleInfo to the hashtable */ + /* Add moduleInfo to the hashtable. */ void *node = hashTableAdd(classLoader->moduleExtraInfoHashTable, (void *)moduleInfo); if (NULL == node) { /* If we fail to add new moduleInfo to the hashtable, then free up jrtURL */ - j9mem_free_memory(moduleInfo->jrtURL); +#if defined(J9VM_OPT_SNAPSHOTS) + if (IS_SNAPSHOTTING_ENABLED(javaVM)) { + vmsnapshot_free_memory(moduleInfo->jrtURL); + } else +#endif /* defined(J9VM_OPT_SNAPSHOTS) */ + { + j9mem_free_memory(moduleInfo->jrtURL); + } goto _exit; } } diff --git a/runtime/util/modularityHelper.c b/runtime/util/modularityHelper.c index e8addc22699..110fb6000a5 100644 --- a/runtime/util/modularityHelper.c +++ b/runtime/util/modularityHelper.c @@ -26,7 +26,6 @@ #if JAVA_SPEC_VERSION >= 11 -static J9Package* hashPackageTableAtWithUTF8Name(J9VMThread *currentThread, J9ClassLoader *classLoader, J9UTF8 *packageName); static BOOLEAN isPackageExportedToModuleHelper(J9VMThread *currentThread, J9Module *fromModule, J9Package *j9package, J9Module *toModule, BOOLEAN toUnnamed); /* All the helper functions below assume that: @@ -149,7 +148,21 @@ addUTFNameToPackage(J9VMThread *currentThread, J9Package *j9package, const char return TRUE; } -static J9Package* +J9Module * +hashModuleTableAtWithUTF8Name(J9VMThread *currentThread, J9ClassLoader *classLoader, J9UTF8 *moduleName) +{ + J9Module module = {0}; + J9Module *modulePtr = &module; + J9Module **targetPtr = NULL; + + modulePtr->moduleName = moduleName; + modulePtr->classLoader = classLoader; + Assert_Util_notNull(modulePtr->moduleName); + targetPtr = hashTableFind(classLoader->moduleHashTable, &modulePtr); + return (NULL != targetPtr) ? *targetPtr : NULL; +} + +J9Package * hashPackageTableAtWithUTF8Name(J9VMThread *currentThread, J9ClassLoader *classLoader, J9UTF8 *packageName) { J9Package package = {0}; diff --git a/runtime/vm/ModularityHashTables.c b/runtime/vm/ModularityHashTables.c index eafbffc7636..9e4a795b51e 100644 --- a/runtime/vm/ModularityHashTables.c +++ b/runtime/vm/ModularityHashTables.c @@ -136,9 +136,16 @@ J9HashTable * hashModulePointerTableNew(J9JavaVM *javaVM, U_32 initialSize) { U_32 flags = J9HASH_TABLE_ALLOW_SIZE_OPTIMIZATION; + OMRPORT_ACCESS_FROM_J9PORT(javaVM->portLibrary); + +#if defined(J9VM_OPT_SNAPSHOTS) + if (IS_SNAPSHOTTING_ENABLED(javaVM)) { + OMRPORTLIB = VMSNAPSHOTIMPL_OMRPORT_FROM_JAVAVM(javaVM); + } +#endif /* defined(J9VM_OPT_SNAPSHOTS) */ return hashTableNew( - OMRPORT_FROM_J9PORT(javaVM->portLibrary), + OMRPORTLIB, J9_GET_CALLSITE(), initialSize, sizeof(void *), @@ -181,9 +188,16 @@ J9HashTable * hashModuleExtraInfoTableNew(J9JavaVM *javaVM, U_32 initialSize) { U_32 flags = J9HASH_TABLE_ALLOW_SIZE_OPTIMIZATION; + OMRPORT_ACCESS_FROM_J9PORT(javaVM->portLibrary); + +#if defined(J9VM_OPT_SNAPSHOTS) + if (IS_SNAPSHOTTING_ENABLED(javaVM)) { + OMRPORTLIB = VMSNAPSHOTIMPL_OMRPORT_FROM_JAVAVM(javaVM); + } +#endif /* defined(J9VM_OPT_SNAPSHOTS) */ return hashTableNew( - OMRPORT_FROM_J9PORT(javaVM->portLibrary), + OMRPORTLIB, J9_GET_CALLSITE(), initialSize, sizeof(J9ModuleExtraInfo), diff --git a/runtime/vm/VMSnapshotImpl.cpp b/runtime/vm/VMSnapshotImpl.cpp index cf639be703a..b4bd0702c3b 100644 --- a/runtime/vm/VMSnapshotImpl.cpp +++ b/runtime/vm/VMSnapshotImpl.cpp @@ -375,6 +375,24 @@ VMSnapshotImpl::isImmortalClassLoader(J9ClassLoader *classLoader) return isImmortal; } +#if JAVA_SPEC_VERSION > 8 +void +VMSnapshotImpl::saveModularityData() +{ + _snapshotHeader->savedJavaVMStructs.modularityPool = _vm->modularityPool; + _snapshotHeader->savedJavaVMStructs.javaBaseModule = _vm->javaBaseModule; + _snapshotHeader->savedJavaVMStructs.unnamedModuleForSystemLoader = _vm->unnamedModuleForSystemLoader; +} + +void +VMSnapshotImpl::restoreModularityData() +{ + _vm->modularityPool = _snapshotHeader->savedJavaVMStructs.modularityPool; + _vm->javaBaseModule = _snapshotHeader->savedJavaVMStructs.javaBaseModule; + _vm->unnamedModuleForSystemLoader = _snapshotHeader->savedJavaVMStructs.unnamedModuleForSystemLoader; +} +#endif /* JAVA_SPEC_VERSION > 8 */ + void VMSnapshotImpl::saveHiddenInstanceFields() { @@ -541,6 +559,27 @@ VMSnapshotImpl::fixupClassPathEntries(J9ClassLoader *classLoader) } } +/* TODO: Fixup during fixupClassLoaders. */ +void +VMSnapshotImpl::fixupModules() +{ + pool_state classLoaderWalkState = {0}; + J9ClassLoader *currentClassLoader = (J9ClassLoader *)pool_startDo(_vm->classLoaderBlocks, &classLoaderWalkState); + while (NULL != currentClassLoader) { + J9HashTableState moduleWalkState = {0}; + + J9Module **modulePtr = (J9Module **)hashTableStartDo(currentClassLoader->moduleHashTable, &moduleWalkState); + while (NULL != modulePtr) { + J9Module *currentModule = *modulePtr; + currentModule->moduleObject = NULL; + currentModule->version = NULL; + + modulePtr = (J9Module **)hashTableNextDo(&moduleWalkState); + } + currentClassLoader = (J9ClassLoader *)pool_nextDo(&classLoaderWalkState); + } +} + /* TODO: Once all class loaders are supported, this won't be needed. */ void VMSnapshotImpl::removeUnpersistedClassLoaders() @@ -571,7 +610,37 @@ VMSnapshotImpl::removeUnpersistedClassLoaders() } for (UDATA i = 0; i < count; i++) { - freeClassLoader(removeLoaders[i], _vm, vmThread, FALSE); + J9ClassLoader *currentClassLoader = removeLoaders[i]; + + J9HashTableState moduleWalkState = {0}; + J9Module **modulePtr = (J9Module **)hashTableStartDo(currentClassLoader->moduleHashTable, &moduleWalkState); + while (NULL != modulePtr) { + J9Module *moduleDel = *modulePtr; + modulePtr = (J9Module **)hashTableNextDo(&moduleWalkState); + freeJ9Module(_vm, moduleDel); + } + + J9HashTableState packageWalkState = {0}; + J9Package **packagePtr = (J9Package **)hashTableStartDo(currentClassLoader->packageHashTable, &packageWalkState); + while (NULL != packagePtr) { + J9Package *packageDel = *packagePtr; + packagePtr = (J9Package **)hashTableNextDo(&packageWalkState); + J9HashTableState walkState = {0}; + + J9Module **modulePtr = (J9Module **)hashTableStartDo(packageDel->exportsHashTable, &walkState); + while (NULL != modulePtr) { + if (NULL != (*modulePtr)->removeExportsHashTable) { + hashTableRemove((*modulePtr)->removeExportsHashTable, &packageDel); + } + J9Module *moduleDel = *modulePtr; + modulePtr = (J9Module **)hashTableNextDo(&walkState); + freeJ9Module(_vm, moduleDel); + } + hashTableFree(packageDel->exportsHashTable); + j9mem_free_memory(packageDel->packageName); + pool_removeElement(_vm->modularityPool, packageDel); + } + freeClassLoader(currentClassLoader, _vm, vmThread, FALSE); } if ((J9ClassLoader **)buf != removeLoaders) { @@ -830,6 +899,7 @@ VMSnapshotImpl::saveJ9JavaVMStructures() saveMemorySegments(); savePrimitiveAndArrayClasses(); saveHiddenInstanceFields(); + saveModularityData(); _snapshotHeader->vm = _vm; } @@ -846,6 +916,7 @@ VMSnapshotImpl::restoreJ9JavaVMStructures() restoreMemorySegments(); restorePrimitiveAndArrayClasses(); restoreHiddenInstanceFields(); + restoreModularityData(); if (J9THREAD_RWMUTEX_OK != omrthread_rwmutex_init(&_vm->systemClassLoader->cpEntriesMutex, 0, "classPathEntries Mutex")) { success = false; @@ -946,6 +1017,7 @@ VMSnapshotImpl::writeSnapshot() /* TODO: Call GC API to snapshot heap. */ fixupClassLoaders(); fixupClasses(); + fixupModules(); saveJ9JavaVMStructures(); if(!writeSnapshotToFile()) { PORT_ACCESS_FROM_PORT(_portLibrary); diff --git a/runtime/vm/VMSnapshotImpl.hpp b/runtime/vm/VMSnapshotImpl.hpp index cd44977c55b..aae62226b85 100644 --- a/runtime/vm/VMSnapshotImpl.hpp +++ b/runtime/vm/VMSnapshotImpl.hpp @@ -86,6 +86,7 @@ class VMSnapshotImpl void fixupArrayClass(J9ArrayClass *clazz); void fixupMethodRunAddresses(J9Class *ramClass); void fixupConstantPool(J9Class *ramClass); + void fixupModules(); void fixupClassPathEntries(J9ClassLoader *classLoader); void removeUnpersistedClassLoaders(); void saveJ9JavaVMStructures(); @@ -112,6 +113,8 @@ class VMSnapshotImpl void restoreClassLoaderBlocks(); void saveMemorySegments(); void restoreMemorySegments(); + void saveModularityData(); + void restoreModularityData(); bool setupRestoreRun(); bool setupSnapshotRun(); diff --git a/runtime/vm/classallocation.c b/runtime/vm/classallocation.c index 1c64575a532..93350365b4a 100644 --- a/runtime/vm/classallocation.c +++ b/runtime/vm/classallocation.c @@ -221,6 +221,9 @@ freeClassLoader(J9ClassLoader *classLoader, J9JavaVM *javaVM, J9VMThread *vmThre #endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */ PORT_ACCESS_FROM_JAVAVM(javaVM); +#if defined(J9VM_OPT_SNAPSHOTS) + VMSNAPSHOTIMPLPORT_ACCESS_FROM_JAVAVM(javaVM); +#endif /* defined(J9VM_OPT_SNAPSHOTS) */ Trc_VM_freeClassLoader_Entry(classLoader); @@ -270,7 +273,6 @@ freeClassLoader(J9ClassLoader *classLoader, J9JavaVM *javaVM, J9VMThread *vmThre if (NULL != classLoader->classPathEntries) { freeClassLoaderEntries(vmThread, classLoader->classPathEntries, classLoader->classPathEntryCount, classLoader->initClassPathEntryCount); #if defined(J9VM_OPT_SNAPSHOTS) - VMSNAPSHOTIMPLPORT_ACCESS_FROM_JAVAVM(javaVM); if (IS_SNAPSHOTTING_ENABLED(javaVM)) { vmsnapshot_free_memory(classLoader->classPathEntries); } else @@ -421,11 +423,25 @@ freeClassLoader(J9ClassLoader *classLoader, J9JavaVM *javaVM, J9VMThread *vmThre J9ModuleExtraInfo *moduleExtraInfoPtr = (J9ModuleExtraInfo *)hashTableStartDo(classLoader->moduleExtraInfoHashTable, &moduleExtraInfoWalkState); while (NULL != moduleExtraInfoPtr) { freeClassLoaderEntries(vmThread, moduleExtraInfoPtr->patchPathEntries, moduleExtraInfoPtr->patchPathCount, moduleExtraInfoPtr->patchPathCount); - j9mem_free_memory(moduleExtraInfoPtr->patchPathEntries); +#if defined(J9VM_OPT_SNAPSHOTS) + if (IS_SNAPSHOTTING_ENABLED(javaVM)) { + vmsnapshot_free_memory(moduleExtraInfoPtr->patchPathEntries); + } else +#endif /* defined(J9VM_OPT_SNAPSHOTS) */ + { + j9mem_free_memory(moduleExtraInfoPtr->patchPathEntries); + } moduleExtraInfoPtr->patchPathEntries = NULL; moduleExtraInfoPtr->patchPathCount = 0; if (NULL != moduleExtraInfoPtr->jrtURL) { - j9mem_free_memory(moduleExtraInfoPtr->jrtURL); +#if defined(J9VM_OPT_SNAPSHOTS) + if (IS_SNAPSHOTTING_ENABLED(javaVM)) { + vmsnapshot_free_memory(moduleExtraInfoPtr->jrtURL); + } else +#endif /* defined(J9VM_OPT_SNAPSHOTS) */ + { + j9mem_free_memory(moduleExtraInfoPtr->jrtURL); + } } moduleExtraInfoPtr = (J9ModuleExtraInfo *)hashTableNextDo(&moduleExtraInfoWalkState); } @@ -458,7 +474,14 @@ freeClassLoader(J9ClassLoader *classLoader, J9JavaVM *javaVM, J9VMThread *vmThre packagePtr = (J9Package**)hashTableNextDo(&packageWalkState); cleanPackage(packageDel); hashTableFree(packageDel->exportsHashTable); - j9mem_free_memory(packageDel->packageName); +#if defined(J9VM_OPT_SNAPSHOTS) + if (IS_SNAPSHOTTING_ENABLED(javaVM)) { + vmsnapshot_free_memory(packageDel->packageName); + } else +#endif /* defined(J9VM_OPT_SNAPSHOTS) */ + { + j9mem_free_memory(packageDel->packageName); + } pool_removeElement(javaVM->modularityPool, packageDel); } diff --git a/runtime/vm/classsupport.c b/runtime/vm/classsupport.c index ffdbabef8b2..54df9934d49 100644 --- a/runtime/vm/classsupport.c +++ b/runtime/vm/classsupport.c @@ -1025,6 +1025,7 @@ loadWarmClassFromSnapshot(J9VMThread *vmThread, J9ClassLoader *classLoader, J9Cl J9JavaVM *vm = vmThread->javaVM; J9Class *superClazz = clazz->superclasses[J9CLASS_DEPTH(clazz) - 1]; J9ITable *itable = (J9ITable *)clazz->iTable; + j9object_t classObject = NULL; const char *className = (const char *)J9UTF8_DATA(J9ROMCLASS_CLASSNAME(clazz->romClass)); clazz->classFlags |= J9ClassIsLoadedFromSnapshot; @@ -1073,6 +1074,18 @@ loadWarmClassFromSnapshot(J9VMThread *vmThread, J9ClassLoader *classLoader, J9Cl } } + /* TODO: Handle/trace error/NULL paths. */ + classObject = clazz->classObject; + if (NULL != classObject) { + J9Module *module = clazz->module; + if (NULL != module) { + j9object_t moduleObject = module->moduleObject; + if (NULL != moduleObject) { + J9VMJAVALANGCLASS_SET_MODULE(vmThread, classObject, moduleObject); + } + } + } + Trc_VM_snapshot_loadWarmClassFromSnapshot_ClassInfo(vmThread, clazz, className); } diff --git a/runtime/vm/intfunc.c b/runtime/vm/intfunc.c index 75a9bc72126..cd6eb073a0c 100644 --- a/runtime/vm/intfunc.c +++ b/runtime/vm/intfunc.c @@ -64,8 +64,10 @@ J9InternalVMFunctions J9InternalFunctions = { javaThreadProc, copyStringToUTF8WithMemAlloc, copyStringToJ9UTF8WithMemAlloc, + copyStringToJ9UTF8WithPortLib, copyJ9UTF8ToUTF8WithMemAlloc, copyJ9UTF8WithMemAlloc, + copyJ9UTF8WithPortLib, internalAcquireVMAccess, internalAcquireVMAccessWithMask, internalAcquireVMAccessNoMutexWithMask, diff --git a/runtime/vm/jvmfree.c b/runtime/vm/jvmfree.c index 862f1222413..1a1908b3f02 100644 --- a/runtime/vm/jvmfree.c +++ b/runtime/vm/jvmfree.c @@ -395,8 +395,16 @@ freeJ9Module(J9JavaVM *javaVM, J9Module *j9module) { } if (NULL != j9module->moduleName) { - PORT_ACCESS_FROM_JAVAVM(javaVM); - j9mem_free_memory((void *)j9module->moduleName); +#if defined(J9VM_OPT_SNAPSHOTS) + if (IS_SNAPSHOTTING_ENABLED(javaVM)) { + VMSNAPSHOTIMPLPORT_ACCESS_FROM_JAVAVM(javaVM); + vmsnapshot_free_memory((void *)j9module->moduleName); + } else +#endif /* defined(J9VM_OPT_SNAPSHOTS) */ + { + PORT_ACCESS_FROM_JAVAVM(javaVM); + j9mem_free_memory((void *)j9module->moduleName); + } } pool_removeElement(javaVM->modularityPool, j9module); diff --git a/runtime/vm/jvminit.c b/runtime/vm/jvminit.c index f0a57ee5154..834909fd775 100644 --- a/runtime/vm/jvminit.c +++ b/runtime/vm/jvminit.c @@ -1864,7 +1864,15 @@ setBootLoaderModulePatchPaths(J9JavaVM * javaVM, J9Module * j9module, const char if (NULL == node) { J9VMThread *currentThread = javaVM->internalVMFunctions->currentVMThread(javaVM); freeClassLoaderEntries(currentThread, moduleInfo.patchPathEntries, moduleInfo.patchPathCount, moduleInfo.patchPathCount); - j9mem_free_memory(moduleInfo.patchPathEntries); +#if defined(J9VM_OPT_SNAPSHOTS) + if (IS_SNAPSHOTTING_ENABLED(javaVM)) { + VMSNAPSHOTIMPLPORT_ACCESS_FROM_JAVAVM(javaVM); + vmsnapshot_free_memory(moduleInfo.patchPathEntries); + } else +#endif /* defined(J9VM_OPT_SNAPSHOTS) */ + { + j9mem_free_memory(moduleInfo.patchPathEntries); + } moduleInfo.patchPathEntries = NULL; result = FALSE; goto _exitMutex; @@ -2663,9 +2671,18 @@ VMInitStages(J9JavaVM *vm, IDATA stage, void* reserved) } if (J2SE_VERSION(vm) >= J2SE_V11) { - vm->modularityPool = pool_new(OMR_MAX(sizeof(J9Package),sizeof(J9Module)), 0, 0, 0, J9_GET_CALLSITE(), J9MEM_CATEGORY_MODULES, POOL_FOR_PORT(vm->portLibrary)); - if (NULL == vm->modularityPool) { - goto _error; +#if defined(J9VM_OPT_SNAPSHOTS) + /* By this point during a restore run, the modularityPool is restored. */ + if (IS_SNAPSHOT_RUN(vm)) { + if (NULL == (vm->modularityPool = pool_new(OMR_MAX(sizeof(J9Package), sizeof(J9Module)), 0, 0, 0, J9_GET_CALLSITE(), J9MEM_CATEGORY_MODULES, POOL_FOR_PORT(VMSNAPSHOTIMPL_OMRPORT_FROM_JAVAVM(vm))))) { + goto _error; + } + } else if (!IS_RESTORE_RUN(vm)) +#endif /* defined(J9VM_OPT_SNAPSHOTS) */ + { + if (NULL == (vm->modularityPool = pool_new(OMR_MAX(sizeof(J9Package), sizeof(J9Module)), 0, 0, 0, J9_GET_CALLSITE(), J9MEM_CATEGORY_MODULES, POOL_FOR_PORT(vm->portLibrary)))) { + goto _error; + } } } #if JAVA_SPEC_VERSION >= 19 @@ -2960,26 +2977,28 @@ VMInitStages(J9JavaVM *vm, IDATA stage, void* reserved) } if (J2SE_VERSION(vm) >= J2SE_V11) { - BOOLEAN patchPathResult = FALSE; - - vm->javaBaseModule = pool_newElement(vm->modularityPool); - if (NULL == vm->javaBaseModule) { - setErrorJ9dll(PORTLIB, loadInfo, "cannot allocate java.base module", FALSE); - goto _error; - } - vm->javaBaseModule->classLoader = vm->systemClassLoader; + /* javaBaseModule and unnamedModuleForSystemLoader are already setup during a restore run. */ + if (!IS_RESTORE_RUN(vm)) { + BOOLEAN patchPathResult = FALSE; + vm->javaBaseModule = pool_newElement(vm->modularityPool); + if (NULL == vm->javaBaseModule) { + setErrorJ9dll(PORTLIB, loadInfo, "cannot allocate java.base module", FALSE); + goto _error; + } + vm->javaBaseModule->classLoader = vm->systemClassLoader; - vm->unnamedModuleForSystemLoader = pool_newElement(vm->modularityPool); - if (NULL == vm->unnamedModuleForSystemLoader) { - setErrorJ9dll(PORTLIB, loadInfo, "cannot allocate unnamed module for bootloader", FALSE); - goto _error; - } - vm->unnamedModuleForSystemLoader->classLoader = vm->systemClassLoader; + vm->unnamedModuleForSystemLoader = pool_newElement(vm->modularityPool); + if (NULL == vm->unnamedModuleForSystemLoader) { + setErrorJ9dll(PORTLIB, loadInfo, "cannot allocate unnamed module for bootloader", FALSE); + goto _error; + } + vm->unnamedModuleForSystemLoader->classLoader = vm->systemClassLoader; - patchPathResult = setBootLoaderModulePatchPaths(vm, vm->javaBaseModule, JAVA_BASE_MODULE); - if (FALSE == patchPathResult) { - setErrorJ9dll(PORTLIB, loadInfo, "cannot set patch paths for java.base module", FALSE); - goto _error; + patchPathResult = setBootLoaderModulePatchPaths(vm, vm->javaBaseModule, JAVA_BASE_MODULE); + if (FALSE == patchPathResult) { + setErrorJ9dll(PORTLIB, loadInfo, "cannot set patch paths for java.base module", FALSE); + goto _error; + } } } diff --git a/runtime/vm/stringhelpers.cpp b/runtime/vm/stringhelpers.cpp index ca2696d3626..2f9caaf9ee9 100644 --- a/runtime/vm/stringhelpers.cpp +++ b/runtime/vm/stringhelpers.cpp @@ -410,6 +410,54 @@ copyStringToJ9UTF8WithMemAlloc(J9VMThread *vmThread, j9object_t string, UDATA st return (J9UTF8 *)result; } +J9UTF8 * +copyStringToJ9UTF8WithPortLib(J9VMThread *vmThread, j9object_t string, UDATA stringFlags, const char *prependStr, UDATA prependStrLength, OMRPortLibrary *portLib) +{ + Assert_VM_notNull(prependStr); + Assert_VM_notNull(string); + + U_8 *result = NULL; + UDATA stringLength = J9VMJAVALANGSTRING_LENGTH(vmThread, string); + U_64 length = sizeof(J9UTF8) + prependStrLength + ((U_64)stringLength * 3); + + if (J9_ARE_ALL_BITS_SET(stringFlags, J9_STR_NULL_TERMINATE_RESULT)) { + ++length; + } + +#if UDATA_MAX < (3 * INT32_MAX) + /* Memory allocation functions take a UDATA as the input parameter for length. + * On 32-bit systems, the length needs to be restricted to UDATA_MAX since the + * maximum UTF-8 length of a Java string can be 3 * Integer.MAX_VALUE. Otherwise, + * there will be overflow. On 64-bit platforms, this is not an issue since UDATA + * and U_64 are the same size. + */ + if (length > UDATA_MAX) { + length = UDATA_MAX; + } +#endif /* UDATA_MAX < (3 * INT32_MAX) */ + + if ((prependStrLength <= J9UTF8_MAX_LENGTH) && (length <= (J9UTF8_MAX_LENGTH - prependStrLength))) { + result = (U_8 *)portLib->mem_allocate_memory(portLib, (UDATA)length, J9_GET_CALLSITE(), OMRMEM_CATEGORY_VM); + } + + if (NULL != result) { + UDATA computedUtf8Length = 0; + + if (0 < prependStrLength) { + memcpy(result + sizeof(J9UTF8), prependStr, prependStrLength); + } + + computedUtf8Length = copyStringToUTF8Helper( + vmThread, string, stringFlags, 0, stringLength, + result + sizeof(J9UTF8) + prependStrLength, + (UDATA)(length - sizeof(J9UTF8) - prependStrLength)); + + J9UTF8_SET_LENGTH(result, (U_16)computedUtf8Length + (U_16)prependStrLength); + } + + return (J9UTF8 *)result; +} + char * copyJ9UTF8ToUTF8WithMemAlloc(J9VMThread *vmThread, J9UTF8 *string, UDATA stringFlags, const char *prependStr, UDATA prependStrLength, char *buffer, UDATA bufferLength) { @@ -487,6 +535,42 @@ copyJ9UTF8WithMemAlloc(J9VMThread *vmThread, J9UTF8 *string, UDATA stringFlags, return result; } +J9UTF8 * +copyJ9UTF8WithPortLib(J9VMThread *vmThread, J9UTF8 *string, UDATA stringFlags, const char *prependStr, UDATA prependStrLength, OMRPortLibrary *portLib) +{ + Assert_VM_notNull(prependStr); + Assert_VM_notNull(string); + + J9UTF8 *result = NULL; + + const U_8 *stringData = J9UTF8_DATA(string); + const UDATA stringLength = (UDATA)J9UTF8_LENGTH(string); + const UDATA totalStringLength = prependStrLength + stringLength; + UDATA allocationSize = totalStringLength + sizeof(J9UTF8); + + if (J9_ARE_ALL_BITS_SET(stringFlags, J9_STR_NULL_TERMINATE_RESULT)) { + allocationSize += 1; + } + + if (totalStringLength < J9UTF8_MAX_LENGTH) { + result = (J9UTF8 *)portLib->mem_allocate_memory(portLib, allocationSize, J9_GET_CALLSITE(), OMRMEM_CATEGORY_VM); + + if (NULL != result) { + U_8 *resultString = J9UTF8_DATA(result); + if (prependStrLength > 0) { + memcpy(resultString, prependStr, prependStrLength); + } + memcpy(resultString + prependStrLength, stringData, stringLength); + if (J9_ARE_ALL_BITS_SET(stringFlags, J9_STR_NULL_TERMINATE_RESULT)) { + resultString[totalStringLength] = '\0'; + } + J9UTF8_SET_LENGTH(result, (U_16)totalStringLength); + } + } + + return result; +} + UDATA getStringUTF8Length(J9VMThread *vmThread, j9object_t string) {