< prev index next >

src/hotspot/share/prims/jvm.cpp

Print this page

        

*** 951,976 **** --- 951,1133 ---- Handle protection_domain (THREAD, JNIHandles::resolve(pd)); Klass* k = SystemDictionary::resolve_from_stream(class_name, class_loader, protection_domain, &st, + NULL, // dynamic_nest_host CHECK_NULL); if (log_is_enabled(Debug, class, resolve) && k != NULL) { trace_class_resolution(k); } return (jclass) JNIHandles::make_local(env, k->java_mirror()); } + enum { + NESTMATE = java_lang_invoke_MemberName::MN_NESTMATE_CLASS, + NONFINDABLE_CLASS = java_lang_invoke_MemberName::MN_NONFINDABLE_CLASS, + WEAK_CLASS = java_lang_invoke_MemberName::MN_WEAK_CLASS, + ACCESS_VM_ANNOTATIONS = java_lang_invoke_MemberName::MN_ACCESS_VM_ANNOTATIONS + }; + + /* + * Define a class with the specified flags that indicates if it's a nestmate, + * not findable, or weakly reachable from class loader. + * + * Same class may be defined by multiple threads at the same time. + * Should the VM keep the classData (the one successfully defined the class) + * as if a private static field is declared in the class? + */ + static jclass jvm_lookup_define_class(JNIEnv *env, jclass lookup, const char *name, + jobject loader, const jbyte *buf, jsize len, jobject pd, + int flags, jobject classData, TRAPS) { + assert(THREAD->is_Java_thread(), "must be a JavaThread"); + JavaThread* jt = (JavaThread*) THREAD; + ResourceMark rm(THREAD); + + Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(lookup)); + // Lookup class must be a non-null instance + if (k == NULL) { + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Lookup class is null"); + } + assert(k->is_instance_klass(), "Lookup class must be an instance klass"); + + jboolean is_nestmate = (flags & NESTMATE) == NESTMATE; + jboolean is_nonfindable = (flags & NONFINDABLE_CLASS) == NONFINDABLE_CLASS; + jboolean is_weak = (flags & WEAK_CLASS) == WEAK_CLASS; + jboolean vm_annotations = (flags & ACCESS_VM_ANNOTATIONS) == ACCESS_VM_ANNOTATIONS; + + InstanceKlass* host_class = NULL; + if (is_nestmate) { + // we need to find the true nest-host of the lookup class, + // so any exceptions in nest validation must be thrown + Symbol* icce = vmSymbols::java_lang_IncompatibleClassChangeError(); + host_class = InstanceKlass::cast(k)->nest_host(icce, CHECK_NULL); + } + + // classData (constant pool patching replacement) is only applicable for nonfindable classes + if (classData != NULL && !is_nonfindable) { + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "classData is only applicable for nonfindable classes"); + } + + // vm_annotations only allowed for nonfindable classes + if (vm_annotations && !is_nonfindable) { + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "vm annotations only allowed for weak nonfindable classes"); + } + + if (log_is_enabled(Info, class, nestmates)) { + log_info(class, nestmates)("LookupDefineClass: %s - %s%s, %s, %s, %s", + name, + is_nestmate ? "with dynamic nest-host " : "non-nestmate", + is_nestmate ? host_class->external_name() : "", + is_nonfindable ? "non-findable" : "findable", + is_weak ? "weak" : "strong", + vm_annotations ? "with vm annotations" : "without vm annotation"); + } + + // Since exceptions can be thrown, class initialization can take place + // if name is NULL no check for class name in .class stream has to be made. + TempNewSymbol class_name = NULL; + if (name != NULL) { + const int str_len = (int)strlen(name); + if (str_len > Symbol::max_length()) { + // It's impossible to create this class; the name cannot fit + // into the constant pool. + Exceptions::fthrow(THREAD_AND_LOCATION, + vmSymbols::java_lang_NoClassDefFoundError(), + "Class name exceeds maximum length of %d: %s", + Symbol::max_length(), + name); + return 0; + } + class_name = SymbolTable::new_symbol(name, str_len, CHECK_NULL); + } + + Handle class_loader (THREAD, JNIHandles::resolve(loader)); + Handle protection_domain (THREAD, JNIHandles::resolve(pd)); + const char* source = is_nestmate ? host_class->external_name() : "__JVM_LookupDefineClass__"; + ClassFileStream st((u1*)buf, len, source, ClassFileStream::verify); + + if (!is_nonfindable) { + k = SystemDictionary::resolve_from_stream(class_name, + class_loader, + protection_domain, + &st, + host_class, + CHECK_NULL); + + if (log_is_enabled(Debug, class, resolve) && k != NULL) { + trace_class_resolution(k); + } + } else { //nonfindable + Handle classData_h(THREAD, JNIHandles::resolve(classData)); + k = SystemDictionary::parse_stream(class_name, + class_loader, + protection_domain, + &st, + NULL, // unsafe_anonymous_host + NULL, // cp_patches + is_nonfindable, + is_weak, + vm_annotations, + host_class, + classData_h, + CHECK_NULL); + if (k == NULL) { + THROW_MSG_0(vmSymbols::java_lang_Error(), "Failure to define a nonfindable class"); + } + + // The nonfindable class loader data has been artificially been kept alive to + // this point. The mirror and any instances of this class have to keep + // it alive afterwards. + InstanceKlass::cast(k)->class_loader_data()->dec_keep_alive(); + } + + if (is_nestmate && log_is_enabled(Debug, class, nestmates)) { + InstanceKlass* ik = InstanceKlass::cast(k); + ModuleEntry* module = ik->module(); + const char * module_name = module->is_named() ? module->name()->as_C_string() : UNNAMED_MODULE; + log_debug(class, nestmates)("Dynamic nestmate: %s/%s, nest_host %s, %s", + module_name, + ik->external_name(), + host_class->external_name(), + ik->is_nonfindable() ? "is non-findable" : "is findable"); + } + + return (jclass) JNIHandles::make_local(env, k->java_mirror()); + } JVM_ENTRY(jclass, JVM_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd)) JVMWrapper("JVM_DefineClass"); return jvm_define_class_common(env, name, loader, buf, len, pd, NULL, THREAD); JVM_END + /* + * Define a class with the specified lookup class. + * lookup: Lookup class + * name: the name of the class + * loader: defining class loader + * buf: class bytes + * len: length of class bytes + * pd: protection domain + * flags: properties of the class + * classData: private static pre-initialized field + */ + JVM_ENTRY(jclass, JVM_LookupDefineClass(JNIEnv *env, jclass lookup, const char *name, jobject loader, + const jbyte *buf, jsize len, jobject pd, int flags, jobject classData)) + JVMWrapper("JVM_LookupDefineClass"); + + if (lookup == NULL) { + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Lookup class is null"); + } + + assert(buf != NULL, "buf must not be NULL"); + + return jvm_lookup_define_class(env, lookup, name, loader, buf, len, pd, flags, classData, THREAD); + JVM_END JVM_ENTRY(jclass, JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd, const char *source)) JVMWrapper("JVM_DefineClassWithSource"); return jvm_define_class_common(env, name, loader, buf, len, pd, source, THREAD);
*** 1388,1398 **** bool inner_is_member = false; Klass* outer_klass = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass)) )->compute_enclosing_class(&inner_is_member, CHECK_NULL); if (outer_klass == NULL) return NULL; // already a top-level class ! if (!inner_is_member) return NULL; // an anonymous class (inside a method) return (jclass) JNIHandles::make_local(env, outer_klass->java_mirror()); } JVM_END JVM_ENTRY(jstring, JVM_GetSimpleBinaryName(JNIEnv *env, jclass cls)) --- 1545,1555 ---- bool inner_is_member = false; Klass* outer_klass = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass)) )->compute_enclosing_class(&inner_is_member, CHECK_NULL); if (outer_klass == NULL) return NULL; // already a top-level class ! if (!inner_is_member) return NULL; // a nonfindable or unsafe anonymous class (inside a method) return (jclass) JNIHandles::make_local(env, outer_klass->java_mirror()); } JVM_END JVM_ENTRY(jstring, JVM_GetSimpleBinaryName(JNIEnv *env, jclass cls))
*** 1833,1843 **** // k's nest host is legal but it isn't our host so // throw ICCE ResourceMark rm(THREAD); Exceptions::fthrow(THREAD_AND_LOCATION, icce, ! "Nest member %s in %s declares a different nest host of %s", k->external_name(), host->external_name(), nest_host_k->external_name() ); return NULL; --- 1990,2001 ---- // k's nest host is legal but it isn't our host so // throw ICCE ResourceMark rm(THREAD); Exceptions::fthrow(THREAD_AND_LOCATION, icce, ! "%s.getNestMembers: Nest member %s in %s declares a different nest host of %s", ! c->external_name(), k->external_name(), host->external_name(), nest_host_k->external_name() ); return NULL;
< prev index next >