< prev index next >

src/hotspot/share/memory/metaspaceShared.cpp

Print this page

        

*** 22,35 **** --- 22,37 ---- * */ #include "precompiled.hpp" #include "jvm.h" + #include "classfile/classFileStream.hpp" #include "classfile/classLoaderDataGraph.hpp" #include "classfile/classListParser.hpp" #include "classfile/classLoaderExt.hpp" #include "classfile/dictionary.hpp" + #include "classfile/klassFactory.hpp" #include "classfile/loaderConstraints.hpp" #include "classfile/javaClasses.inline.hpp" #include "classfile/placeholders.hpp" #include "classfile/symbolTable.hpp" #include "classfile/stringTable.hpp"
*** 57,68 **** --- 59,72 ---- #include "oops/methodData.hpp" #include "oops/objArrayKlass.hpp" #include "oops/objArrayOop.hpp" #include "oops/oop.inline.hpp" #include "oops/typeArrayKlass.hpp" + #include "oops/typeArrayOop.inline.hpp" #include "prims/jvmtiRedefineClasses.hpp" #include "runtime/handles.inline.hpp" + #include "runtime/javaCalls.hpp" #include "runtime/os.hpp" #include "runtime/safepointVerifiers.hpp" #include "runtime/signature.hpp" #include "runtime/timerTrace.hpp" #include "runtime/vmThread.hpp"
*** 1933,1948 **** --- 1937,2078 ---- Heap_lock : NULL); // needed by HeapShared::run_gc() VMThread::execute(&op); } } + static GrowableArray<char *>* lambda_list = NULL; + + void MetaspaceShared::regenerate_holder_classes(TRAPS) { + assert(lambda_list != NULL, "Bad List"); + ResourceMark rm(THREAD); + + Symbol* helper_name = vmSymbols::java_lang_invoke_InvokerBytecodeGeneratorHelper(); + Klass* helper_klass = SystemDictionary::resolve_or_null(helper_name, THREAD); + guarantee(helper_klass != NULL, "java/lang/invoke/InvokerByteCodeGeneratorHelper exist!"); + + int len = lambda_list->length(); + objArrayHandle list_lines = oopFactory::new_objArray_handle(SystemDictionary::String_klass(), len, CHECK); + for (int i = 0; i < len; i++) { + Handle h_line = java_lang_String::create_from_str(lambda_list->at(i), CHECK); + list_lines->obj_at_put(i, h_line()); + } + + // + // Object[] InvokerBytecodeGeneratorHelper.generateMethodHandleHolderClasses(String[] lines) + // the returned Object[] layout: + // name, byte[], name, byte[] .... + Symbol* method = vmSymbols::generateMethodHandleHolderClasses(); + Symbol* signrs = vmSymbols::generateMethodHandleHolderClasses_signature(); + + jobject ret_obj; + JavaValue result(T_OBJECT); + JavaCalls::call_static(&result, helper_klass, method, signrs, list_lines, THREAD); + ret_obj = result.get_jobject(); + if (!HAS_PENDING_EXCEPTION) { + if (ret_obj == NULL) { + log_info(cds)("Failed call to %s.%s", helper_name->as_C_string(), method->as_C_string()); + return; + } + } else { + log_info(cds)("Exception happened: %s", PENDING_EXCEPTION->klass()->name()->as_C_string()); + CLEAR_PENDING_EXCEPTION; + return; + } + + objArrayHandle h_array(THREAD, (objArrayOop)ret_obj); + int sz = h_array->length(); + assert(sz % 2 == 0 && sz >= 2, "Must be even size of length"); + for (int i = 0; i < sz; i+= 2) { + Handle h_name(THREAD, h_array->obj_at(i)); + Handle h_bytes(THREAD, h_array->obj_at(i+1)); + assert(h_name != NULL, "Class name is NULL"); + assert(h_bytes != NULL, "Class bytes is NULL"); + reload_class(h_name, h_bytes, THREAD); + } + + } + + // the format maybe of "/java.base/package/class_name.class" + char* get_full_class_name(char* path_name) { + char* end = strstr(path_name, ".class"); + if (end == NULL) { + end = path_name + strlen(path_name); + } + char* start = strstr(path_name, "/java.base/"); + if (start == NULL) { + start = path_name; + } else { + start = path_name + strlen("/java.base/"); + } + assert(start < end, "Sanity check"); + size_t size = end - start + 1; + + char* full_name = (char*)os::malloc(size, mtInternal); + size_t i = 0; + while (i < size) { + full_name[i++] = *start++; + } + full_name[size - 1] = '\0'; + return full_name; + } + + // k - the class full name + // v - the class bytes + void MetaspaceShared::reload_class(Handle k, Handle v, TRAPS) { + char* path_name = java_lang_String::as_utf8_string(k()); + char* class_name = get_full_class_name(path_name); + Symbol* sym = SymbolTable::probe((const char*)class_name, (int)strlen(class_name)); + assert(sym != NULL, "The class should be loaded already"); + // the class must exist + Klass* klass = SystemDictionary::resolve_or_null(sym, THREAD); + if (klass == NULL) { + log_info(cds)("Class %s not present, skip", class_name); + return; + } + + typeArrayOop bytes = (typeArrayOop)v(); + int len = bytes->length(); + u1* buf = (u1*)bytes->byte_at_addr(0); + ClassFileStream st(buf, len, NULL, ClassFileStream::verify); + ClassLoaderData* cld = ClassLoaderData::the_null_class_loader_data(); + Handle protection_domain; + ClassLoadInfo cl_info(protection_domain); + + InstanceKlass* result = KlassFactory::create_from_stream(&st, + sym, + cld, + cl_info, + CHECK); + + if (HAS_PENDING_EXCEPTION) { + log_info(cds)("Exception happened: %s", PENDING_EXCEPTION->klass()->name()->as_C_string()); + log_info(cds)("Could not create InstanceKlass for class %s", class_name); + CLEAR_PENDING_EXCEPTION; + return; + } + + // replace with the new created klass. + { + MutexLocker lock(THREAD, SystemDictionary_lock); + InstanceKlass* old = cld->replace_class(sym, result); + SystemDictionaryShared::set_excluded(old); + log_info(cds)("Replace class %s, old: %p new: %p", class_name, old, result); + } + + // add to hierarchy and set state to loaded. + SystemDictionaryShared::add_replaced_class(result, THREAD); + // new class not linked yet. + try_link_class(result, THREAD); + assert(!HAS_PENDING_EXCEPTION, "Invariant"); + } int MetaspaceShared::preload_classes(const char* class_list_path, TRAPS) { ClassListParser parser(class_list_path); int class_count = 0; while (parser.parse_one_line()) { + if (!parser.is_lambda_format()) { Klass* klass = parser.load_current_class(THREAD); if (HAS_PENDING_EXCEPTION) { if (klass == NULL && (PENDING_EXCEPTION->klass()->name() == vmSymbols::java_lang_ClassNotFoundException())) { // print a warning only when the pending exception is class not found
*** 1964,1978 **** // are loaded in order that the related data structures (klass and // cpCache) are located together. try_link_class(ik, THREAD); guarantee(!HAS_PENDING_EXCEPTION, "exception in link_class"); } - class_count++; } } return class_count; } // Returns true if the class's status has changed bool MetaspaceShared::try_link_class(InstanceKlass* ik, TRAPS) { --- 2094,2117 ---- // are loaded in order that the related data structures (klass and // cpCache) are located together. try_link_class(ik, THREAD); guarantee(!HAS_PENDING_EXCEPTION, "exception in link_class"); } class_count++; } + } else { + if (lambda_list == NULL) { + lambda_list = new GrowableArray<char*>(8); + } + lambda_list->append(parser.current_line()); + } } + // call java to generate holder classes then replace them in dictionary. + if (lambda_list != NULL) { + regenerate_holder_classes(THREAD); + } return class_count; } // Returns true if the class's status has changed bool MetaspaceShared::try_link_class(InstanceKlass* ik, TRAPS) {
*** 2690,2699 **** } else { st->print("CDS disabled."); } st->cr(); } - - - - - --- 2829,2833 ----
< prev index next >