- deleted: 8046294-Generate-the-4-byte-timestamp-randomly.patch - deleted: 8148754-C2-loop-unrolling-fails-due-to-unexpected-gr.patch - deleted: 8151788.patch - deleted: 8161072.patch - deleted: 8171537.patch - deleted: 8203481-Incorrect-constraint-for-unextended_sp-in-frame-safe_for_sender.patch - deleted: 8203699-java-lang-invoke-SpecialInte.patch - modified: Extend-CDS-to-support-app-class-metadata-sharing.patch - deleted: Test-SSLSocketSSLEngineTemplate.java-intermittent-fa.patch - modified: fast-serializer-jdk8.patch - deleted: fix-CompactibleFreeListSpace-block_size-crash.patch - deleted: fix-incorrect-klass-field-in-oop-with-weak-memory-model.patch
748 lines
34 KiB
Diff
748 lines
34 KiB
Diff
diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp
|
|
index 6d62380..58d9116 100644
|
|
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp
|
|
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp
|
|
@@ -3939,7 +3939,8 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
|
#if INCLUDE_CDS
|
|
if (DumpLoadedClassList != NULL && cfs->source() != NULL && classlist_file->is_open()) {
|
|
// Only dump the classes that can be stored into CDS archive
|
|
- if (SystemDictionaryShared::is_sharing_possible(loader_data)) {
|
|
+ // unless AppCDS is enabled
|
|
+ if (_host_klass == NULL && SystemDictionaryShared::is_sharing_possible(loader_data)) {
|
|
if (name != NULL) {
|
|
ResourceMark rm(THREAD);
|
|
classlist_file->print_cr("%s", name->as_C_string());
|
|
diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp
|
|
index b9f46df..c7c0f53 100644
|
|
--- a/hotspot/src/share/vm/classfile/classLoader.cpp
|
|
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp
|
|
@@ -1203,8 +1203,8 @@ instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) {
|
|
|
|
h = context.record_result(classpath_index, e, result, THREAD);
|
|
} else {
|
|
- if (DumpSharedSpaces) {
|
|
- tty->print_cr("Preload Warning: Cannot find %s", class_name);
|
|
+ if (!UseAppCDS && DumpSharedSpaces) {
|
|
+ tty->print_cr("Preload Warning: Cannot find %s", class_name); // No need for AppCDS
|
|
}
|
|
}
|
|
|
|
diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp
|
|
index 5c6b094..61140d3 100644
|
|
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp
|
|
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp
|
|
@@ -175,6 +175,16 @@ bool SystemDictionary::is_ext_class_loader(Handle class_loader) {
|
|
return (class_loader->klass()->name() == vmSymbols::sun_misc_Launcher_ExtClassLoader());
|
|
}
|
|
|
|
+/**
|
|
+ * Returns true if the passed class loader is the application class loader.
|
|
+ */
|
|
+bool SystemDictionary::is_app_class_loader(Handle class_loader) {
|
|
+ if (class_loader.is_null()) {
|
|
+ return false;
|
|
+ }
|
|
+ return (class_loader->klass()->name() == vmSymbols::sun_misc_Launcher_AppClassLoader());
|
|
+}
|
|
+
|
|
// ----------------------------------------------------------------------------
|
|
// Resolving of classes
|
|
|
|
@@ -336,7 +346,8 @@ Klass* SystemDictionary::resolve_super_or_fail(Symbol* child_name,
|
|
// Bugs 4643874, 4715493
|
|
// compute_hash can have a safepoint
|
|
|
|
- ClassLoaderData* loader_data = class_loader_data(class_loader);
|
|
+ // class loader may be not registered yet, so use register_loader, which will return a valid classloaderData anyway.
|
|
+ ClassLoaderData* loader_data = register_loader(class_loader, CHECK_NULL);
|
|
unsigned int d_hash = dictionary()->compute_hash(child_name, loader_data);
|
|
int d_index = dictionary()->hash_to_index(d_hash);
|
|
unsigned int p_hash = placeholders()->compute_hash(child_name, loader_data);
|
|
@@ -526,7 +537,8 @@ instanceKlassHandle SystemDictionary::handle_parallel_super_load(
|
|
Handle protection_domain, Handle lockObject, TRAPS) {
|
|
|
|
instanceKlassHandle nh = instanceKlassHandle(); // null Handle
|
|
- ClassLoaderData* loader_data = class_loader_data(class_loader);
|
|
+ // class loader may be not registered yet, so use register_loader, which will return a valid classloaderData anyway.
|
|
+ ClassLoaderData* loader_data = register_loader(class_loader, CHECK_NULL);
|
|
unsigned int d_hash = dictionary()->compute_hash(name, loader_data);
|
|
int d_index = dictionary()->hash_to_index(d_hash);
|
|
unsigned int p_hash = placeholders()->compute_hash(name, loader_data);
|
|
@@ -1074,6 +1086,19 @@ Klass* SystemDictionary::parse_stream(Symbol* class_name,
|
|
return k();
|
|
}
|
|
|
|
+static char* convert_into_package_name(char* name) {
|
|
+ char* index = strrchr(name, '/');
|
|
+ if (index == NULL) {
|
|
+ return NULL;
|
|
+ } else {
|
|
+ *index = '\0'; // chop to just the package name
|
|
+ while ((index = strchr(name, '/')) != NULL) {
|
|
+ *index = '.'; // replace '/' with '.' in package name
|
|
+ }
|
|
+ return name;
|
|
+ }
|
|
+}
|
|
+
|
|
static bool is_prohibited_package_slow(Symbol* class_name) {
|
|
// Caller has ResourceMark
|
|
int length;
|
|
@@ -1147,12 +1172,9 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name,
|
|
// It is illegal to define classes in the "java." package from
|
|
// JVM_DefineClass or jni_DefineClass unless you're the bootclassloader
|
|
char* name = parsed_name->as_C_string();
|
|
- char* index = strrchr(name, '/');
|
|
- assert(index != NULL, "must be");
|
|
- *index = '\0'; // chop to just the package name
|
|
- while ((index = strchr(name, '/')) != NULL) {
|
|
- *index = '.'; // replace '/' with '.' in package name
|
|
- }
|
|
+ name = convert_into_package_name(name);
|
|
+ assert(name != NULL, "must be");
|
|
+
|
|
const char* fmt = "Prohibited package name: %s";
|
|
size_t len = strlen(fmt) + strlen(name);
|
|
char* message = NEW_RESOURCE_ARRAY(char, len);
|
|
@@ -1217,12 +1240,62 @@ Klass* SystemDictionary::find_shared_class(Symbol* class_name) {
|
|
|
|
instanceKlassHandle SystemDictionary::load_shared_class(
|
|
Symbol* class_name, Handle class_loader, TRAPS) {
|
|
- instanceKlassHandle ik (THREAD, find_shared_class(class_name));
|
|
- // Make sure we only return the boot class for the NULL classloader.
|
|
- if (ik.not_null() &&
|
|
- SharedClassUtil::is_shared_boot_class(ik()) && class_loader.is_null()) {
|
|
- Handle protection_domain;
|
|
- return load_shared_class(ik, class_loader, protection_domain, THREAD);
|
|
+ if (!(class_loader.is_null() || SystemDictionary::is_app_class_loader(class_loader) ||
|
|
+ SystemDictionary::is_ext_class_loader(class_loader))) {
|
|
+ return instanceKlassHandle();
|
|
+ }
|
|
+
|
|
+ instanceKlassHandle ik (THREAD, find_shared_class(class_name)); // InstanceKlass is find with null class loader.
|
|
+ if (ik.not_null()) {
|
|
+ if (!UseAppCDS) {
|
|
+ // CDS logic
|
|
+ if (SharedClassUtil::is_shared_boot_class(ik()) && class_loader.is_null()) {
|
|
+ // CDS record boot class load index.
|
|
+ Handle protection_domain;
|
|
+ return load_shared_class(ik, class_loader, protection_domain, THREAD);
|
|
+ }
|
|
+ } else {
|
|
+ // AppCDS logic. Only use null loader only to load classes that
|
|
+ // have been dumped by null loader. For non-null class loaders,
|
|
+ // either the class loader data is not initialized (but also not
|
|
+ // null) or the same class loader is used to load previously
|
|
+ // defined class
|
|
+ bool bFound = false;
|
|
+ if (class_loader.is_null()) {
|
|
+ // condition1: Bootstrap class loader loaded
|
|
+ bFound = (ik()->class_loader_data() == NULL || ik()->class_loader_data()->is_the_null_class_loader_data());
|
|
+ } else if (ik()->class_loader_data() != NULL) {
|
|
+ // condition2: App Class Loader
|
|
+ // condition3: ExtClass Loader
|
|
+ // Condition4: not fake class Loader, real one
|
|
+ bFound = ((ik->has_fake_loader_data_App() && SystemDictionary::is_app_class_loader(class_loader)) ||
|
|
+ (ik->has_fake_loader_data_Ext() && SystemDictionary::is_ext_class_loader(class_loader)) ||
|
|
+ (!ik->has_fake_loader_data() && ik()->class_loader() == class_loader()));
|
|
+ }
|
|
+ if (!bFound) {
|
|
+ return instanceKlassHandle();
|
|
+ }
|
|
+
|
|
+ // get protection domain for this class if not loaded by null class loader
|
|
+ if (class_loader.not_null()) {
|
|
+ ResourceMark rm(THREAD);
|
|
+ char* name = ik->name()->as_C_string();
|
|
+ Handle klass_name = java_lang_String::create_from_str(name, CHECK_0);
|
|
+ JavaValue result(T_OBJECT);
|
|
+
|
|
+ // ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(class_loader());
|
|
+ JavaCalls::call_virtual(&result,
|
|
+ class_loader,
|
|
+ KlassHandle(THREAD, SystemDictionary::URLClassLoader_klass()),
|
|
+ vmSymbols::getProtectionDomainInternal_name(),
|
|
+ vmSymbols::getProtectionDomainInternal_signature(),
|
|
+ klass_name,
|
|
+ THREAD);
|
|
+ return load_shared_class(ik, class_loader, Handle(THREAD, (oop) result.get_jobject()), THREAD);
|
|
+ } else {
|
|
+ return load_shared_class(ik, class_loader, Handle(), THREAD);
|
|
+ }
|
|
+ }
|
|
}
|
|
return instanceKlassHandle();
|
|
}
|
|
@@ -1298,6 +1371,7 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik,
|
|
|
|
if (DumpLoadedClassList != NULL && classlist_file->is_open()) {
|
|
// Only dump the classes that can be stored into CDS archive
|
|
+ // unless AppCDS is enabled
|
|
if (SystemDictionaryShared::is_sharing_possible(loader_data)) {
|
|
ResourceMark rm(THREAD);
|
|
classlist_file->print_cr("%s", ik->name()->as_C_string());
|
|
@@ -1308,6 +1382,32 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik,
|
|
// notify a class loaded from shared object
|
|
ClassLoadingService::notify_class_loaded(InstanceKlass::cast(ik()),
|
|
true /* shared class */);
|
|
+
|
|
+ // register package for this class, if necessary
|
|
+ if (UseAppCDS && class_loader.not_null()) {
|
|
+
|
|
+ ResourceMark rm(THREAD);
|
|
+ char* name = ik->name()->as_C_string();
|
|
+ name = convert_into_package_name(name);
|
|
+ if (name != NULL) {
|
|
+ // not a default package
|
|
+ Handle package_name = java_lang_String::create_from_str(name, CHECK_0);
|
|
+ // The digital 4 is used only once, indicating the parameter number of
|
|
+ // the method invoked in JavaCalls::call_virtual
|
|
+ JavaCallArguments args(4);
|
|
+ args.push_oop(class_loader);
|
|
+ args.push_oop(package_name);
|
|
+ args.push_oop(Handle());
|
|
+ args.push_oop(Handle());
|
|
+ JavaValue result(T_VOID);
|
|
+ JavaCalls::call_virtual(&result,
|
|
+ KlassHandle(THREAD, SystemDictionary::URLClassLoader_klass()),
|
|
+ vmSymbols::definePackageInternal_name(),
|
|
+ vmSymbols::definePackageInternal_signature(),
|
|
+ &args,
|
|
+ CHECK_0);
|
|
+ }
|
|
+ }
|
|
}
|
|
return ik;
|
|
}
|
|
@@ -2167,7 +2267,6 @@ void SystemDictionary::update_dictionary(int d_index, unsigned int d_hash,
|
|
// yet and these will be ignored.
|
|
Klass* SystemDictionary::find_constrained_instance_or_array_klass(
|
|
Symbol* class_name, Handle class_loader, TRAPS) {
|
|
-
|
|
// First see if it has been loaded directly.
|
|
// Force the protection domain to be null. (This removes protection checks.)
|
|
Handle no_protection_domain;
|
|
diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp
|
|
index 6f0b38a..cab7381 100644
|
|
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp
|
|
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp
|
|
@@ -649,6 +649,7 @@ public:
|
|
Handle class_loader,
|
|
TRAPS);
|
|
static bool is_ext_class_loader(Handle class_loader);
|
|
+ static bool is_app_class_loader(Handle class_loader);
|
|
|
|
protected:
|
|
static Klass* find_shared_class(Symbol* class_name);
|
|
diff --git a/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp b/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp
|
|
index e1adf8b..a8dbda2 100644
|
|
--- a/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp
|
|
+++ b/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp
|
|
@@ -35,13 +35,25 @@ public:
|
|
static instanceKlassHandle find_or_load_shared_class(Symbol* class_name,
|
|
Handle class_loader,
|
|
TRAPS) {
|
|
+ if (UseAppCDS) {
|
|
+ instanceKlassHandle ik = load_shared_class(class_name, class_loader, CHECK_NULL);
|
|
+ if (!ik.is_null()) {
|
|
+ instanceKlassHandle nh = instanceKlassHandle(); // null Handle
|
|
+ ik = find_or_define_instance_class(class_name, class_loader, ik, CHECK_(nh));
|
|
+ }
|
|
+ return ik;
|
|
+ }
|
|
return instanceKlassHandle();
|
|
}
|
|
static void roots_oops_do(OopClosure* blk) {}
|
|
static void oops_do(OopClosure* f) {}
|
|
+
|
|
static bool is_sharing_possible(ClassLoaderData* loader_data) {
|
|
oop class_loader = loader_data->class_loader();
|
|
- return (class_loader == NULL);
|
|
+ return (class_loader == NULL ||
|
|
+ (UseAppCDS && (SystemDictionary::is_app_class_loader(class_loader) ||
|
|
+ SystemDictionary::is_ext_class_loader(class_loader)))
|
|
+ );
|
|
}
|
|
|
|
static size_t dictionary_entry_size() {
|
|
diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp
|
|
index f72a948..6bd8dbe 100644
|
|
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp
|
|
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp
|
|
@@ -418,8 +418,8 @@
|
|
template(getFileURL_signature, "(Ljava/io/File;)Ljava/net/URL;") \
|
|
template(definePackageInternal_name, "definePackageInternal") \
|
|
template(definePackageInternal_signature, "(Ljava/lang/String;Ljava/util/jar/Manifest;Ljava/net/URL;)V") \
|
|
- template(getProtectionDomain_name, "getProtectionDomain") \
|
|
- template(getProtectionDomain_signature, "(Ljava/security/CodeSource;)Ljava/security/ProtectionDomain;") \
|
|
+ template(getProtectionDomainInternal_name, "getProtectionDomainInternal") \
|
|
+ template(getProtectionDomainInternal_signature, "(Ljava/lang/String;)Ljava/security/ProtectionDomain;") \
|
|
template(url_code_signer_array_void_signature, "(Ljava/net/URL;[Ljava/security/CodeSigner;)V") \
|
|
template(resolved_references_name, "<resolved_references>") \
|
|
template(referencequeue_null_name, "NULL") \
|
|
diff --git a/hotspot/src/share/vm/memory/filemap.cpp b/hotspot/src/share/vm/memory/filemap.cpp
|
|
index 644e3b1..0f3c076 100644
|
|
--- a/hotspot/src/share/vm/memory/filemap.cpp
|
|
+++ b/hotspot/src/share/vm/memory/filemap.cpp
|
|
@@ -344,12 +344,12 @@ bool FileMapInfo::init_from_file(int fd) {
|
|
|
|
// Read the FileMapInfo information from the file.
|
|
bool FileMapInfo::open_for_read() {
|
|
- _full_path = Arguments::GetSharedArchivePath();
|
|
+ _full_path = make_log_name(Arguments::GetSharedArchivePath(), NULL);
|
|
int fd = open(_full_path, O_RDONLY | O_BINARY, 0);
|
|
if (fd < 0) {
|
|
if (errno == ENOENT) {
|
|
// Not locating the shared archive is ok.
|
|
- fail_continue("Specified shared archive not found.");
|
|
+ fail_continue("Specified shared archive not found. archive file path:%s", _full_path);
|
|
} else {
|
|
fail_continue("Failed to open shared archive file (%s).",
|
|
strerror(errno));
|
|
@@ -366,7 +366,7 @@ bool FileMapInfo::open_for_read() {
|
|
// Write the FileMapInfo information to the file.
|
|
|
|
void FileMapInfo::open_for_write() {
|
|
- _full_path = Arguments::GetSharedArchivePath();
|
|
+ _full_path = make_log_name(Arguments::GetSharedArchivePath(), NULL);
|
|
if (PrintSharedSpaces) {
|
|
tty->print_cr("Dumping shared data to file: ");
|
|
tty->print_cr(" %s", _full_path);
|
|
diff --git a/hotspot/src/share/vm/memory/metaspaceShared.cpp b/hotspot/src/share/vm/memory/metaspaceShared.cpp
|
|
index d5826d6..f3c3c51 100644
|
|
--- a/hotspot/src/share/vm/memory/metaspaceShared.cpp
|
|
+++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp
|
|
@@ -677,14 +677,9 @@ void MetaspaceShared::link_and_cleanup_shared_classes(TRAPS) {
|
|
SystemDictionary::classes_do(check_one_shared_class);
|
|
} while (_check_classes_made_progress);
|
|
|
|
- if (IgnoreUnverifiableClassesDuringDump) {
|
|
- // This is useful when running JCK or SQE tests. You should not
|
|
- // enable this when running real apps.
|
|
- SystemDictionary::remove_classes_in_error_state();
|
|
- } else {
|
|
- tty->print_cr("Please remove the unverifiable classes from your class list and try again");
|
|
- exit(1);
|
|
- }
|
|
+ // record error message, remove error state, and continue to dump jsa file
|
|
+ tty->print_cr("Please remove the unverifiable classes from your class list and try again");
|
|
+ SystemDictionary::remove_classes_in_error_state();
|
|
}
|
|
|
|
// Copy the dependencies from C_HEAP-alloced GrowableArrays to RO-alloced
|
|
@@ -803,8 +798,12 @@ int MetaspaceShared::preload_and_dump(const char * class_list_path,
|
|
// Got a class name - load it.
|
|
TempNewSymbol class_name_symbol = SymbolTable::new_permanent_symbol(class_name, THREAD);
|
|
guarantee(!HAS_PENDING_EXCEPTION, "Exception creating a symbol.");
|
|
+
|
|
+ Handle loader = UseAppCDS ? SystemDictionary::java_system_loader() : Handle();
|
|
Klass* klass = SystemDictionary::resolve_or_null(class_name_symbol,
|
|
- THREAD);
|
|
+ loader,
|
|
+ Handle(),
|
|
+ THREAD);
|
|
CLEAR_PENDING_EXCEPTION;
|
|
if (klass != NULL) {
|
|
if (PrintSharedSpaces && Verbose && WizardMode) {
|
|
@@ -824,8 +823,8 @@ int MetaspaceShared::preload_and_dump(const char * class_list_path,
|
|
guarantee(!HAS_PENDING_EXCEPTION, "exception in link_class");
|
|
|
|
class_count++;
|
|
- } else {
|
|
- //tty->print_cr("Preload failed: %s", class_name);
|
|
+ } else if (UseAppCDS) {
|
|
+ tty->print_cr("Preload failed: %s", class_name);
|
|
}
|
|
}
|
|
fclose(file);
|
|
diff --git a/hotspot/src/share/vm/oops/arrayKlass.cpp b/hotspot/src/share/vm/oops/arrayKlass.cpp
|
|
index 2d2e44b..129bce6 100644
|
|
--- a/hotspot/src/share/vm/oops/arrayKlass.cpp
|
|
+++ b/hotspot/src/share/vm/oops/arrayKlass.cpp
|
|
@@ -195,6 +195,12 @@ void ArrayKlass::remove_unshareable_info() {
|
|
Klass::remove_unshareable_info();
|
|
// Clear the java mirror
|
|
set_component_mirror(NULL);
|
|
+
|
|
+ if (_higher_dimension != NULL) {
|
|
+ ArrayKlass *ak = ArrayKlass::cast(higher_dimension());
|
|
+ ak->remove_unshareable_info();
|
|
+ }
|
|
+ _higher_dimension = NULL;
|
|
}
|
|
|
|
void ArrayKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
|
|
diff --git a/hotspot/src/share/vm/oops/constantPool.cpp b/hotspot/src/share/vm/oops/constantPool.cpp
|
|
index 98a11fe..4502a01 100644
|
|
--- a/hotspot/src/share/vm/oops/constantPool.cpp
|
|
+++ b/hotspot/src/share/vm/oops/constantPool.cpp
|
|
@@ -180,6 +180,20 @@ void ConstantPool::restore_unshareable_info(TRAPS) {
|
|
}
|
|
|
|
void ConstantPool::remove_unshareable_info() {
|
|
+ if (UseAppCDS) {
|
|
+ if (cache() != NULL) {
|
|
+ cache()->reset();
|
|
+ }
|
|
+ for (int i = 0; i < _length; i++) {
|
|
+ if (tag_at(i).is_klass()) {
|
|
+ Klass* resolvedKlass = resolved_klass_at(i);
|
|
+ ResourceMark rm;
|
|
+ char* name = resolvedKlass->name()->as_C_string();
|
|
+ int len = strlen(name);
|
|
+ unresolved_klass_at_put(i, resolvedKlass->name());
|
|
+ }
|
|
+ }
|
|
+ }
|
|
// Resolved references are not in the shared archive.
|
|
// Save the length for restoration. It is not necessarily the same length
|
|
// as reference_map.length() if invokedynamic is saved.
|
|
diff --git a/hotspot/src/share/vm/oops/cpCache.cpp b/hotspot/src/share/vm/oops/cpCache.cpp
|
|
index cda9a4e..ebcf3d6 100644
|
|
--- a/hotspot/src/share/vm/oops/cpCache.cpp
|
|
+++ b/hotspot/src/share/vm/oops/cpCache.cpp
|
|
@@ -673,3 +673,16 @@ void ConstantPoolCache::verify_on(outputStream* st) {
|
|
// print constant pool cache entries
|
|
for (int i = 0; i < length(); i++) entry_at(i)->verify(st);
|
|
}
|
|
+
|
|
+void ConstantPoolCache::reset() {
|
|
+ for (int i = 0; i < length(); i++) {
|
|
+ ConstantPoolCacheEntry* entry = entry_at(i);
|
|
+ int cp_index = entry->constant_pool_index();
|
|
+ if (!entry->is_initial_resolved_ref_index()) {
|
|
+ // constant pool cache after initialization contains
|
|
+ // placeholders fr handling invokedynamic and invokehandle -
|
|
+ // these need to be preserved and all other entries reset
|
|
+ entry->initialize_entry(cp_index);
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/hotspot/src/share/vm/oops/cpCache.hpp b/hotspot/src/share/vm/oops/cpCache.hpp
|
|
index a4a6c3f..48f9bbd 100644
|
|
--- a/hotspot/src/share/vm/oops/cpCache.hpp
|
|
+++ b/hotspot/src/share/vm/oops/cpCache.hpp
|
|
@@ -360,7 +360,14 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
|
|
bool is_double() const { return flag_state() == dtos; }
|
|
TosState flag_state() const { assert((uint)number_of_states <= (uint)tos_state_mask+1, "");
|
|
return (TosState)((_flags >> tos_state_shift) & tos_state_mask); }
|
|
-
|
|
+ bool is_initial_resolved_ref_index() const {
|
|
+ if (_flags == 0 && _f1 == NULL && bytecode_1() == Bytecodes::_nop && bytecode_2() == Bytecodes::_nop) {
|
|
+ return true;
|
|
+ } else {
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+
|
|
// Code generation support
|
|
static WordSize size() { return in_WordSize(sizeof(ConstantPoolCacheEntry) / HeapWordSize); }
|
|
static ByteSize size_in_bytes() { return in_ByteSize(sizeof(ConstantPoolCacheEntry)); }
|
|
@@ -480,6 +487,8 @@ class ConstantPoolCache: public MetaspaceObj {
|
|
void dump_cache();
|
|
#endif // INCLUDE_JVMTI
|
|
|
|
+ void reset();
|
|
+
|
|
// Deallocate - no fields to deallocate
|
|
DEBUG_ONLY(bool on_stack() { return false; })
|
|
void deallocate_contents(ClassLoaderData* data) {}
|
|
diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp
|
|
index 6f881ac..6d67113 100644
|
|
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp
|
|
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp
|
|
@@ -2452,6 +2452,22 @@ void InstanceKlass::remove_unshareable_info() {
|
|
m->remove_unshareable_info();
|
|
}
|
|
|
|
+ if (UseAppCDS) {
|
|
+ if (_oop_map_cache != NULL) {
|
|
+ delete _oop_map_cache;
|
|
+ _oop_map_cache = NULL;
|
|
+ }
|
|
+
|
|
+ JNIid::deallocate(jni_ids());
|
|
+ set_jni_ids(NULL);
|
|
+
|
|
+ jmethodID* jmeths = methods_jmethod_ids_acquire();
|
|
+ if (jmeths != (jmethodID*)NULL) {
|
|
+ release_set_methods_jmethod_ids(NULL);
|
|
+ FreeHeap(jmeths);
|
|
+ }
|
|
+ }
|
|
+
|
|
// do array classes also.
|
|
array_klasses_do(remove_unshareable_in_class);
|
|
}
|
|
diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp
|
|
index ba20471..399290f 100644
|
|
--- a/hotspot/src/share/vm/oops/klass.cpp
|
|
+++ b/hotspot/src/share/vm/oops/klass.cpp
|
|
@@ -63,6 +63,9 @@ void Klass::set_is_cloneable() {
|
|
}
|
|
}
|
|
|
|
+ClassLoaderData *Klass::_fake_loader_data_App = reinterpret_cast<ClassLoaderData *>(0xFDFDFDFA);
|
|
+ClassLoaderData *Klass::_fake_loader_data_Ext = reinterpret_cast<ClassLoaderData *>(0xFDFDFDFB);
|
|
+
|
|
void Klass::set_name(Symbol* n) {
|
|
_name = n;
|
|
if (_name != NULL) _name->increment_refcount();
|
|
@@ -536,8 +539,21 @@ void Klass::remove_unshareable_info() {
|
|
set_java_mirror(NULL);
|
|
set_next_link(NULL);
|
|
|
|
- // Null out class_loader_data because we don't share that yet.
|
|
- set_class_loader_data(NULL);
|
|
+ if (!UseAppCDS) {
|
|
+ // CDS logic
|
|
+ set_class_loader_data(NULL);
|
|
+ } else if (class_loader_data() != NULL) {
|
|
+ // AppCDS logic
|
|
+ if (class_loader() == NULL) {
|
|
+ // Null out class loader data for classes loaded by bootstrap (null) loader
|
|
+ set_class_loader_data(NULL);
|
|
+ } else if(SystemDictionary::is_ext_class_loader(class_loader())) {
|
|
+ // Mark class loaded by system class loader
|
|
+ set_class_loader_data(_fake_loader_data_Ext);
|
|
+ } else {
|
|
+ set_class_loader_data(_fake_loader_data_App);
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
|
|
@@ -545,7 +561,10 @@ void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protec
|
|
// If an exception happened during CDS restore, some of these fields may already be
|
|
// set. We leave the class on the CLD list, even if incomplete so that we don't
|
|
// modify the CLD list outside a safepoint.
|
|
- if (class_loader_data() == NULL) {
|
|
+ if (class_loader_data() == NULL || has_fake_loader_data()) {
|
|
+ // CDS should not set fake loader data
|
|
+ assert(!has_fake_loader_data() || (has_fake_loader_data() && UseAppCDS),
|
|
+ "setting fake loader data possible only with AppCDS enabled");
|
|
// Restore class_loader_data
|
|
set_class_loader_data(loader_data);
|
|
|
|
diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp
|
|
index 428df42..cb7640c 100644
|
|
--- a/hotspot/src/share/vm/oops/klass.hpp
|
|
+++ b/hotspot/src/share/vm/oops/klass.hpp
|
|
@@ -188,6 +188,10 @@ private:
|
|
// -1.
|
|
jshort _shared_class_path_index;
|
|
|
|
+ // This is used only during AppCDS to mark classes that have non-null class loader
|
|
+ static ClassLoaderData* _fake_loader_data_App;
|
|
+ static ClassLoaderData* _fake_loader_data_Ext;
|
|
+
|
|
friend class SharedClassUtil;
|
|
protected:
|
|
|
|
@@ -202,6 +206,10 @@ protected:
|
|
enum StaticLookupMode { find_static, skip_static };
|
|
enum PrivateLookupMode { find_private, skip_private };
|
|
|
|
+ bool has_fake_loader_data_App() { return class_loader_data() == _fake_loader_data_App; }
|
|
+ bool has_fake_loader_data_Ext() { return class_loader_data() == _fake_loader_data_Ext; }
|
|
+ bool has_fake_loader_data() { return (has_fake_loader_data_App() || has_fake_loader_data_Ext()); }
|
|
+
|
|
bool is_klass() const volatile { return true; }
|
|
|
|
// super
|
|
diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp
|
|
index f9b6bd3..a04dcac 100644
|
|
--- a/hotspot/src/share/vm/runtime/arguments.cpp
|
|
+++ b/hotspot/src/share/vm/runtime/arguments.cpp
|
|
@@ -3020,6 +3020,23 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
|
// Remaining part of option string
|
|
const char* tail;
|
|
|
|
+ // Special handling for UseAppCDS flag - it has to enable
|
|
+ // SharedArviveFile flag no matter where it's located in the
|
|
+ // argument list (and in order to enable UseAppCDS)
|
|
+ for (int index = 0; index < args->nOptions; index++) {
|
|
+ const JavaVMOption* option = args->options + index;
|
|
+ if (match_option(option, "-XX:+UseAppCDS", &tail)) {
|
|
+ if (!process_argument("+UseAppCDS", args->ignoreUnrecognized, origin)) {
|
|
+ return JNI_EINVAL;
|
|
+ } else {
|
|
+ const char* n = "SharedArchiveFile";
|
|
+ Flag* shared_archive_flag = Flag::find_flag(n, strlen(n), true, true);
|
|
+ shared_archive_flag->unlock_diagnostic();
|
|
+ FLAG_SET_CMDLINE(bool, UseAppCDS, true);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
// iterate over arguments
|
|
for (int index = 0; index < args->nOptions; index++) {
|
|
bool is_absolute_path = false; // for -agentpath vs -agentlib
|
|
diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp
|
|
index 46bbfb4..520cc31 100644
|
|
--- a/hotspot/src/share/vm/runtime/globals.hpp
|
|
+++ b/hotspot/src/share/vm/runtime/globals.hpp
|
|
@@ -4010,6 +4010,9 @@ class CommandLineFlags {
|
|
product(ccstr, ExtraSharedClassListFile, NULL, \
|
|
"Extra classlist for building the CDS archive file") \
|
|
\
|
|
+ product(bool, UseAppCDS, false, \
|
|
+ "Enable Application Class Data Sharing (AppCDS)") \
|
|
+ \
|
|
experimental(uintx, ArrayAllocatorMallocLimit, \
|
|
SOLARIS_ONLY(64*K) NOT_SOLARIS(max_uintx), \
|
|
"Allocation less than this value will be allocated " \
|
|
diff --git a/hotspot/src/share/vm/runtime/javaCalls.cpp b/hotspot/src/share/vm/runtime/javaCalls.cpp
|
|
index 12925a9..217b8ff 100644
|
|
--- a/hotspot/src/share/vm/runtime/javaCalls.cpp
|
|
+++ b/hotspot/src/share/vm/runtime/javaCalls.cpp
|
|
@@ -310,7 +310,7 @@ void JavaCalls::call(JavaValue* result, methodHandle method, JavaCallArguments*
|
|
void JavaCalls::call_helper(JavaValue* result, methodHandle* m, JavaCallArguments* args, TRAPS) {
|
|
// During dumping, Java execution environment is not fully initialized. Also, Java execution
|
|
// may cause undesirable side-effects in the class metadata.
|
|
- assert(!DumpSharedSpaces, "must not execute Java bytecodes when dumping");
|
|
+ assert(!DumpSharedSpaces || UseAppCDS, "must not execute Java bytecodes when dumping");
|
|
|
|
methodHandle method = *m;
|
|
JavaThread* thread = (JavaThread*)THREAD;
|
|
diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp
|
|
index 03b6aaf..03c1098 100644
|
|
--- a/hotspot/src/share/vm/runtime/thread.cpp
|
|
+++ b/hotspot/src/share/vm/runtime/thread.cpp
|
|
@@ -3428,6 +3428,14 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
|
|
os::pause();
|
|
}
|
|
|
|
+ if (DumpSharedSpaces) {
|
|
+ // when dumping shared spaces for AppCDS we must disable bytecode
|
|
+ // rewriting as it initializes internal (cached) meta-data that
|
|
+ // would be stored in the archive but cannot be carried over to
|
|
+ // the next execution
|
|
+ RewriteBytecodes = false;
|
|
+ }
|
|
+
|
|
#ifndef USDT2
|
|
HS_DTRACE_PROBE(hotspot, vm__init__begin);
|
|
#else /* USDT2 */
|
|
@@ -3554,8 +3562,8 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
|
|
|
|
// At this point, the Universe is initialized, but we have not executed
|
|
// any byte code. Now is a good time (the only time) to dump out the
|
|
- // internal state of the JVM for sharing.
|
|
- if (DumpSharedSpaces) {
|
|
+ // internal state of the JVM for sharing, unless AppCDS is enabled.
|
|
+ if (!UseAppCDS && DumpSharedSpaces) {
|
|
MetaspaceShared::preload_and_dump(CHECK_0);
|
|
ShouldNotReachHere();
|
|
}
|
|
@@ -3682,6 +3690,11 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
|
|
vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION));
|
|
}
|
|
|
|
+ if (UseAppCDS && DumpSharedSpaces) {
|
|
+ MetaspaceShared::preload_and_dump(CHECK_0);
|
|
+ ShouldNotReachHere();
|
|
+ }
|
|
+
|
|
#if INCLUDE_ALL_GCS
|
|
// Support for ConcurrentMarkSweep. This should be cleaned up
|
|
// and better encapsulated. The ugly nested if test would go away
|
|
diff --git a/hotspot/src/share/vm/utilities/ostream.cpp b/hotspot/src/share/vm/utilities/ostream.cpp
|
|
index fc17aeb..2b458fe 100644
|
|
--- a/hotspot/src/share/vm/utilities/ostream.cpp
|
|
+++ b/hotspot/src/share/vm/utilities/ostream.cpp
|
|
@@ -495,7 +495,7 @@ static const char* make_log_name_internal(const char* log_name, const char* forc
|
|
// -XX:DumpLoadedClassList=<file_name>
|
|
// in log_name, %p => pid1234 and
|
|
// %t => YYYY-MM-DD_HH-MM-SS
|
|
-static const char* make_log_name(const char* log_name, const char* force_directory) {
|
|
+const char* make_log_name(const char* log_name, const char* force_directory) {
|
|
char timestr[32];
|
|
get_datetime_string(timestr, sizeof(timestr));
|
|
return make_log_name_internal(log_name, force_directory, os::current_process_id(),
|
|
diff --git a/hotspot/src/share/vm/utilities/ostream.hpp b/hotspot/src/share/vm/utilities/ostream.hpp
|
|
index fbcb299..530c523 100644
|
|
--- a/hotspot/src/share/vm/utilities/ostream.hpp
|
|
+++ b/hotspot/src/share/vm/utilities/ostream.hpp
|
|
@@ -332,4 +332,6 @@ class networkStream : public bufferedStream {
|
|
|
|
#endif
|
|
|
|
+const char* make_log_name(const char* log_name, const char* force_directory);
|
|
+
|
|
#endif // SHARE_VM_UTILITIES_OSTREAM_HPP
|
|
diff --git a/jdk/src/share/classes/java/lang/ClassLoader.java b/jdk/src/share/classes/java/lang/ClassLoader.java
|
|
index 2e98092..f305c1e 100644
|
|
--- a/jdk/src/share/classes/java/lang/ClassLoader.java
|
|
+++ b/jdk/src/share/classes/java/lang/ClassLoader.java
|
|
@@ -2182,6 +2182,10 @@ public abstract class ClassLoader {
|
|
|
|
// Retrieves the assertion directives from the VM.
|
|
private static native AssertionStatusDirectives retrieveDirectives();
|
|
+
|
|
+ protected ProtectionDomain getProtectionDomainInternal(String name) {
|
|
+ return null;
|
|
+ }
|
|
}
|
|
|
|
|
|
diff --git a/jdk/src/share/classes/java/net/URLClassLoader.java b/jdk/src/share/classes/java/net/URLClassLoader.java
|
|
index 416941c..e82cb6d 100644
|
|
--- a/jdk/src/share/classes/java/net/URLClassLoader.java
|
|
+++ b/jdk/src/share/classes/java/net/URLClassLoader.java
|
|
@@ -38,6 +38,7 @@ import java.security.Permission;
|
|
import java.security.PermissionCollection;
|
|
import java.security.PrivilegedAction;
|
|
import java.security.PrivilegedExceptionAction;
|
|
+import java.security.ProtectionDomain;
|
|
import java.security.SecureClassLoader;
|
|
import java.util.Enumeration;
|
|
import java.util.List;
|
|
@@ -343,6 +344,25 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
|
|
return ucp.getURLs();
|
|
}
|
|
|
|
+ /*
|
|
+ * Retrieve protection domain using the specified class name.
|
|
+ * Called from the VM to support AppCDS
|
|
+ */
|
|
+ protected ProtectionDomain getProtectionDomainInternal(String name) {
|
|
+ String path = name.replace('.', '/').concat(".class");
|
|
+ Resource res = ucp.getResource(path, false);
|
|
+
|
|
+ if(res == null)
|
|
+ {
|
|
+ // Should never happen
|
|
+ throw new AssertionError("Cannot find resource fpr path " + path);
|
|
+ }
|
|
+ URL url = res.getCodeSourceURL();
|
|
+ CodeSigner[] signers = res.getCodeSigners();
|
|
+ CodeSource cs = new CodeSource(url, signers);
|
|
+ return getProtectionDomain(cs);
|
|
+ }
|
|
+
|
|
/**
|
|
* Finds and loads the class with the specified name from the URL search
|
|
* path. Any URLs referring to JAR files are loaded and opened as needed
|
|
diff --git a/jdk/src/share/classes/java/security/SecureClassLoader.java b/jdk/src/share/classes/java/security/SecureClassLoader.java
|
|
index 145f4fc..cb5f017 100644
|
|
--- a/jdk/src/share/classes/java/security/SecureClassLoader.java
|
|
+++ b/jdk/src/share/classes/java/security/SecureClassLoader.java
|
|
@@ -195,7 +195,7 @@ public class SecureClassLoader extends ClassLoader {
|
|
/*
|
|
* Returned cached ProtectionDomain for the specified CodeSource.
|
|
*/
|
|
- private ProtectionDomain getProtectionDomain(CodeSource cs) {
|
|
+ protected ProtectionDomain getProtectionDomain(CodeSource cs) {
|
|
if (cs == null)
|
|
return null;
|
|
|
|
@@ -215,6 +215,7 @@ public class SecureClassLoader extends ClassLoader {
|
|
return pd;
|
|
}
|
|
|
|
+
|
|
/*
|
|
* Check to make sure the class loader has been initialized.
|
|
*/
|