8264538: Rename SystemDictionary::parse_stream

Reviewed-by: lfoltan, hseigel
This commit is contained in:
Coleen Phillimore 2021-04-01 14:55:11 +00:00
parent 80681b5470
commit 1dc75e9ef5
7 changed files with 113 additions and 105 deletions

@ -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;
}