diff --git a/runtime/j9vm/jvm.c b/runtime/j9vm/jvm.c index 68f3eb88d06..808e0a7f540 100644 --- a/runtime/j9vm/jvm.c +++ b/runtime/j9vm/jvm.c @@ -1242,6 +1242,7 @@ typedef struct J9SpecialArguments { UDATA *argEncoding; IDATA *ibmMallocTraceSet; const char *executableJarPath; + char *ramCache; } J9SpecialArguments; /** * Look for special options: @@ -1287,6 +1288,8 @@ initialArgumentScan(JavaVMInitArgs *args, J9SpecialArguments *specialArgs) *(specialArgs->argEncoding) = ARG_ENCODING_UTF; } else if (0 == strcmp(args->options[argCursor].optionString, VMOPT_XARGENCODINGLATIN)) { *(specialArgs->argEncoding) = ARG_ENCODING_LATIN; + } else if (0 == strncmp(args->options[argCursor].optionString, VMOPT_XRAMCACHE, sizeof(VMOPT_XRAMCACHE) - 1)) { + specialArgs->ramCache = args->options[argCursor].optionString + strlen(VMOPT_XRAMCACHE); } } @@ -1760,6 +1763,11 @@ jint JNICALL JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *vm_args) { launcherArgumentsSize = initialArgumentScan(args, &specialArgs); localVerboseLevel = specialArgs.localVerboseLevel; + if (NULL != specialArgs.ramCache) { + createParams.flags |= J9_CREATEJAVAVM_RAM_CACHE; + createParams.ramCache = specialArgs.ramCache; + } + if (VERBOSE_INIT == localVerboseLevel) { createParams.flags |= J9_CREATEJAVAVM_VERBOSE_INIT; } diff --git a/runtime/oti/j9nonbuilder.h b/runtime/oti/j9nonbuilder.h index 21f65a3db21..135b6927d3f 100644 --- a/runtime/oti/j9nonbuilder.h +++ b/runtime/oti/j9nonbuilder.h @@ -34,6 +34,7 @@ #include "j9consts.h" #include "jvmti.h" #include "j9javaaccessflags.h" +#include "jvmimageport.h" #define J9VM_MAX_HIDDEN_FIELDS_PER_CLASS 8 @@ -5116,7 +5117,7 @@ typedef struct J9JavaVM { struct J9PortLibrary * portLibrary; UDATA j2seVersion; void* zipCachePool; - void* jvmImagePortLibrary; + JVMImagePortLibrary* jvmImagePortLibrary; char* ramStateFilePath; struct J9VMInterface vmInterface; #if defined(J9VM_OPT_HARMONY) diff --git a/runtime/oti/jvmimage.h b/runtime/oti/jvmimage.h index e9b1226b269..cf2dacfba4e 100644 --- a/runtime/oti/jvmimage.h +++ b/runtime/oti/jvmimage.h @@ -70,6 +70,8 @@ struct JVMImageSizeAndLocation; */ typedef struct JVMImageHeader { UDATA imageSize; /* image size in bytes */ + J9JavaVM *vm; + J9Pool *classLoaderBlocks; uintptr_t imageAddress; uintptr_t imageAlignedAddress; /* TODO: Will be removed once PAGE alignment is not needed anymore */ /* TODO: only three main class loaders stored for prototype and quick access. Need to allow user defined classloaders */ @@ -84,17 +86,6 @@ typedef struct JVMImageHeader { J9WSRP cInitialVirtualMethod; } JVMImageHeader; -/* - * Struct containing first three elements of JVMImageHeader - * - * Used for initial read from file. see @ref JVMImage::readImageFromFile - */ -typedef struct JVMImageSizeAndLocation { - UDATA imageSize; - uintptr_t imageAddress; - uintptr_t imageAlignedAddress; -} JVMImageSizeAndLocation; - /* Table structure to walk thorugh registered entries for J9Class, J9ClassLoader, and CPEntries * * Needed for fixup during teardown sequence diff --git a/runtime/oti/jvmimage_api.h b/runtime/oti/jvmimage_api.h index 672eec71802..7c540dac06b 100644 --- a/runtime/oti/jvmimage_api.h +++ b/runtime/oti/jvmimage_api.h @@ -58,7 +58,44 @@ void image_mem_free_memory(struct OMRPortLibrary *portLibrary, void *memoryPoint * * @return 0 on fail, 1 on success */ -UDATA initializeJVMImage(J9JavaVM *javaVM); +JVMImagePortLibrary * +initializeJVMImage(J9PortLibrary *portLibrary, BOOLEAN isColdRun, const char* ramCache); + +/** + * Initialize JVMImage + * + * @param jvmImagePortLibrary[in] jvmPortLib + * @param javaVM[in] vm token + */ +void +setupJVMImage(JVMImagePortLibrary *jvmImagePortLibrary, J9JavaVM *javaVM); + +/** + * Retrieve javaVM from JVm image + * + * @param jvmImagePortLibrary[in] jvmPortLib + * @return vm token + */ +J9JavaVM * +getJ9JavaVMFromJVMImage(JVMImagePortLibrary *jvmImagePortLibrary); + +/** + * Retrieve classloader blocks from JVM image + * + * @param javaVM[in] vm token + * @return classLoaderBlocks + */ +J9Pool* +getClassLoaderBlocks(J9JavaVM *javaVM); + +/** + * Store classloader blocks in JVM image + * + * @param javaVM[in] vm token + * @return classLoaderBlocks + */ +void +registerClassLoaderBlocks(J9JavaVM *javaVM); /* * Registers class loader to one of the three defined class loaders @@ -166,14 +203,16 @@ void initializeImageClassLoaderObject(J9JavaVM *javaVM, J9ClassLoader *classLoad * Frees memory of heap variables and jvmimage instance * Does not destroy jvmimageheap monitor * -* @param javaVM[in] the java vm +* @param jvmImagePortLibrary[in] the jvmImagePortlib */ -void shutdownJVMImage(J9JavaVM *vm); +void shutdownJVMImage(JVMImagePortLibrary *jvmImagePortLibrary); /* * Called on cold run to perform fixup of the image heap memory * Fixup of J9Class, J9ClassLoader, and J9CPEntry performed * +* TODO should rename this, not clear +* * @param javaVM[in] the java vm */ void teardownJVMImage(J9JavaVM *javaVM); @@ -203,4 +242,4 @@ void setInitialVMMethods(J9JavaVM *javaVM, J9Method **cInitialStaticMethod, J9Me } #endif -#endif /* jvmimage_api_h */ \ No newline at end of file +#endif /* jvmimage_api_h */ diff --git a/runtime/oti/jvmimageport.h b/runtime/oti/jvmimageport.h index 861c72e01ef..47075894ccf 100644 --- a/runtime/oti/jvmimageport.h +++ b/runtime/oti/jvmimageport.h @@ -50,4 +50,4 @@ typedef struct JVMImagePortLibrary { #define imem_allocate_memory(param1, category) IMAGE_OMRPORT_FROM_JVMIMAGEPORT(privateImagePortLibrary)->mem_allocate_memory(IMAGE_OMRPORT_FROM_JVMIMAGEPORT(privateImagePortLibrary),param1, J9_GET_CALLSITE(), category) #define imem_free_memory(param1) IMAGE_OMRPORT_FROM_JVMIMAGEPORT(privateImagePortLibrary)->mem_free_memory(IMAGE_OMRPORT_FROM_JVMIMAGEPORT(privateImagePortLibrary),param1) -#endif \ No newline at end of file +#endif diff --git a/runtime/oti/vm_api.h b/runtime/oti/vm_api.h index 6dc0d3abfc5..f36a2cb5ceb 100644 --- a/runtime/oti/vm_api.h +++ b/runtime/oti/vm_api.h @@ -36,6 +36,7 @@ #include "j9comp.h" #include "jni.h" #include "omrthread.h" +#include "jvmimageport.h" #ifdef __cplusplus extern "C" { @@ -45,6 +46,7 @@ extern "C" { #define J9_CREATEJAVAVM_ARGENCODING_LATIN 2 #define J9_CREATEJAVAVM_ARGENCODING_UTF8 4 #define J9_CREATEJAVAVM_ARGENCODING_PLATFORM 8 +#define J9_CREATEJAVAVM_RAM_CACHE 16 typedef struct J9CreateJavaVMParams { UDATA j2seVersion; @@ -54,6 +56,7 @@ typedef struct J9CreateJavaVMParams { J9JavaVM **globalJavaVM; J9PortLibrary *portLibrary; UDATA flags; + const char *ramCache; } J9CreateJavaVMParams; /* ---------------- FastJNI.cpp ---------------- */ diff --git a/runtime/util/cphelp.c b/runtime/util/cphelp.c index 7a59b19e809..b0c76ebf6c5 100644 --- a/runtime/util/cphelp.c +++ b/runtime/util/cphelp.c @@ -211,7 +211,7 @@ addJarToSystemClassLoaderClassPathEntries(J9JavaVM *vm, const char *filename) classPathLength += oldEntries[entryIndex].pathLength + 1; /* add 1 for a null character */ } /* Copy and grow the classPathEntries array */ - if (IS_COLD_RUN(vm)) { + if (IS_RAM_CACHE_ON(vm)) { newEntries = (J9ClassPathEntry *) imem_allocate_memory(sizeof(J9ClassPathEntry) * (entryCount + 1) + classPathLength, J9MEM_CATEGORY_CLASSES); } else { newEntries = (J9ClassPathEntry *) j9mem_allocate_memory(sizeof(J9ClassPathEntry) * (entryCount + 1) + classPathLength, J9MEM_CATEGORY_CLASSES); @@ -253,7 +253,7 @@ addJarToSystemClassLoaderClassPathEntries(J9JavaVM *vm, const char *filename) newCount = entryCount + 1; classLoader->classPathEntries = newEntries; classLoader->classPathEntryCount = newCount; - if (IS_COLD_RUN(vm)) { + if (IS_RAM_CACHE_ON(vm)) { imem_free_memory(oldEntries); } else { j9mem_free_memory(oldEntries); @@ -264,7 +264,7 @@ addJarToSystemClassLoaderClassPathEntries(J9JavaVM *vm, const char *filename) done: /* If any error occurred, discard any allocated memory and throw OutOfMemoryError */ if (0 == newCount) { - if (IS_COLD_RUN(vm)) { + if (IS_RAM_CACHE_ON(vm)) { imem_free_memory(oldEntries); } else { j9mem_free_memory(oldEntries); diff --git a/runtime/vm/JVMImage.cpp b/runtime/vm/JVMImage.cpp index 047cc9ffaee..0359ed03419 100644 --- a/runtime/vm/JVMImage.cpp +++ b/runtime/vm/JVMImage.cpp @@ -21,25 +21,50 @@ *******************************************************************************/ #include "JVMImage.hpp" +#include #include /* TODO: Change to OMRPortLibrary MMAP functionality. Currently does not allow MAP_FIXED as it is not supported in all architectures */ /* TODO: reallocation will fail so initial heap size is large (Should be PAGE_SIZE aligned) */ /* TODO: initial image size restriction will be removed once MMAP MAP_FIXED removed. see @ref JVMImage::readImageFromFile */ const UDATA JVMImage::INITIAL_IMAGE_SIZE = 100 * 1024 * 1024; +const UDATA JVMImage::CLASS_LOADER_REMOVE_COUNT = 8; - -JVMImage::JVMImage(J9JavaVM *javaVM) : - _vm(javaVM), +JVMImage::JVMImage(J9PortLibrary *portLibrary, const char* ramCache) : + _vm(NULL), + _portLibrary(portLibrary), _jvmImageHeader(NULL), - _heap(NULL) + _heap(NULL), + _invalidITable(NULL), + _ramCache(ramCache), + _jvmImageMonitor(NULL), + _jvmImagePortLibrary(NULL) +{ +} + +void +JVMImage::setJ9JavaVM(J9JavaVM *vm) +{ + _vm = vm; + _jvmImageHeader->vm = vm; +} + +void +JVMImage::setImagePortLib(JVMImagePortLibrary *jvmImagePortLibrary) +{ + _jvmImagePortLibrary = jvmImagePortLibrary; +} + +J9JavaVM * +JVMImage::getJ9JavaVM() { + return _vm; } JVMImage::~JVMImage() { PORT_ACCESS_FROM_JAVAVM(_vm); - + destroyMonitor(); if (IS_COLD_RUN(_vm)) { j9mem_free_memory((void*)_jvmImageHeader->imageAddress); } else { @@ -50,6 +75,7 @@ JVMImage::~JVMImage() bool JVMImage::initializeMonitor(void) { + /* TODO need to free monitor */ if (omrthread_monitor_init_with_name(&_jvmImageMonitor, 0, "JVM Image Heap Monitor") != 0) { return false; } @@ -95,13 +121,12 @@ JVMImage::destroyMonitor(void) } JVMImage * -JVMImage::createInstance(J9JavaVM *vm) +JVMImage::createInstance(J9PortLibrary *portLibrary, const char* ramCache) { - PORT_ACCESS_FROM_JAVAVM(vm); - + PORT_ACCESS_FROM_PORT(portLibrary); JVMImage *jvmInstance = (JVMImage *)j9mem_allocate_memory(sizeof(JVMImage), J9MEM_CATEGORY_CLASSES); if (NULL != jvmInstance) { - new(jvmInstance) JVMImage(vm); + new(jvmInstance) JVMImage(portLibrary, ramCache); } return jvmInstance; @@ -114,6 +139,10 @@ JVMImage::setupWarmRun(void) return IMAGE_ERROR; } + if (!initializeMonitor()) { + return IMAGE_ERROR; + } + return IMAGE_OK; } @@ -152,14 +181,14 @@ JVMImage::setupColdRun(void) void * JVMImage::allocateImageMemory(UDATA size) { - PORT_ACCESS_FROM_JAVAVM(_vm); - - void *imageAddress = j9mem_allocate_memory(size + PAGE_SIZE, J9MEM_CATEGORY_CLASSES); + PORT_ACCESS_FROM_PORT(_portLibrary); + UDATA pageSize = j9vmem_supported_page_sizes()[0]; + void *imageAddress = j9mem_allocate_memory(size + pageSize, J9MEM_CATEGORY_CLASSES); if (NULL == imageAddress) { return NULL; } - _jvmImageHeader = (JVMImageHeader *) PAGE_SIZE_ALIGNED_ADDRESS(imageAddress); + _jvmImageHeader = (JVMImageHeader *) ROUND_UP_TO_POWEROF2((UDATA)imageAddress, pageSize); _jvmImageHeader->imageAddress = (uintptr_t)imageAddress; _jvmImageHeader->imageAlignedAddress = (uintptr_t)_jvmImageHeader; _jvmImageHeader->imageSize = size; @@ -178,7 +207,7 @@ JVMImage::reallocateImageMemory(UDATA size) void * JVMImage::initializeHeap(void) { - PORT_ACCESS_FROM_JAVAVM(_vm); + PORT_ACCESS_FROM_PORT(_portLibrary); _heap = j9heap_create((J9Heap *)(_jvmImageHeader + 1), JVMImage::INITIAL_IMAGE_SIZE - sizeof(_jvmImageHeader), 0); if (NULL == _heap) { @@ -243,7 +272,7 @@ JVMImage::subAllocateMemory(uintptr_t byteAmount) omrthread_monitor_enter(_jvmImageMonitor); - OMRPortLibrary *portLibrary = IMAGE_OMRPORT_FROM_JAVAVM(_vm); + OMRPortLibrary *portLibrary = IMAGE_OMRPORT_FROM_JVMIMAGEPORT(_jvmImagePortLibrary); void *memStart = portLibrary->heap_allocate(portLibrary, _heap, byteAmount); /* image memory is not large enough and needs to be reallocated */ if (NULL == memStart) { @@ -263,7 +292,7 @@ JVMImage::reallocateMemory(void *address, uintptr_t byteAmount) { omrthread_monitor_enter(_jvmImageMonitor); - OMRPortLibrary *portLibrary = IMAGE_OMRPORT_FROM_JAVAVM(_vm); + OMRPortLibrary *portLibrary = IMAGE_OMRPORT_FROM_JVMIMAGEPORT(_jvmImagePortLibrary); void *memStart = portLibrary->heap_reallocate(portLibrary, _heap, address, byteAmount); /* image memory is not large enough and needs to be reallocated */ if (NULL == memStart) { @@ -281,7 +310,7 @@ JVMImage::freeSubAllocatedMemory(void *address) { omrthread_monitor_enter(_jvmImageMonitor); - OMRPortLibrary *portLibrary = IMAGE_OMRPORT_FROM_JAVAVM(_vm); + OMRPortLibrary *portLibrary = IMAGE_OMRPORT_FROM_JVMIMAGEPORT(_jvmImagePortLibrary); portLibrary->heap_free(portLibrary, _heap, address); omrthread_monitor_exit(_jvmImageMonitor); @@ -355,6 +384,28 @@ JVMImage::setClassLoader(J9ClassLoader *classLoader, uint32_t classLoaderCategor } } +void +JVMImage::setClassLoaderBlocks(J9JavaVM *vm) +{ + _jvmImageHeader->classLoaderBlocks = vm->classLoaderBlocks; +} + +J9Pool* +JVMImage::getClassLoaderBlocks() +{ + return _jvmImageHeader->classLoaderBlocks; +} + + +void +JVMImage::fixupVMStructures(void) +{ + UDATA omrRuntimeOffset = ROUND_UP_TO_POWEROF2(sizeof(J9JavaVM), 8); + UDATA omrVMOffset = ROUND_UP_TO_POWEROF2(omrRuntimeOffset + sizeof(OMR_Runtime), 8); + UDATA vmAllocationSize = omrVMOffset + sizeof(OMR_VM); + memset(_vm, 0, vmAllocationSize); +} + void JVMImage::fixupClassLoaders(void) { @@ -379,6 +430,41 @@ JVMImage::fixupClassLoaders(void) } } +void +JVMImage::removeUnpersistedClassLoaders(void) +{ + /* wont need this once we support all classloaders */ + pool_state classLoaderWalkState = {0}; + UDATA numOfClassLoaders = pool_numElements(_vm->classLoaderBlocks); + U_8 buf[CLASS_LOADER_REMOVE_COUNT * sizeof(J9ClassLoader*)]; + J9ClassLoader **removeLoaders = (J9ClassLoader **) buf; + J9VMThread *vmThread = currentVMThread(_vm); + UDATA count = 0; + + if (CLASS_LOADER_REMOVE_COUNT < numOfClassLoaders) { + PORT_ACCESS_FROM_PORT(_portLibrary); + removeLoaders = (J9ClassLoader **) j9mem_allocate_memory(numOfClassLoaders * sizeof(J9ClassLoader*), J9MEM_CATEGORY_CLASSES); + if (NULL == removeLoaders) { + /* TODO error handling for fixups */ + Assert_VM_unreachable(); + } + } + + J9ClassLoader *classloader = (J9ClassLoader *) pool_startDo(_vm->classLoaderBlocks, &classLoaderWalkState); + while (NULL != classloader) { + if ((classloader != _vm->applicationClassLoader) && (classloader != _vm->extensionClassLoader) && (classloader != _vm->systemClassLoader)) { + removeLoaders[count] = classloader; + count++; + } + classloader = (J9ClassLoader *) pool_nextDo(&classLoaderWalkState); + } + + for (UDATA i = 0; i < count; i++) { + freeClassLoader(removeLoaders[i], _vm, vmThread, FALSE); + } +} + + void JVMImage::fixupClasses(void) { @@ -412,9 +498,6 @@ JVMImage::fixupClass(J9Class *clazz) clazz->initializeStatus = J9ClassInitNotInitialized; clazz->jniIDs = NULL; clazz->replacedClass = NULL; - clazz->callSites = NULL; - clazz->methodTypes = NULL; - clazz->varHandleMethodTypes = NULL; clazz->gcLink = NULL; UDATA totalStaticSlots = totalStaticSlotsForClass(clazz->romClass); @@ -431,6 +514,17 @@ JVMImage::fixupClass(J9Class *clazz) clazz->specialSplitMethodTable[i] = (J9Method*)_vm->initialMethods.initialSpecialMethod; } } + if (NULL != clazz->callSites) { + memset(clazz->callSites, 0, sizeof(UDATA) * clazz->romClass->callSiteCount); + } + + if (NULL != clazz->methodTypes) { + memset(clazz->methodTypes, 0, sizeof(UDATA) * clazz->romClass->methodTypeCount); + } + + if (NULL != clazz->varHandleMethodTypes) { + memset(clazz->varHandleMethodTypes, 0, sizeof(UDATA) * clazz->romClass->varHandleMethodTypeCount); + } } void @@ -510,26 +604,36 @@ JVMImage::fixupClassPathEntries(void) bool JVMImage::readImageFromFile(void) { - Trc_VM_ReadImageFromFile_Entry(_heap, _vm->ramStateFilePath); + Trc_VM_ReadImageFromFile_Entry(_heap, _ramCache); - OMRPortLibrary *portLibrary = IMAGE_OMRPORT_FROM_JAVAVM(_vm); - OMRPORT_ACCESS_FROM_OMRPORT(portLibrary); + OMRPORT_ACCESS_FROM_OMRPORT(&_portLibrary->omrPortLibrary); - intptr_t fileDescriptor = omrfile_open(_vm->ramStateFilePath, EsOpenRead | EsOpenWrite, 0444); + intptr_t fileDescriptor = omrfile_open(_ramCache, EsOpenRead | EsOpenWrite, 0444); if (-1 == fileDescriptor) { + printf("falied to open ramCache file file=%s \n", _ramCache); return false; } /* Read image header size and location then mmap the rest of the image (heap) into memory */ - JVMImageSizeAndLocation imageHeaderBuffer; - omrfile_read(fileDescriptor, (void *)&imageHeaderBuffer, sizeof(JVMImageSizeAndLocation)); + JVMImageHeader imageHeaderBuffer; + if (-1 == omrfile_read(fileDescriptor, (void *)&imageHeaderBuffer, sizeof(JVMImageHeader))) { + return false; + } /* TODO: currently mmap uses sys/mman.h and MAP_FIXED. Once random memory loading is complete it will change to omr mmap without MAP_FIXED */ _jvmImageHeader = (JVMImageHeader *)mmap( (void *)imageHeaderBuffer.imageAlignedAddress, imageHeaderBuffer.imageSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, fileDescriptor, 0); + if (-1 == (IDATA)_jvmImageHeader) { + return false; + } + if (imageHeaderBuffer.imageAlignedAddress != (UDATA) _jvmImageHeader) { + return false; + } _heap = (J9Heap *)(_jvmImageHeader + 1); + _vm = _jvmImageHeader->vm; + _vm->ramStateFilePath = (char*) _ramCache; omrfile_close(fileDescriptor); @@ -541,12 +645,12 @@ JVMImage::readImageFromFile(void) bool JVMImage::writeImageToFile(void) { - Trc_VM_WriteImageToFile_Entry(_heap, _vm->ramStateFilePath); + Trc_VM_WriteImageToFile_Entry(_heap, _ramCache); - OMRPortLibrary *portLibrary = IMAGE_OMRPORT_FROM_JAVAVM(_vm); + OMRPortLibrary *portLibrary = (OMRPortLibrary *) _portLibrary; OMRPORT_ACCESS_FROM_OMRPORT(portLibrary); - intptr_t fileDescriptor = omrfile_open(_vm->ramStateFilePath, EsOpenCreate | EsOpenCreateAlways | EsOpenWrite, 0666); + intptr_t fileDescriptor = omrfile_open(_ramCache, EsOpenCreate | EsOpenCreateAlways | EsOpenWrite, 0666); if (-1 == fileDescriptor) { return false; } @@ -565,20 +669,21 @@ JVMImage::writeImageToFile(void) void JVMImage::teardownImage(void) { + removeUnpersistedClassLoaders(); fixupClassLoaders(); fixupClasses(); fixupClassPathEntries(); - writeImageToFile(); + } JVMImagePortLibrary * -setupJVMImagePortLibrary(J9JavaVM *javaVM) +setupJVMImagePortLibrary(J9PortLibrary *portLibrary) { - PORT_ACCESS_FROM_JAVAVM(javaVM); + PORT_ACCESS_FROM_PORT(portLibrary); JVMImagePortLibrary *jvmImagePortLibrary = (JVMImagePortLibrary*)j9mem_allocate_memory(sizeof(JVMImagePortLibrary), OMRMEM_CATEGORY_PORT_LIBRARY); - OMRPORT_ACCESS_FROM_J9PORT(javaVM->portLibrary); + OMRPORT_ACCESS_FROM_J9PORT(portLibrary); memcpy(&(jvmImagePortLibrary->portLibrary), privateOmrPortLibrary, sizeof(OMRPortLibrary)); jvmImagePortLibrary->portLibrary.mem_allocate_memory = image_mem_allocate_memory; jvmImagePortLibrary->portLibrary.mem_free_memory = image_mem_free_memory; @@ -588,33 +693,46 @@ setupJVMImagePortLibrary(J9JavaVM *javaVM) } -extern "C" UDATA -initializeJVMImage(J9JavaVM *javaVM) +extern "C" JVMImagePortLibrary * +initializeJVMImage(J9PortLibrary *portLibrary, BOOLEAN isColdRun, const char* ramCache) { - JVMImagePortLibrary *jvmImagePortLibrary = setupJVMImagePortLibrary(javaVM); - JVMImage *jvmImage = JVMImage::createInstance(javaVM); + JVMImagePortLibrary *jvmImagePortLibrary = setupJVMImagePortLibrary(portLibrary); + JVMImage *jvmImage = JVMImage::createInstance(portLibrary, ramCache); if (NULL == jvmImagePortLibrary || NULL == jvmImage) { goto _error; } - javaVM->jvmImagePortLibrary = jvmImagePortLibrary; + jvmImagePortLibrary->jvmImage = jvmImage; + ((JVMImage *)jvmImagePortLibrary->jvmImage)->setImagePortLib(jvmImagePortLibrary); - if (IS_COLD_RUN(javaVM) - && (IMAGE_ERROR == jvmImage->setupColdRun())) { + if (isColdRun && (IMAGE_ERROR == jvmImage->setupColdRun())) { goto _error; } - if(IS_WARM_RUN(javaVM) - && (IMAGE_ERROR == jvmImage->setupWarmRun())) { + if(!isColdRun && (IMAGE_ERROR == jvmImage->setupWarmRun())) { goto _error; } - return 1; + return jvmImagePortLibrary; _error: - shutdownJVMImage(javaVM); + shutdownJVMImage(jvmImagePortLibrary); jvmImage->destroyMonitor(); - return 0; + return NULL; +} + +extern "C" void +setupJVMImage(JVMImagePortLibrary *jvmImagePortLibrary, J9JavaVM *javaVM) +{ + ((JVMImage *)jvmImagePortLibrary->jvmImage)->setJ9JavaVM(javaVM); + javaVM->jvmImagePortLibrary = jvmImagePortLibrary; +} + +extern "C" J9JavaVM * +getJ9JavaVMFromJVMImage(JVMImagePortLibrary *jvmImagePortLibrary) +{ + ((JVMImage *)jvmImagePortLibrary->jvmImage)->fixupVMStructures(); + return ((JVMImage *)jvmImagePortLibrary->jvmImage)->getJ9JavaVM(); } extern "C" void @@ -630,6 +748,24 @@ registerClassLoader(J9JavaVM *javaVM, J9ClassLoader *classLoader, uint32_t class jvmImage->setClassLoader(classLoader, classLoaderCategory); } +extern "C" void +registerClassLoaderBlocks(J9JavaVM *javaVM) +{ + IMAGE_ACCESS_FROM_JAVAVM(javaVM); + Assert_VM_notNull(jvmImage); + + jvmImage->setClassLoaderBlocks(javaVM); +} + +extern "C" J9Pool* +getClassLoaderBlocks(J9JavaVM *javaVM) +{ + IMAGE_ACCESS_FROM_JAVAVM(javaVM); + Assert_VM_notNull(jvmImage); + + return jvmImage->getClassLoaderBlocks(); +} + extern "C" void registerClass(J9JavaVM *javaVM, J9Class *clazz) { @@ -678,22 +814,24 @@ findClassLoader(J9JavaVM *javaVM, uint32_t classLoaderCategory) { IMAGE_ACCESS_FROM_JAVAVM(javaVM); Assert_VM_notNull(jvmImage); - + J9ClassLoader *classLoader = NULL; /* TODO: Function will change when hash table is created and there would be no need for accessing specific class loaders (hardcoded) */ if (IS_SYSTEM_CLASSLOADER_CATEGORY(classLoaderCategory)) { - return jvmImage->getSystemClassLoader(); + classLoader = jvmImage->getSystemClassLoader(); } if (IS_APP_CLASSLOADER_CATEGORY(classLoaderCategory)) { - return jvmImage->getApplicationClassLoader(); + classLoader = jvmImage->getApplicationClassLoader(); } if (IS_EXTENSION_CLASSLOADER_CATEGORY(classLoaderCategory)) { - return jvmImage->getExtensionClassLoader(); + classLoader = jvmImage->getExtensionClassLoader(); } - /* find should never get here */ - return NULL; + TRIGGER_J9HOOK_VM_CLASS_LOADER_CREATED(javaVM->hookInterface, javaVM, classLoader); + Assert_VM_notNull(classLoader); + + return classLoader; } extern "C" void @@ -715,7 +853,6 @@ extern "C" J9Class * initializeImageClassObject(J9VMThread *vmThread, J9ClassLoader *classLoader, J9Class *clazz) { J9JavaVM *javaVM = vmThread->javaVM; - /* Allocate class object */ J9Class *jlClass = J9VMCONSTANTPOOL_CLASSREF_AT(javaVM, J9VMCONSTANTPOOL_JAVALANGCLASS)->value; @@ -755,18 +892,21 @@ initializeImageClassObject(J9VMThread *vmThread, J9ClassLoader *classLoader, J9C } extern "C" void -shutdownJVMImage(J9JavaVM *javaVM) +shutdownJVMImage(JVMImagePortLibrary *jvmImagePortLibrary) { - IMAGE_ACCESS_FROM_JAVAVM(javaVM); - Assert_VM_notNull(jvmImage); + if (NULL != jvmImagePortLibrary->jvmImage) { + PORT_ACCESS_FROM_PORT(((JVMImage *)jvmImagePortLibrary->jvmImage)->getJ9JavaVM()->portLibrary); + Assert_VM_notNull(jvmImagePortLibrary); - if (NULL != jvmImage) { - PORT_ACCESS_FROM_JAVAVM(javaVM); + JVMImage *jvmImage = (JVMImage *) jvmImagePortLibrary->jvmImage; - jvmImage->~JVMImage(); - j9mem_free_memory(jvmImage); - j9mem_free_memory(JVMIMAGEPORT_FROM_JAVAVM(javaVM)); - javaVM->jvmImagePortLibrary = NULL; + if (NULL != jvmImage) { + jvmImage->~JVMImage(); + j9mem_free_memory(jvmImage); + /* TODO */ + //j9mem_free_memory(JVMIMAGEPORT_FROM_JAVAVM(javaVM)); + } + j9mem_free_memory(jvmImagePortLibrary); } } diff --git a/runtime/vm/JVMImage.hpp b/runtime/vm/JVMImage.hpp index 3ba5e5c69df..c0968e48783 100644 --- a/runtime/vm/JVMImage.hpp +++ b/runtime/vm/JVMImage.hpp @@ -40,15 +40,17 @@ class JVMImage */ private: J9JavaVM *_vm; - + J9PortLibrary *_portLibrary; JVMImageHeader *_jvmImageHeader; J9Heap *_heap; J9ITable *_invalidITable; - + const char *_ramCache; omrthread_monitor_t _jvmImageMonitor; + JVMImagePortLibrary *_jvmImagePortLibrary; protected: public: static const UDATA INITIAL_IMAGE_SIZE; + static const UDATA CLASS_LOADER_REMOVE_COUNT; /* * Function Members @@ -77,17 +79,27 @@ class JVMImage void fixupMethodRunAddresses(J9Class *ramClass); void fixupConstantPool(J9Class *ramClass); void fixupClassPathEntries(void); + void removeUnpersistedClassLoaders(void); + protected: void *operator new(size_t size, void *memoryPointer) { return memoryPointer; } public: - JVMImage(J9JavaVM *vm); + JVMImage(J9PortLibrary *portLibrary, const char* ramCache); ~JVMImage(); - static JVMImage* createInstance(J9JavaVM *javaVM); + static JVMImage* createInstance(J9PortLibrary *portLibrary, const char* ramCache); + + void setJ9JavaVM(J9JavaVM *vm); + void setImagePortLib(JVMImagePortLibrary *jvmImagePortLibrary); + J9JavaVM* getJ9JavaVM(); + + void setClassLoaderBlocks(J9JavaVM *vm); + J9Pool* getClassLoaderBlocks(); - ImageRC setupWarmRun(void); - ImageRC setupColdRun(void); + ImageRC setupWarmRun(); + ImageRC setupColdRun(); + void fixupVMStructures(void); void teardownImage(void); /* Suballocator functions */ diff --git a/runtime/vm/classsupport.c b/runtime/vm/classsupport.c index 5b954a2321a..8c21c2e60cd 100644 --- a/runtime/vm/classsupport.c +++ b/runtime/vm/classsupport.c @@ -953,12 +953,18 @@ loadNonArrayClass(J9VMThread* vmThread, J9Module *j9module, U_8* className, UDAT foundClass = hashClassTableAt(classLoader, className, classNameLength); if (NULL != foundClass) { - if (IS_WARM_RUN(vmThread->javaVM) - && J9_ARE_ALL_BITS_SET(vmThread->javaVM->extendedRuntimeFlags, J9_EXTENDED_RUNTIME_CLASS_OBJECT_ASSIGNED) - && foundClass->classObject == NULL) { - foundClass = initializeImageClassObject(vmThread, classLoader, foundClass); + if (IS_WARM_RUN(vmThread->javaVM)) { + UDATA failed = FALSE; + if (J9_ARE_ALL_BITS_SET(vmThread->javaVM->extendedRuntimeFlags, J9_EXTENDED_RUNTIME_CLASS_OBJECT_ASSIGNED) + && foundClass->classObject == NULL) + { + foundClass = initializeImageClassObject(vmThread, classLoader, foundClass); + } + TRIGGER_J9HOOK_VM_INTERNAL_CLASS_LOAD(vmThread->javaVM->hookInterface, vmThread, foundClass, failed); + if (failed) { + /* TODO should do something with the failed value */ + } } - if (!fastMode) { omrthread_monitor_exit(vmThread->javaVM->classTableMutex); } diff --git a/runtime/vm/jvmfree.c b/runtime/vm/jvmfree.c index ba678cd4ef5..81deef4807e 100644 --- a/runtime/vm/jvmfree.c +++ b/runtime/vm/jvmfree.c @@ -87,7 +87,7 @@ freeClassLoaderEntries(J9VMThread * vmThread, J9ClassPathEntry * entries, UDATA cpEntry++; } - if (IS_COLD_RUN(vm)) { + if (IS_RAM_CACHE_ON(vm)) { imem_free_memory(entries); } else { j9mem_free_memory(entries); diff --git a/runtime/vm/jvminit.c b/runtime/vm/jvminit.c index 2ba20978c0c..94c80d5601b 100644 --- a/runtime/vm/jvminit.c +++ b/runtime/vm/jvminit.c @@ -862,11 +862,14 @@ freeJavaVM(J9JavaVM * vm) } if (IS_RAM_CACHE_ON(vm)) { - shutdownJVMImage(vm); + JVMImagePortLibrary* imagePortLibrary = vm->jvmImagePortLibrary; + PORT_ACCESS_FROM_PORT((J9PortLibrary *) imagePortLibrary); + j9mem_free_memory(vm); + shutdownJVMImage(imagePortLibrary); + } else { + j9mem_free_memory(vm); } - j9mem_free_memory(vm); - if (NULL != tmpLib->self_handle) { tmpLib->port_shutdown_library(tmpLib); } else { @@ -954,10 +957,42 @@ initializeJavaVM(void * osMainThread, J9JavaVM ** vmPtr, J9CreateJavaVMParams *c return JNI_ERR; } - /* Allocate the VM, including the extra OMR structures */ - vm = allocateJavaVMWithOMR(portLibrary); - if (vm == NULL) { - return JNI_ENOMEM; + if (J9_ARE_ALL_BITS_SET(createParams->flags, J9_CREATEJAVAVM_RAM_CACHE)) { + BOOLEAN isColdRun = TRUE; + JVMImagePortLibrary *imagePortLib = NULL; + + /* TODO need to use portlib functions */ + if (-1 != access(createParams->ramCache, F_OK)) { + isColdRun = FALSE; + } + + imagePortLib = initializeJVMImage(portLibrary, isColdRun, createParams->ramCache); + + if (FALSE == imagePortLib) { + return JNI_ENOMEM; + } + if (isColdRun) { + vm = allocateJavaVMWithOMR((J9PortLibrary *)imagePortLib); + } else { + vm = getJ9JavaVMFromJVMImage(imagePortLib); + } + setupJVMImage(imagePortLib, vm); + + if (vm == NULL) { + return JNI_ENOMEM; + } + + if (isColdRun) { + vm->extendedRuntimeFlags2 |= J9_EXTENDED_RUNTIME2_RAMSTATE_COLD_RUN; + } else { + vm->extendedRuntimeFlags2 |= J9_EXTENDED_RUNTIME2_RAMSTATE_WARM_RUN; + } + } else { + /* Allocate the VM, including the extra OMR structures */ + vm = allocateJavaVMWithOMR(portLibrary); + if (vm == NULL) { + return JNI_ENOMEM; + } } #if defined(J9VM_THR_ASYNC_NAME_UPDATE) @@ -2107,7 +2142,7 @@ IDATA VMInitStages(J9JavaVM *vm, IDATA stage, void* reserved) { if (NULL == (vm->jniWeakGlobalReferences = pool_new(sizeof(UDATA), 0, 0, POOL_NO_ZERO, J9_GET_CALLSITE(), J9MEM_CATEGORY_JNI, POOL_FOR_PORT(vm->portLibrary)))) goto _error; - /* TODO: Load if Warm run */ + /* TODO: Load if Warm run, also classloading stacks do not need to be persisted */ if (IS_COLD_RUN(vm)) { if (NULL == (vm->classLoadingStackPool = pool_new(sizeof(J9ClassLoadingStackElement), 0, 0, 0, J9_GET_CALLSITE(), J9MEM_CATEGORY_CLASSES, POOL_FOR_PORT(IMAGE_OMRPORT_FROM_JAVAVM(vm))))) { goto _error; @@ -2115,12 +2150,19 @@ IDATA VMInitStages(J9JavaVM *vm, IDATA stage, void* reserved) { if (NULL == (vm->classLoaderBlocks = pool_new(sizeof(J9ClassLoader), 0, 0, 0, J9_GET_CALLSITE(), J9MEM_CATEGORY_CLASSES, POOL_FOR_PORT(IMAGE_OMRPORT_FROM_JAVAVM(vm))))) { goto _error; } + registerClassLoaderBlocks(vm); } else { if (NULL == (vm->classLoadingStackPool = pool_new(sizeof(J9ClassLoadingStackElement), 0, 0, 0, J9_GET_CALLSITE(), J9MEM_CATEGORY_CLASSES, POOL_FOR_PORT(vm->portLibrary)))) { goto _error; } - if (NULL == (vm->classLoaderBlocks = pool_new(sizeof(J9ClassLoader), 0, 0, 0, J9_GET_CALLSITE(), J9MEM_CATEGORY_CLASSES, POOL_FOR_PORT(vm->portLibrary)))) { - goto _error; + if (IS_WARM_RUN(vm)) { + if (NULL == (vm->classLoaderBlocks = getClassLoaderBlocks(vm))) { + goto _error; + } + } else { + if (NULL == (vm->classLoaderBlocks = pool_new(sizeof(J9ClassLoader), 0, 0, 0, J9_GET_CALLSITE(), J9MEM_CATEGORY_CLASSES, POOL_FOR_PORT(vm->portLibrary)))) { + goto _error; + } } } @@ -6001,12 +6043,6 @@ protectedInitializeJavaVM(J9PortLibrary* portLibrary, void * userData) goto error; } - /* TODO: Create separate initialization stage for RAM Caching */ - if (IS_RAM_CACHE_ON(vm) - && 0 == initializeJVMImage(vm)) { - goto error; - } - if (JNI_OK != (stageRC = runInitializationStage(vm, HEAP_STRUCTURES_INITIALIZED))) { goto error; }