src/share/vm/classfile/systemDictionary.cpp
Print this page
@@ -138,28 +138,10 @@
if (class_loader() == NULL) return ClassLoaderData::the_null_class_loader_data();
return ClassLoaderDataGraph::find_or_create(class_loader, THREAD);
}
// ----------------------------------------------------------------------------
-// debugging
-
-#ifdef ASSERT
-
-// return true if class_name contains no '.' (internal format is '/')
-bool SystemDictionary::is_internal_format(Symbol* class_name) {
- if (class_name != NULL) {
- ResourceMark rm;
- char* name = class_name->as_C_string();
- return strchr(name, '.') == NULL;
- } else {
- return true;
- }
-}
-
-#endif
-
-// ----------------------------------------------------------------------------
// Parallel class loading check
bool SystemDictionary::is_parallelCapable(Handle class_loader) {
if (UnsyncloadClass || class_loader.is_null()) return true;
if (AlwaysLockClassLoader) return false;
@@ -349,10 +331,12 @@
if (k) {
return k;
}
}
#endif // INCLUDE_CDS
+ // leave PENDING_EXCEPTION handling in this code to ensure we do the placeholder cleanup (find_and_remove)
+ // and do not throw exceptions while holding locks
// Double-check, if child class is already loaded, just return super-class,interface
// Don't add a placedholder if already loaded, i.e. already in system dictionary
// Make sure there's a placeholder for the *child* before resolving.
// Used as a claim that this thread is currently loading superclass/classloader
@@ -653,10 +637,12 @@
event.commit();
}
#endif // INCLUDE_TRACE
}
+// leave PENDING_EXCEPTION handling in this code to ensure we do the placeholder cleanup (find_and_remove)
+// and do not throw exceptions while holding locks
Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
Handle class_loader,
Handle protection_domain,
TRAPS) {
assert(name != NULL && !FieldType::is_array(name) &&
@@ -1013,13 +999,39 @@
k = find(class_name, class_loader, protection_domain, THREAD);
}
return k;
}
+// Only boot and platform class loaders can define classes in "java/" packages.
+void SystemDictionary::check_prohibited_package(Symbol* class_name,
+ Handle class_loader,
+ TRAPS) {
+ const char* javapkg = "java/";
+ ResourceMark rm(THREAD);
+ if (!class_loader.is_null() &&
+ !SystemDictionary::is_platform_class_loader(class_loader) &&
+ class_name != NULL &&
+ strncmp(class_name->as_C_string(), javapkg, strlen(javapkg)) == 0) {
+ TempNewSymbol pkg_name = InstanceKlass::package_from_name(class_name, CHECK);
+ assert(pkg_name != NULL, "Error in parsing package name starting with 'java/'");
+ char* name = pkg_name->as_C_string();
+ const char* class_loader_name = loader_name(class_loader());
+ StringUtils::replace_no_expand(name, "/", ".");
+ const char* msg_text1 = "Class loader (instance of): ";
+ const char* msg_text2 = " tried to load prohibited package name: ";
+ size_t len = strlen(msg_text1) + strlen(class_loader_name) + strlen(msg_text2) + strlen(name) + 1;
+ char* message = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, len);
+ jio_snprintf(message, len, "%s%s%s%s", msg_text1, class_loader_name, msg_text2, name);
+ THROW_MSG(vmSymbols::java_lang_SecurityException(), message);
+ }
+ return;
+}
+
// Note: this method is much like resolve_from_stream, but
-// updates no supplemental data structures.
-// TODO consolidate the two methods with a helper routine?
+// does not publish the classes via the SystemDictionary.
+// Handles unsafe_DefineAnonymousClass and redefineclasses
+// redefinedclasses do not add to the class hierarchy
Klass* SystemDictionary::parse_stream(Symbol* class_name,
Handle class_loader,
Handle protection_domain,
ClassFileStream* st,
const Klass* host_klass,
@@ -1052,12 +1064,12 @@
class_name,
loader_data,
protection_domain,
host_klass,
cp_patches,
- NULL, // parsed_name
- THREAD);
+ CHECK_NULL);
+
if (host_klass != NULL && k.not_null()) {
// If it's anonymous, initialize it now, since nobody else will.
{
@@ -1092,10 +1104,11 @@
"cp_patches only found with host_klass");
return k();
}
+
// Add a klass to the system from a stream (called by jni_DefineClass and
// JVM_DefineClass).
// Note: class_name can be NULL. In that case we do not know the name of
// the class until we have parsed the stream.
@@ -1124,12 +1137,10 @@
// Parse the 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.
//
- // Note: "parsed_name" is updated.
- TempNewSymbol parsed_name = NULL;
instanceKlassHandle k;
#if INCLUDE_CDS
k = SystemDictionaryShared::lookup_from_stream(class_name,
@@ -1137,80 +1148,42 @@
protection_domain,
st,
CHECK_NULL);
#endif
- if (k.not_null()) {
- parsed_name = k->name();
- } else {
+ if (k.is_null()) {
if (st->buffer() == NULL) {
return NULL;
}
k = KlassFactory::create_from_stream(st,
class_name,
loader_data,
protection_domain,
NULL, // host_klass
NULL, // cp_patches
- &parsed_name,
- THREAD);
- }
-
- const char* pkg = "java/";
- if (!HAS_PENDING_EXCEPTION &&
- !class_loader.is_null() &&
- !SystemDictionary::is_platform_class_loader(class_loader) &&
- parsed_name != NULL &&
- !strncmp((const char*)parsed_name->bytes(), pkg, strlen(pkg))) {
- // It is illegal to define classes in the "java." package from
- // JVM_DefineClass or jni_DefineClass unless you're the bootclassloader
- ResourceMark rm(THREAD);
- TempNewSymbol pkg_name = InstanceKlass::package_from_name(parsed_name, CHECK_NULL);
- assert(pkg_name != NULL, "Error in parsing package name starting with 'java/'");
- char* name = pkg_name->as_C_string();
- StringUtils::replace_no_expand(name, "/", ".");
- const char* msg_text = "Prohibited package name: ";
- size_t len = strlen(msg_text) + strlen(name) + 1;
- char* message = NEW_RESOURCE_ARRAY(char, len);
- jio_snprintf(message, len, "%s%s", msg_text, name);
- Exceptions::_throw_msg(THREAD_AND_LOCATION,
- vmSymbols::java_lang_SecurityException(), message);
+ CHECK_NULL);
}
- if (!HAS_PENDING_EXCEPTION) {
- assert(parsed_name != NULL, "Sanity");
- assert(class_name == NULL || class_name == parsed_name, "name mismatch");
- // Verification prevents us from creating names with dots in them, this
- // asserts that that's the case.
- assert(is_internal_format(parsed_name),
- "external class name format used internally");
+ assert(k.not_null(), "no klass created");
+ Symbol* h_name = k->name();
+ assert(class_name == NULL || class_name == h_name, "name mismatch");
// Add class just loaded
// If a class loader supports parallel classloading handle parallel define requests
// find_or_define_instance_class may return a different InstanceKlass
if (is_parallelCapable(class_loader)) {
- k = find_or_define_instance_class(class_name, class_loader, k, THREAD);
+ k = find_or_define_instance_class(h_name, class_loader, k, CHECK_NULL);
} else {
- define_instance_class(k, THREAD);
- }
+ define_instance_class(k, CHECK_NULL);
}
// Make sure we have an entry in the SystemDictionary on success
debug_only( {
- if (!HAS_PENDING_EXCEPTION) {
- assert(parsed_name != NULL, "parsed_name is still null?");
- Symbol* h_name = k->name();
- ClassLoaderData *defining_loader_data = k->class_loader_data();
-
MutexLocker mu(SystemDictionary_lock, THREAD);
- Klass* check = find_class(parsed_name, loader_data);
+ Klass* check = find_class(h_name, k->class_loader_data());
assert(check == k(), "should be present in the dictionary");
-
- Klass* check2 = find_class(h_name, defining_loader_data);
- assert(check == check2, "name inconsistancy in SystemDictionary");
- }
} );
return k();
}
@@ -1398,10 +1371,12 @@
ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(class_loader());
{
Handle lockObject = compute_loader_lock_object(class_loader, THREAD);
check_loader_lock_contention(lockObject, THREAD);
ObjectLocker ol(lockObject, THREAD, true);
+ // prohibited package check assumes all classes loaded from archive call
+ // restore_unshareable_info which calls ik->set_package()
ik->restore_unshareable_info(loader_data, protection_domain, CHECK_(nh));
}
if (log_is_enabled(Info, class, load)) {
ik()->print_loading_log(LogLevel::Info, loader_data, NULL, NULL);
@@ -1418,10 +1393,11 @@
int path_index = ik->shared_classpath_index();
ResourceMark rm;
ClassLoader::add_package(ik->name()->as_C_string(), path_index, THREAD);
}
+
if (DumpLoadedClassList != NULL && classlist_file->is_open()) {
// Only dump the classes that can be stored into CDS archive
if (SystemDictionaryShared::is_sharing_possible(loader_data)) {
ResourceMark rm(THREAD);
classlist_file->print_cr("%s", ik->name()->as_C_string());
@@ -1684,10 +1660,12 @@
// False is the requested default.
// For better performance, the class loaders should synchronize
// findClass(), i.e. FindLoadedClass/DefineClassIfAbsent or they
// potentially waste time reading and parsing the bytestream.
// Note: VM callers should ensure consistency of k/class_name,class_loader
+// leave PENDING_EXCEPTION handling in this code to ensure we do the placeholder cleanup (find_and_remove)
+// and do not throw exceptions while holding locks
instanceKlassHandle SystemDictionary::find_or_define_instance_class(Symbol* class_name, Handle class_loader, instanceKlassHandle k, TRAPS) {
instanceKlassHandle nh = instanceKlassHandle(); // null Handle
Symbol* name_h = k->name(); // passed in class_name may be null
ClassLoaderData* loader_data = class_loader_data(class_loader);