< 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 >