8264538: Rename SystemDictionary::parse_stream
Reviewed-by: lfoltan, hseigel
This commit is contained in:
parent
80681b5470
commit
1dc75e9ef5
src/hotspot/share
@ -879,15 +879,15 @@ Klass* SystemDictionary::find_instance_or_array_klass(Symbol* class_name,
|
||||
return k;
|
||||
}
|
||||
|
||||
// Note: this method is much like resolve_from_stream, but
|
||||
// does not publish the classes via the SystemDictionary.
|
||||
// Handles Lookup.defineClass hidden, unsafe_DefineAnonymousClass
|
||||
// and redefineclasses. RedefinedClasses do not add to the class hierarchy.
|
||||
InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name,
|
||||
Handle class_loader,
|
||||
ClassFileStream* st,
|
||||
const ClassLoadInfo& cl_info,
|
||||
TRAPS) {
|
||||
// Note: this method is much like resolve_class_from_stream, but
|
||||
// does not publish the classes in the SystemDictionary.
|
||||
// Handles Lookup.defineClass hidden and unsafe_DefineAnonymousClass.
|
||||
InstanceKlass* SystemDictionary::resolve_hidden_class_from_stream(
|
||||
ClassFileStream* st,
|
||||
Symbol* class_name,
|
||||
Handle class_loader,
|
||||
const ClassLoadInfo& cl_info,
|
||||
TRAPS) {
|
||||
|
||||
EventClassLoad class_load_start_event;
|
||||
ClassLoaderData* loader_data;
|
||||
@ -898,23 +898,16 @@ InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name,
|
||||
// - for hidden classes that are not strong: create a new CLD that has a class holder and
|
||||
// whose loader is the Lookup class's loader.
|
||||
// - for hidden class: add the class to the Lookup class's loader's CLD.
|
||||
if (is_unsafe_anon_class || cl_info.is_hidden()) {
|
||||
guarantee(!is_unsafe_anon_class || cl_info.unsafe_anonymous_host()->class_loader() == class_loader(),
|
||||
assert (is_unsafe_anon_class || cl_info.is_hidden(), "only used for hidden classes");
|
||||
guarantee(!is_unsafe_anon_class || cl_info.unsafe_anonymous_host()->class_loader() == class_loader(),
|
||||
"should be NULL or the same");
|
||||
bool create_mirror_cld = is_unsafe_anon_class || !cl_info.is_strong_hidden();
|
||||
loader_data = register_loader(class_loader, create_mirror_cld);
|
||||
} else {
|
||||
loader_data = ClassLoaderData::class_loader_data(class_loader());
|
||||
}
|
||||
bool create_mirror_cld = is_unsafe_anon_class || !cl_info.is_strong_hidden();
|
||||
loader_data = register_loader(class_loader, create_mirror_cld);
|
||||
|
||||
assert(st != NULL, "invariant");
|
||||
assert(st->need_verify(), "invariant");
|
||||
|
||||
// Parse stream and create a klass.
|
||||
// Note that we do this even though this klass might
|
||||
// already be present in the SystemDictionary, otherwise we would not
|
||||
// throw potential ClassFormatErrors.
|
||||
|
||||
InstanceKlass* k = KlassFactory::create_from_stream(st,
|
||||
class_name,
|
||||
loader_data,
|
||||
@ -922,40 +915,39 @@ InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name,
|
||||
CHECK_NULL);
|
||||
assert(k != NULL, "no klass created");
|
||||
|
||||
if (cl_info.is_hidden() || is_unsafe_anon_class) {
|
||||
// Hidden classes that are not strong and unsafe anonymous classes must update
|
||||
// ClassLoaderData holder so that they can be unloaded when the mirror is no
|
||||
// longer referenced.
|
||||
if (!cl_info.is_strong_hidden() || is_unsafe_anon_class) {
|
||||
k->class_loader_data()->initialize_holder(Handle(THREAD, k->java_mirror()));
|
||||
}
|
||||
|
||||
{
|
||||
MutexLocker mu_r(THREAD, Compile_lock);
|
||||
// Add to class hierarchy, and do possible deoptimizations.
|
||||
add_to_hierarchy(k);
|
||||
// But, do not add to dictionary.
|
||||
}
|
||||
|
||||
// Rewrite and patch constant pool here.
|
||||
k->link_class(CHECK_NULL);
|
||||
if (cl_info.cp_patches() != NULL) {
|
||||
k->constants()->patch_resolved_references(cl_info.cp_patches());
|
||||
}
|
||||
|
||||
// If it's anonymous, initialize it now, since nobody else will.
|
||||
if (is_unsafe_anon_class) {
|
||||
k->eager_initialize(CHECK_NULL);
|
||||
}
|
||||
|
||||
// notify jvmti
|
||||
if (JvmtiExport::should_post_class_load()) {
|
||||
JvmtiExport::post_class_load(THREAD->as_Java_thread(), k);
|
||||
}
|
||||
if (class_load_start_event.should_commit()) {
|
||||
post_class_load_event(&class_load_start_event, k, loader_data);
|
||||
}
|
||||
// Hidden classes that are not strong and unsafe anonymous classes must update
|
||||
// ClassLoaderData holder so that they can be unloaded when the mirror is no
|
||||
// longer referenced.
|
||||
if (!cl_info.is_strong_hidden() || is_unsafe_anon_class) {
|
||||
k->class_loader_data()->initialize_holder(Handle(THREAD, k->java_mirror()));
|
||||
}
|
||||
|
||||
{
|
||||
MutexLocker mu_r(THREAD, Compile_lock);
|
||||
// Add to class hierarchy, and do possible deoptimizations.
|
||||
add_to_hierarchy(k);
|
||||
// But, do not add to dictionary.
|
||||
}
|
||||
|
||||
// Rewrite and patch constant pool here.
|
||||
k->link_class(CHECK_NULL);
|
||||
if (cl_info.cp_patches() != NULL) {
|
||||
k->constants()->patch_resolved_references(cl_info.cp_patches());
|
||||
}
|
||||
|
||||
// If it's anonymous, initialize it now, since nobody else will.
|
||||
if (is_unsafe_anon_class) {
|
||||
k->eager_initialize(CHECK_NULL);
|
||||
}
|
||||
|
||||
// notify jvmti
|
||||
if (JvmtiExport::should_post_class_load()) {
|
||||
JvmtiExport::post_class_load(THREAD->as_Java_thread(), k);
|
||||
}
|
||||
if (class_load_start_event.should_commit()) {
|
||||
post_class_load_event(&class_load_start_event, k, loader_data);
|
||||
}
|
||||
|
||||
assert(is_unsafe_anon_class || NULL == cl_info.cp_patches(),
|
||||
"cp_patches only found with unsafe_anonymous_host");
|
||||
|
||||
@ -968,10 +960,11 @@ InstanceKlass* SystemDictionary::parse_stream(Symbol* class_name,
|
||||
// the class until we have parsed the stream.
|
||||
// This function either returns an InstanceKlass or throws an exception. It does
|
||||
// not return NULL without a pending exception.
|
||||
InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name,
|
||||
Handle class_loader,
|
||||
Handle protection_domain,
|
||||
InstanceKlass* SystemDictionary::resolve_class_from_stream(
|
||||
ClassFileStream* st,
|
||||
Symbol* class_name,
|
||||
Handle class_loader,
|
||||
const ClassLoadInfo& cl_info,
|
||||
TRAPS) {
|
||||
|
||||
HandleMark hm(THREAD);
|
||||
@ -993,14 +986,13 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name,
|
||||
if (!DumpSharedSpaces) {
|
||||
k = SystemDictionaryShared::lookup_from_stream(class_name,
|
||||
class_loader,
|
||||
protection_domain,
|
||||
cl_info.protection_domain(),
|
||||
st,
|
||||
CHECK_NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (k == NULL) {
|
||||
ClassLoadInfo cl_info(protection_domain);
|
||||
k = KlassFactory::create_from_stream(st, class_name, loader_data, cl_info, CHECK_NULL);
|
||||
}
|
||||
|
||||
@ -1031,6 +1023,20 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name,
|
||||
return k;
|
||||
}
|
||||
|
||||
InstanceKlass* SystemDictionary::resolve_from_stream(ClassFileStream* st,
|
||||
Symbol* class_name,
|
||||
Handle class_loader,
|
||||
const ClassLoadInfo& cl_info,
|
||||
TRAPS) {
|
||||
bool is_unsafe_anon_class = cl_info.unsafe_anonymous_host() != NULL;
|
||||
if (cl_info.is_hidden() || is_unsafe_anon_class) {
|
||||
return resolve_hidden_class_from_stream(st, class_name, class_loader, cl_info, CHECK_NULL);
|
||||
} else {
|
||||
return resolve_class_from_stream(st, class_name, class_loader, cl_info, CHECK_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if INCLUDE_CDS
|
||||
// Load a class for boot loader from the shared spaces. This also
|
||||
// forces the super class and all interfaces to be loaded.
|
||||
|
@ -121,21 +121,29 @@ class SystemDictionary : AllStatic {
|
||||
Handle protection_domain,
|
||||
bool is_superclass,
|
||||
TRAPS);
|
||||
private:
|
||||
// Parse the stream to create an unsafe anonymous or hidden class.
|
||||
// Used by Unsafe_DefineAnonymousClass and jvm_lookup_define_class.
|
||||
static InstanceKlass* resolve_hidden_class_from_stream(ClassFileStream* st,
|
||||
Symbol* class_name,
|
||||
Handle class_loader,
|
||||
const ClassLoadInfo& cl_info,
|
||||
TRAPS);
|
||||
|
||||
// Parse new stream. This won't update the dictionary or class
|
||||
// hierarchy, simply parse the stream. Used by JVMTI RedefineClasses
|
||||
// and by Unsafe_DefineAnonymousClass and jvm_lookup_define_class.
|
||||
static InstanceKlass* parse_stream(Symbol* class_name,
|
||||
Handle class_loader,
|
||||
ClassFileStream* st,
|
||||
const ClassLoadInfo& cl_info,
|
||||
TRAPS);
|
||||
// Resolve a class from stream (called by jni_DefineClass and JVM_DefineClass)
|
||||
// This class is added to the SystemDictionary.
|
||||
static InstanceKlass* resolve_class_from_stream(ClassFileStream* st,
|
||||
Symbol* class_name,
|
||||
Handle class_loader,
|
||||
const ClassLoadInfo& cl_info,
|
||||
TRAPS);
|
||||
|
||||
// Resolve from stream (called by jni_DefineClass and JVM_DefineClass)
|
||||
static InstanceKlass* resolve_from_stream(Symbol* class_name,
|
||||
public:
|
||||
// Resolve either a hidden or normal class from a stream of bytes, based on ClassLoadInfo
|
||||
static InstanceKlass* resolve_from_stream(ClassFileStream* st,
|
||||
Symbol* class_name,
|
||||
Handle class_loader,
|
||||
Handle protection_domain,
|
||||
ClassFileStream* st,
|
||||
const ClassLoadInfo& cl_info,
|
||||
TRAPS);
|
||||
|
||||
// Lookup an already loaded class. If not found NULL is returned.
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include "ci/ciReplay.hpp"
|
||||
#include "classfile/altHashing.hpp"
|
||||
#include "classfile/classFileStream.hpp"
|
||||
#include "classfile/classLoader.hpp"
|
||||
#include "classfile/classLoadInfo.hpp"
|
||||
#include "classfile/javaClasses.hpp"
|
||||
#include "classfile/javaClasses.inline.hpp"
|
||||
#include "classfile/javaThreadStatus.hpp"
|
||||
@ -283,10 +285,11 @@ JNI_ENTRY(jclass, jni_DefineClass(JNIEnv *env, const char *name, jobject loaderR
|
||||
ResourceMark rm(THREAD);
|
||||
ClassFileStream st((u1*)buf, bufLen, NULL, ClassFileStream::verify);
|
||||
Handle class_loader (THREAD, JNIHandles::resolve(loaderRef));
|
||||
Klass* k = SystemDictionary::resolve_from_stream(class_name,
|
||||
Handle protection_domain;
|
||||
ClassLoadInfo cl_info(protection_domain);
|
||||
Klass* k = SystemDictionary::resolve_from_stream(&st, class_name,
|
||||
class_loader,
|
||||
Handle(),
|
||||
&st,
|
||||
cl_info,
|
||||
CHECK_NULL);
|
||||
|
||||
if (log_is_enabled(Debug, class, resolve)) {
|
||||
|
@ -860,10 +860,10 @@ static jclass jvm_define_class_common(const char *name,
|
||||
ClassFileStream st((u1*)buf, len, source, ClassFileStream::verify);
|
||||
Handle class_loader (THREAD, JNIHandles::resolve(loader));
|
||||
Handle protection_domain (THREAD, JNIHandles::resolve(pd));
|
||||
Klass* k = SystemDictionary::resolve_from_stream(class_name,
|
||||
ClassLoadInfo cl_info(protection_domain);
|
||||
Klass* k = SystemDictionary::resolve_from_stream(&st, class_name,
|
||||
class_loader,
|
||||
protection_domain,
|
||||
&st,
|
||||
cl_info,
|
||||
CHECK_NULL);
|
||||
|
||||
if (log_is_enabled(Debug, class, resolve)) {
|
||||
@ -947,10 +947,10 @@ static jclass jvm_lookup_define_class(jclass lookup, const char *name,
|
||||
|
||||
InstanceKlass* ik = NULL;
|
||||
if (!is_hidden) {
|
||||
ik = SystemDictionary::resolve_from_stream(class_name,
|
||||
ClassLoadInfo cl_info(protection_domain);
|
||||
ik = SystemDictionary::resolve_from_stream(&st, class_name,
|
||||
class_loader,
|
||||
protection_domain,
|
||||
&st,
|
||||
cl_info,
|
||||
CHECK_NULL);
|
||||
|
||||
if (log_is_enabled(Debug, class, resolve)) {
|
||||
@ -966,11 +966,10 @@ static jclass jvm_lookup_define_class(jclass lookup, const char *name,
|
||||
is_hidden,
|
||||
is_strong,
|
||||
vm_annotations);
|
||||
ik = SystemDictionary::parse_stream(class_name,
|
||||
class_loader,
|
||||
&st,
|
||||
cl_info,
|
||||
CHECK_NULL);
|
||||
ik = SystemDictionary::resolve_from_stream(&st, class_name,
|
||||
class_loader,
|
||||
cl_info,
|
||||
CHECK_NULL);
|
||||
|
||||
// The hidden class loader data has been artificially been kept alive to
|
||||
// this point. The mirror and any instances of this class have to keep
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include "classfile/javaClasses.inline.hpp"
|
||||
#include "classfile/metadataOnStackMark.hpp"
|
||||
#include "classfile/symbolTable.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "classfile/klassFactory.hpp"
|
||||
#include "classfile/verifier.hpp"
|
||||
#include "classfile/vmClasses.hpp"
|
||||
#include "classfile/vmSymbols.hpp"
|
||||
@ -1367,7 +1367,6 @@ jvmtiError VM_RedefineClasses::load_new_class_versions() {
|
||||
// constant pools
|
||||
HandleMark hm(current);
|
||||
InstanceKlass* the_class = get_ik(_class_defs[i].klass);
|
||||
Symbol* the_class_sym = the_class->name();
|
||||
|
||||
log_debug(redefine, class, load)
|
||||
("loading name=%s kind=%d (avail_mem=" UINT64_FORMAT "K)",
|
||||
@ -1378,9 +1377,6 @@ jvmtiError VM_RedefineClasses::load_new_class_versions() {
|
||||
"__VM_RedefineClasses__",
|
||||
ClassFileStream::verify);
|
||||
|
||||
// Parse the stream.
|
||||
Handle the_class_loader(current, the_class->class_loader());
|
||||
Handle protection_domain(current, the_class->protection_domain());
|
||||
// Set redefined class handle in JvmtiThreadState class.
|
||||
// This redefined class is sent to agent event handler for class file
|
||||
// load hook event.
|
||||
@ -1388,13 +1384,16 @@ jvmtiError VM_RedefineClasses::load_new_class_versions() {
|
||||
|
||||
Thread* THREAD = current; // for exception processing
|
||||
ExceptionMark em(THREAD);
|
||||
Handle protection_domain(THREAD, the_class->protection_domain());
|
||||
ClassLoadInfo cl_info(protection_domain);
|
||||
InstanceKlass* scratch_class = SystemDictionary::parse_stream(
|
||||
the_class_sym,
|
||||
the_class_loader,
|
||||
&st,
|
||||
// Parse and create a class from the bytes, but this class isn't added
|
||||
// to the dictionary, so do not call resolve_from_stream.
|
||||
InstanceKlass* scratch_class = KlassFactory::create_from_stream(&st,
|
||||
the_class->name(),
|
||||
the_class->class_loader_data(),
|
||||
cl_info,
|
||||
THREAD);
|
||||
|
||||
// Clear class_being_redefined just to be sure.
|
||||
state->clear_class_being_redefined();
|
||||
|
||||
@ -1407,7 +1406,7 @@ jvmtiError VM_RedefineClasses::load_new_class_versions() {
|
||||
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
Symbol* ex_name = PENDING_EXCEPTION->klass()->name();
|
||||
log_info(redefine, class, load, exceptions)("parse_stream exception: '%s'", ex_name->as_C_string());
|
||||
log_info(redefine, class, load, exceptions)("create_from_stream exception: '%s'", ex_name->as_C_string());
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
|
||||
if (ex_name == vmSymbols::java_lang_UnsupportedClassVersionError()) {
|
||||
|
@ -302,12 +302,6 @@
|
||||
//
|
||||
// - How do we serialize the RedefineClasses() API without deadlocking?
|
||||
//
|
||||
// - SystemDictionary::parse_stream() was called with a NULL protection
|
||||
// domain since the initial version. This has been changed to pass
|
||||
// the_class->protection_domain(). This change has been tested with
|
||||
// all NSK tests and nothing broke, but what will adding it now break
|
||||
// in ways that we don't test?
|
||||
//
|
||||
// - GenerateOopMap::rewrite_load_or_store() has a comment in its
|
||||
// (indirect) use of the Relocator class that the max instruction
|
||||
// size is 4 bytes. goto_w and jsr_w are 5 bytes and wide/iinc is
|
||||
|
@ -865,11 +865,10 @@ Unsafe_DefineAnonymousClass_impl(JNIEnv *env,
|
||||
false, // is_strong_hidden
|
||||
true); // can_access_vm_annotations
|
||||
|
||||
InstanceKlass* anonk = SystemDictionary::parse_stream(no_class_name,
|
||||
host_loader,
|
||||
&st,
|
||||
cl_info,
|
||||
CHECK_NULL);
|
||||
InstanceKlass* anonk = SystemDictionary::resolve_from_stream(&st, no_class_name,
|
||||
host_loader,
|
||||
cl_info,
|
||||
CHECK_NULL);
|
||||
assert(anonk != NULL, "no klass created");
|
||||
return anonk;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user