1317 lines
50 KiB
Diff
1317 lines
50 KiB
Diff
From a7acbdd7c7885a92e3e62d485c0ceaa95923806f Mon Sep 17 00:00:00 2001
|
|
Date: Mon, 27 May 2024 16:14:55 +0800
|
|
Subject: [PATCH] [Huawei]Add Aggressive CDS
|
|
---
|
|
hotspot/make/bsd/makefiles/mapfile-vers-debug | 1 +
|
|
.../make/bsd/makefiles/mapfile-vers-product | 1 +
|
|
.../make/linux/makefiles/mapfile-vers-debug | 1 +
|
|
.../make/linux/makefiles/mapfile-vers-product | 1 +
|
|
hotspot/src/share/vm/cds/archiveBuilder.cpp | 5 +
|
|
hotspot/src/share/vm/cds/dynamicArchive.cpp | 20 +
|
|
.../share/vm/classfile/classFileParser.cpp | 32 ++
|
|
.../vm/classfile/systemDictionaryShared.cpp | 375 ++++++++++++++++++
|
|
.../vm/classfile/systemDictionaryShared.hpp | 13 +
|
|
hotspot/src/share/vm/classfile/vmSymbols.hpp | 2 +
|
|
hotspot/src/share/vm/memory/filemap.cpp | 53 ++-
|
|
hotspot/src/share/vm/memory/filemap.hpp | 11 +
|
|
hotspot/src/share/vm/prims/jvm.cpp | 30 ++
|
|
hotspot/src/share/vm/prims/jvm.h | 6 +
|
|
hotspot/src/share/vm/runtime/arguments.cpp | 16 +
|
|
hotspot/src/share/vm/runtime/arguments.hpp | 4 +
|
|
hotspot/src/share/vm/runtime/globals.hpp | 8 +
|
|
hotspot/src/share/vm/utilities/macros.hpp | 9 +
|
|
jdk/make/mapfiles/libjava/mapfile-linux | 1 +
|
|
jdk/make/mapfiles/libjava/mapfile-vers | 1 +
|
|
.../share/classes/java/lang/ClassLoader.java | 35 ++
|
|
.../classes/java/net/AggressiveCDSPlugin.java | 45 +++
|
|
.../classes/java/net/URLClassLoader.java | 27 ++
|
|
.../java/security/ProtectionDomain.java | 16 +
|
|
.../java/security/SecureClassLoader.java | 12 +
|
|
.../share/classes/sun/misc/URLClassPath.java | 18 +
|
|
jdk/src/share/javavm/export/jvm.h | 5 +
|
|
jdk/src/share/native/java/lang/ClassLoader.c | 25 ++
|
|
28 files changed, 772 insertions(+), 1 deletion(-)
|
|
create mode 100644 jdk/src/share/classes/java/net/AggressiveCDSPlugin.java
|
|
|
|
diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-debug b/hotspot/make/bsd/makefiles/mapfile-vers-debug
|
|
index c60ad3e00..86af8a1be 100644
|
|
--- a/hotspot/make/bsd/makefiles/mapfile-vers-debug
|
|
+++ b/hotspot/make/bsd/makefiles/mapfile-vers-debug
|
|
@@ -233,6 +233,7 @@
|
|
_JVM_AdaptiveHeapGetG1PeriodicGCInterval
|
|
_JVM_AdaptiveHeapSetG1PeriodicGCLoadThreshold
|
|
_JVM_AdaptiveHeapGetG1PeriodicGCLoadThreshold
|
|
+ _JVM_DefineTrustedSharedClass
|
|
_JVM_Sleep
|
|
_JVM_Socket
|
|
_JVM_SocketAvailable
|
|
diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-product b/hotspot/make/bsd/makefiles/mapfile-vers-product
|
|
index 94d123c9f..69cd3f962 100644
|
|
--- a/hotspot/make/bsd/makefiles/mapfile-vers-product
|
|
+++ b/hotspot/make/bsd/makefiles/mapfile-vers-product
|
|
@@ -233,6 +233,7 @@
|
|
_JVM_AdaptiveHeapGetG1PeriodicGCLoadThreshold
|
|
_JVM_AdaptiveHeapSetG1PeriodicGCInterval
|
|
_JVM_AdaptiveHeapSetG1PeriodicGCLoadThreshold
|
|
+ _JVM_DefineTrustedSharedClass
|
|
_JVM_Sleep
|
|
_JVM_Socket
|
|
_JVM_SocketAvailable
|
|
diff --git a/hotspot/make/linux/makefiles/mapfile-vers-debug b/hotspot/make/linux/makefiles/mapfile-vers-debug
|
|
index 1ebe436cb..b006a84c2 100644
|
|
--- a/hotspot/make/linux/makefiles/mapfile-vers-debug
|
|
+++ b/hotspot/make/linux/makefiles/mapfile-vers-debug
|
|
@@ -237,6 +237,7 @@ SUNWprivate_1.1 {
|
|
JVM_AdaptiveHeapGetG1PeriodicGCInterval;
|
|
JVM_AdaptiveHeapSetG1PeriodicGCLoadThreshold;
|
|
JVM_AdaptiveHeapGetG1PeriodicGCLoadThreshold;
|
|
+ JVM_DefineTrustedSharedClass;
|
|
JVM_Sleep;
|
|
JVM_Socket;
|
|
JVM_SocketAvailable;
|
|
diff --git a/hotspot/make/linux/makefiles/mapfile-vers-product b/hotspot/make/linux/makefiles/mapfile-vers-product
|
|
index 75e527894..64ccc47fb 100644
|
|
--- a/hotspot/make/linux/makefiles/mapfile-vers-product
|
|
+++ b/hotspot/make/linux/makefiles/mapfile-vers-product
|
|
@@ -237,6 +237,7 @@ SUNWprivate_1.1 {
|
|
JVM_AdaptiveHeapGetG1PeriodicGCInterval;
|
|
JVM_AdaptiveHeapSetG1PeriodicGCLoadThreshold;
|
|
JVM_AdaptiveHeapGetG1PeriodicGCLoadThreshold;
|
|
+ JVM_DefineTrustedSharedClass;
|
|
JVM_Sleep;
|
|
JVM_Socket;
|
|
JVM_SocketAvailable;
|
|
diff --git a/hotspot/src/share/vm/cds/archiveBuilder.cpp b/hotspot/src/share/vm/cds/archiveBuilder.cpp
|
|
index 13a620028..decd638e0 100644
|
|
--- a/hotspot/src/share/vm/cds/archiveBuilder.cpp
|
|
+++ b/hotspot/src/share/vm/cds/archiveBuilder.cpp
|
|
@@ -772,7 +772,12 @@ void ArchiveBuilder::clean_up_src_obj_table() {
|
|
}
|
|
|
|
void ArchiveBuilder::write_archive(FileMapInfo* mapinfo) {
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ assert(mapinfo->header()->magic() == (UseAggressiveCDS ?
|
|
+ CDS_AGGRESSIVE_ARCHIVE_MAGIC : CDS_DYNAMIC_ARCHIVE_MAGIC), "Dynamic CDS or Aggressive CDS calls only");
|
|
+#else
|
|
assert(mapinfo->header()->magic() == CDS_DYNAMIC_ARCHIVE_MAGIC, "Dynamic CDS calls only");
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
|
|
mapinfo->write_dynamic_header();
|
|
|
|
diff --git a/hotspot/src/share/vm/cds/dynamicArchive.cpp b/hotspot/src/share/vm/cds/dynamicArchive.cpp
|
|
index a623c5b00..2e5ab9385 100644
|
|
--- a/hotspot/src/share/vm/cds/dynamicArchive.cpp
|
|
+++ b/hotspot/src/share/vm/cds/dynamicArchive.cpp
|
|
@@ -165,6 +165,16 @@ void DynamicArchiveBuilder::init_header() {
|
|
|
|
FileMapInfo* base_info = FileMapInfo::current_info();
|
|
_header->set_base_header_crc(base_info->header()->crc());
|
|
+
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ if (UseAggressiveCDS) {
|
|
+ int crc = FileMapInfo::DynamicArchiveHeader::get_current_program_crc();
|
|
+ _header->set_program_crc(crc);
|
|
+ } else {
|
|
+ _header->set_program_crc(0);
|
|
+ }
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
+
|
|
for (int i = 0; i < MetaspaceShared::n_regions; i++) {
|
|
_header->set_base_region_crc(i, base_info->header()->space_crc(i));
|
|
}
|
|
@@ -401,6 +411,16 @@ bool DynamicArchive::validate(FileMapInfo* dynamic_info) {
|
|
return false;
|
|
}
|
|
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ // Check the program crc
|
|
+ if (UseAggressiveCDS) {
|
|
+ if (dynamic_header->program_crc() != FileMapInfo::DynamicArchiveHeader::get_current_program_crc()) {
|
|
+ FileMapInfo::fail_continue("Aggressive Dynamic archive cannot be used: program crc verification failed.");
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
+
|
|
// Check each space's crc
|
|
for (int i = 0; i < MetaspaceShared::n_regions; i++) {
|
|
if (dynamic_header->base_region_crc(i) != base_info->space_crc(i)) {
|
|
diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp
|
|
index b9fde38dc..8f1b2d47a 100644
|
|
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp
|
|
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp
|
|
@@ -4416,6 +4416,38 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
|
if (DynamicDumpSharedSpaces && !SystemDictionary::is_builtin_loader(class_loader)) {
|
|
this_klass->set_shared_classpath_index(UNREGISTERED_INDEX);
|
|
SystemDictionaryShared::set_shared_class_misc_info(this_klass(), cfs);
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ if (UseAggressiveCDS && protection_domain() != NULL) {
|
|
+ ResourceMark rm(THREAD);
|
|
+ KlassHandle protectionDomain_klass(THREAD, SystemDictionary::ProtectionDomain_klass());
|
|
+ JavaValue result(T_OBJECT);
|
|
+ JavaCalls::call_virtual(&result,
|
|
+ protection_domain,
|
|
+ protectionDomain_klass,
|
|
+ vmSymbols::getLocationNoFragString_name(),
|
|
+ vmSymbols::void_string_signature(),
|
|
+ THREAD);
|
|
+ if (!HAS_PENDING_EXCEPTION) {
|
|
+ oop res_oop = (oop) result.get_jobject();
|
|
+ if (res_oop != NULL) {
|
|
+ char* string_value = java_lang_String::as_utf8_string(res_oop);
|
|
+ if (strlen(string_value) != 0) {
|
|
+ SystemDictionaryShared::set_url_string(this_klass(), string_value);
|
|
+ SystemDictionaryShared::save_timestamp(this_klass(), string_value);
|
|
+ }
|
|
+ }
|
|
+ } else {
|
|
+ char* ex_msg = const_cast<char*>("");
|
|
+ oop message = java_lang_Throwable::message(PENDING_EXCEPTION);
|
|
+ if (message != NULL) {
|
|
+ ex_msg = java_lang_String::as_utf8_string(message);
|
|
+ }
|
|
+ dynamic_cds_log->print_cr("get LocationNoFragString from protection_domain has encountered exception: %s %s",
|
|
+ PENDING_EXCEPTION->klass()->external_name(), ex_msg);
|
|
+ CLEAR_PENDING_EXCEPTION;
|
|
+ }
|
|
+ }
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
}
|
|
#endif // INCLUDE_CDS
|
|
|
|
diff --git a/hotspot/src/share/vm/classfile/systemDictionaryShared.cpp b/hotspot/src/share/vm/classfile/systemDictionaryShared.cpp
|
|
index 3a601ee37..7707d6ac6 100644
|
|
--- a/hotspot/src/share/vm/classfile/systemDictionaryShared.cpp
|
|
+++ b/hotspot/src/share/vm/classfile/systemDictionaryShared.cpp
|
|
@@ -35,6 +35,10 @@
|
|
#include "utilities/resourceHash.hpp"
|
|
#include "runtime/mutexLocker.hpp"
|
|
#include "utilities/ostream.hpp"
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+#include "memory/oopFactory.hpp"
|
|
+#include "runtime/javaCalls.hpp"
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
|
|
DEBUG_ONLY(bool SystemDictionaryShared::_no_class_loading_should_happen = false;)
|
|
bool SystemDictionaryShared::_dump_in_progress = false;
|
|
@@ -68,6 +72,14 @@ public:
|
|
}
|
|
};
|
|
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ struct DTSharedClassFile {
|
|
+ int length;
|
|
+ u1 data[1];
|
|
+ int obj_size() { return ((int)sizeof(length)) + length; }
|
|
+ };
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
+
|
|
InstanceKlass* _klass;
|
|
InstanceKlass* _nest_host;
|
|
bool _failed_verification;
|
|
@@ -78,6 +90,10 @@ public:
|
|
GrowableArray<DTVerifierConstraint>* _verifier_constraints;
|
|
GrowableArray<char>* _verifier_constraint_flags;
|
|
GrowableArray<DTLoaderConstraint>* _loader_constraints;
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ DTSharedClassFile* _url_string;
|
|
+ int64_t _classfile_timestamp;
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
|
|
DumpTimeSharedClassInfo() {
|
|
_klass = NULL;
|
|
@@ -92,6 +108,10 @@ public:
|
|
_verifier_constraints = NULL;
|
|
_verifier_constraint_flags = NULL;
|
|
_loader_constraints = NULL;
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ _url_string = NULL;
|
|
+ _classfile_timestamp = 0;
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
}
|
|
|
|
void add_verification_constraint(InstanceKlass* k, Symbol* name,
|
|
@@ -149,6 +169,44 @@ public:
|
|
void set_failed_verification() { _failed_verification = true; }
|
|
InstanceKlass* nest_host() const { return _nest_host; }
|
|
void set_nest_host(InstanceKlass* nest_host) { _nest_host = nest_host; }
|
|
+
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ DTSharedClassFile* url_string() {
|
|
+ return _url_string;
|
|
+ }
|
|
+
|
|
+ size_t url_string_size() {
|
|
+ if (_url_string != NULL) {
|
|
+ return (size_t)(_url_string->obj_size());
|
|
+ }
|
|
+ return (size_t)0;
|
|
+ }
|
|
+
|
|
+ void copy_url_string(char* string_value) {
|
|
+ assert(strlen(string_value) != 0, "sanity");
|
|
+ size_t string_len = strlen(string_value) + (size_t)1;
|
|
+ size_t size = offset_of(DTSharedClassFile, data) + string_len;
|
|
+ _url_string = (DTSharedClassFile*) NEW_C_HEAP_ARRAY(u1, size, mtInternal);
|
|
+ _url_string->length = (int)string_len;
|
|
+ memcpy(_url_string->data, string_value, string_len);
|
|
+ assert((int)size == _url_string->obj_size(), "sanity");
|
|
+ }
|
|
+
|
|
+ void free_url_string() {
|
|
+ if (_url_string != NULL) {
|
|
+ FREE_C_HEAP_ARRAY(u1, _url_string, mtInternal);
|
|
+ _url_string = NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ int64_t classfile_timestamp() {
|
|
+ return _classfile_timestamp;
|
|
+ }
|
|
+
|
|
+ void set_classfile_timestamp(int64_t classfile_timestamp) {
|
|
+ _classfile_timestamp = classfile_timestamp;
|
|
+ }
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
};
|
|
|
|
inline unsigned DumpTimeSharedClassTable_hash(InstanceKlass* const& k) {
|
|
@@ -245,7 +303,18 @@ public:
|
|
}
|
|
};
|
|
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ struct RTSharedClassFile {
|
|
+ int length;
|
|
+ u1 data[1];
|
|
+ };
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
+
|
|
InstanceKlass* _klass;
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ RTSharedClassFile* _url_string;
|
|
+ int64_t _classfile_timestamp;
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
int _num_verifier_constraints;
|
|
int _num_loader_constraints;
|
|
|
|
@@ -294,6 +363,17 @@ public:
|
|
verifier_constraint_flags_size(num_verifier_constraints);
|
|
}
|
|
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ static size_t byte_size(DumpTimeSharedClassInfo& info) {
|
|
+ size_t previous_size = byte_size(info._klass, info.num_verifier_constraints(), info.num_loader_constraints());
|
|
+ if (UseAggressiveCDS) {
|
|
+ size_t cf_size = info.url_string_size();
|
|
+ if (cf_size != 0) return align_up(previous_size, sizeof(int)) + cf_size;
|
|
+ }
|
|
+ return previous_size;
|
|
+ }
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
+
|
|
private:
|
|
size_t crc_offset() const {
|
|
return header_size_size();
|
|
@@ -321,6 +401,13 @@ private:
|
|
assert(0 <= i && i < _num_loader_constraints, "sanity");
|
|
}
|
|
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ size_t url_string_offset() const {
|
|
+ return align_up(verifier_constraint_flags_offset() + verifier_constraint_flags_size(_num_verifier_constraints),
|
|
+ sizeof(int));
|
|
+ }
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
+
|
|
public:
|
|
CrcInfo* crc() const {
|
|
assert(crc_size(_klass) > 0, "must be");
|
|
@@ -350,6 +437,20 @@ public:
|
|
return loader_constraints() + i;
|
|
}
|
|
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ RTSharedClassFile* url_string() {
|
|
+ return (RTSharedClassFile*)(address(this) + url_string_offset());
|
|
+ }
|
|
+
|
|
+ int64_t classfile_timestamp() {
|
|
+ return _classfile_timestamp;
|
|
+ }
|
|
+
|
|
+ void set_classfile_timestamp(int64_t classfile_timestamp) {
|
|
+ _classfile_timestamp = classfile_timestamp;
|
|
+ }
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
+
|
|
void init(DumpTimeSharedClassInfo& info) {
|
|
ArchiveBuilder* builder = ArchiveBuilder::current();
|
|
assert(builder->is_in_buffer_space(info._klass), "must be");
|
|
@@ -383,6 +484,18 @@ public:
|
|
}
|
|
}
|
|
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ if (info.url_string_size() != 0) {
|
|
+ _url_string = url_string();
|
|
+ memcpy(_url_string, info.url_string(), info.url_string_size());
|
|
+ ArchivePtrMarker::mark_pointer(&_url_string);
|
|
+ info.free_url_string();
|
|
+ } else {
|
|
+ _url_string = NULL;
|
|
+ }
|
|
+ set_classfile_timestamp(info.classfile_timestamp());
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
+
|
|
ArchivePtrMarker::mark_pointer(&_klass);
|
|
}
|
|
|
|
@@ -426,6 +539,69 @@ public:
|
|
const RunTimeSharedClassInfo* value, Symbol* key, int len_unused) {
|
|
return (value->_klass->name() == key);
|
|
}
|
|
+
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ // check timestamp in the load time when UseAggressiveCDS.
|
|
+ // regular_file(*.class): need to check timestamp.
|
|
+ // jar_file(*.jar): no need to check timestamp here,already check programe_crc
|
|
+ // somewhere else, see DynamicArchive::validate.
|
|
+ // other_file: not supported when UseAggressiveCDS.
|
|
+ bool check_classfile_timestamp(char* url_string, TRAPS) {
|
|
+ if (SystemDictionaryShared::is_regular_file(url_string)) {
|
|
+ ResourceMark rm(THREAD);
|
|
+ char* dir = SystemDictionaryShared::get_filedir(url_string);
|
|
+ if (dir == NULL) {
|
|
+ return false;
|
|
+ }
|
|
+ int64_t timestamp = SystemDictionaryShared::get_timestamp(dir, _klass->name());
|
|
+ if (timestamp != _classfile_timestamp) {
|
|
+ dynamic_cds_log->print_cr("%s, timestamp mismatch: " INT64_FORMAT " -> " INT64_FORMAT, _klass->name()->as_C_string(), _classfile_timestamp, timestamp);
|
|
+ return false;
|
|
+ }
|
|
+ } else if (!SystemDictionaryShared::is_jar_file(url_string)) {
|
|
+ dynamic_cds_log->print_cr("Unsupported URL:%s", url_string);
|
|
+ return false;
|
|
+ }
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ Handle get_protection_domain(Handle class_loader, TRAPS) {
|
|
+ if (_url_string == NULL) {
|
|
+ return Handle();
|
|
+ }
|
|
+ char* data_ptr = (char*)(_url_string->data);
|
|
+
|
|
+ if (CheckClassFileTimeStamp) {
|
|
+ if (!check_classfile_timestamp(data_ptr, THREAD)) {
|
|
+ return Handle();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ Handle url_string = java_lang_String::create_from_str(data_ptr, THREAD);
|
|
+ JavaValue result(T_OBJECT);
|
|
+ JavaCalls::call_virtual(&result,
|
|
+ class_loader,
|
|
+ class_loader->klass(),
|
|
+ vmSymbols::getProtectionDomainByURLString_name(),
|
|
+ vmSymbols::getProtectionDomainInternal_signature(),
|
|
+ url_string, THREAD);
|
|
+ if (!HAS_PENDING_EXCEPTION) {
|
|
+ oop pd = (oop) result.get_jobject();
|
|
+ return Handle(THREAD, pd);
|
|
+ } else {
|
|
+ ResourceMark rm(THREAD);
|
|
+ char* ex_msg = const_cast<char*>("");
|
|
+ oop message = java_lang_Throwable::message(PENDING_EXCEPTION);
|
|
+ if (message != NULL) {
|
|
+ ex_msg = java_lang_String::as_utf8_string(message);
|
|
+ }
|
|
+ dynamic_cds_log->print_cr("get protection_domain has encountered exception: %s %s",
|
|
+ PENDING_EXCEPTION->klass()->external_name(), ex_msg);
|
|
+ CLEAR_PENDING_EXCEPTION;
|
|
+ }
|
|
+ return Handle();
|
|
+ }
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
};
|
|
|
|
class RunTimeSharedDictionary : public OffsetCompactHashtable<
|
|
@@ -710,7 +886,11 @@ public:
|
|
|
|
bool do_entry(InstanceKlass* k, DumpTimeSharedClassInfo& info) {
|
|
if (!info.is_excluded()) {
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ size_t byte_size = RunTimeSharedClassInfo::byte_size(info);
|
|
+#else
|
|
size_t byte_size = RunTimeSharedClassInfo::byte_size(info._klass, info.num_verifier_constraints(), info.num_loader_constraints());
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
_shared_class_info_size += align_up(byte_size, KlassAlignmentInBytes);
|
|
}
|
|
return true; // keep on iterating
|
|
@@ -746,6 +926,38 @@ unsigned int SystemDictionaryShared::hash_for_shared_dictionary(address ptr) {
|
|
}
|
|
}
|
|
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+class ExcludeDuplicateKlass : StackObj {
|
|
+public:
|
|
+ static const int INITIAL_TABLE_SIZE = 15889;
|
|
+
|
|
+ ExcludeDuplicateKlass(int size) : _has_been_visited(size) {}
|
|
+
|
|
+ bool do_entry(InstanceKlass* k, DumpTimeSharedClassInfo& info) {
|
|
+ if (!info.is_excluded()) {
|
|
+ bool created;
|
|
+ Symbol* name = info._klass->name();
|
|
+ address* info_ptr = _has_been_visited.add_if_absent((address)name, (address)&info, &created);
|
|
+ if (!created) {
|
|
+ info.set_excluded();
|
|
+ DumpTimeSharedClassInfo* first_info = (DumpTimeSharedClassInfo*)(*info_ptr);
|
|
+ if (!first_info->is_excluded()) {
|
|
+ first_info->set_excluded();
|
|
+ }
|
|
+ if (TraceDynamicCDS) {
|
|
+ ResourceMark rm;
|
|
+ dynamic_cds_log->print_cr("[AggressiveCDS] Skipping duplicate class (excluded): %s", name->as_C_string());
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+private:
|
|
+ KVHashtable<address, address, mtClassShared> _has_been_visited;
|
|
+};
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
+
|
|
class CopySharedClassInfoToArchive : StackObj {
|
|
CompactHashtableWriter* _writer;
|
|
bool _is_builtin;
|
|
@@ -757,7 +969,11 @@ public:
|
|
|
|
bool do_entry(InstanceKlass* k, DumpTimeSharedClassInfo& info) {
|
|
if (!info.is_excluded() && info.is_builtin() == _is_builtin) {
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ size_t byte_size = RunTimeSharedClassInfo::byte_size(info);
|
|
+#else
|
|
size_t byte_size = RunTimeSharedClassInfo::byte_size(info._klass, info.num_verifier_constraints(), info.num_loader_constraints());
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
RunTimeSharedClassInfo* record;
|
|
record = (RunTimeSharedClassInfo*)ArchiveBuilder::ro_region_alloc(byte_size);
|
|
record->init(info);
|
|
@@ -787,6 +1003,12 @@ void SystemDictionaryShared::write_dictionary(RunTimeSharedDictionary* dictionar
|
|
bool is_builtin) {
|
|
CompactHashtableStats stats;
|
|
dictionary->reset();
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ if (UseAggressiveCDS && !is_builtin) {
|
|
+ ExcludeDuplicateKlass dup(ExcludeDuplicateKlass::INITIAL_TABLE_SIZE);
|
|
+ _dumptime_table->iterate(&dup);
|
|
+ }
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
CompactHashtableWriter writer(_dumptime_table->count_of(is_builtin), &stats);
|
|
CopySharedClassInfoToArchive copy(&writer, is_builtin);
|
|
assert_lock_strong(DumpTimeTable_lock);
|
|
@@ -909,3 +1131,156 @@ InstanceKlass* SystemDictionaryShared::find_dynamic_builtin_class(Symbol* name)
|
|
return NULL;
|
|
}
|
|
}
|
|
+
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+static const char* JAR_FILE_PREFIX = "jar://file:";
|
|
+static const char* FILE_SEPARATOR = "file://";
|
|
+static const char* CLASSFILE_SUFFIX = ".class";
|
|
+
|
|
+static bool start_with(char* str, const char* prefix) {
|
|
+ if (str == NULL || prefix == NULL || strlen(str) < strlen(prefix)) {
|
|
+ return false;
|
|
+ }
|
|
+ if (strncmp(str, prefix, strlen(prefix)) == 0) {
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
+bool SystemDictionaryShared::is_jar_file(char* url_string) {
|
|
+ if (start_with(url_string, JAR_FILE_PREFIX)) {
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
+bool SystemDictionaryShared::is_regular_file(char* url_string) {
|
|
+ if (start_with(url_string, FILE_SEPARATOR)) {
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
+char* SystemDictionaryShared::get_filedir(char* url_string) {
|
|
+ if (!is_regular_file(url_string)) {
|
|
+ return NULL;
|
|
+ }
|
|
+ char* dir = url_string + strlen(FILE_SEPARATOR);
|
|
+ struct stat st;
|
|
+ if (os::stat(dir, &st) == 0) {
|
|
+ if ((st.st_mode & S_IFDIR) == S_IFDIR) {
|
|
+ return dir;
|
|
+ }
|
|
+ }
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+int64_t SystemDictionaryShared::get_timestamp(char* dir, Symbol* class_name) {
|
|
+ char* name = class_name->as_C_string();
|
|
+ size_t name_len = strlen(name);
|
|
+ size_t dir_len = strlen(dir);
|
|
+ size_t classfile_suffix_len = strlen(CLASSFILE_SUFFIX);
|
|
+ char* file_path = NEW_RESOURCE_ARRAY(char, dir_len + name_len + classfile_suffix_len + 1);
|
|
+ memcpy(file_path, dir, dir_len);
|
|
+ memcpy(file_path + dir_len, name, name_len);
|
|
+ memcpy(file_path + dir_len + name_len, CLASSFILE_SUFFIX, classfile_suffix_len + 1);
|
|
+ assert(strlen(file_path) == dir_len + name_len + classfile_suffix_len, "sanity");
|
|
+ struct stat st;
|
|
+ if (os::stat(file_path, &st) == 0) {
|
|
+ return st.st_mtime;
|
|
+ }
|
|
+ dynamic_cds_log->print_cr("get timestamp failed:%s", file_path);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+Handle SystemDictionaryShared::get_protection_domain(InstanceKlass* k, Handle class_loader, TRAPS) {
|
|
+ assert(UseAggressiveCDS, "sanity");
|
|
+ RunTimeSharedClassInfo* info = RunTimeSharedClassInfo::get_for(k);
|
|
+ assert(!is_builtin_loader(class_loader), "sanity");
|
|
+ return info->get_protection_domain(class_loader, THREAD);
|
|
+}
|
|
+
|
|
+void SystemDictionaryShared::set_url_string(InstanceKlass* k, char* string_value) {
|
|
+ assert(UseAggressiveCDS, "sanity");
|
|
+ Arguments::assert_is_dumping_archive();
|
|
+ assert(!is_builtin(k), "must be unregistered class");
|
|
+ DumpTimeSharedClassInfo* info = find_or_allocate_info_for(k);
|
|
+ if (info != NULL && info->_url_string == NULL) {
|
|
+ info->copy_url_string(string_value);
|
|
+ }
|
|
+}
|
|
+
|
|
+void SystemDictionaryShared::save_timestamp(InstanceKlass* k, char* string_value) {
|
|
+ if (SystemDictionaryShared::is_regular_file(string_value)) {
|
|
+ char* dir = SystemDictionaryShared::get_filedir(string_value);
|
|
+ if (dir != NULL) {
|
|
+ int64_t timestamp = SystemDictionaryShared::get_timestamp(dir, k->name());
|
|
+ SystemDictionaryShared::set_classfile_timestamp(k, timestamp);
|
|
+ }
|
|
+ } else if (!SystemDictionaryShared::is_jar_file(string_value)) {
|
|
+ dynamic_cds_log->print_cr("Unsupported URL:%s", string_value);
|
|
+ }
|
|
+}
|
|
+
|
|
+void SystemDictionaryShared::set_classfile_timestamp(InstanceKlass* k, int64_t classfile_timestamp) {
|
|
+ assert(UseAggressiveCDS, "sanity");
|
|
+ Arguments::assert_is_dumping_archive();
|
|
+ assert(!is_builtin(k), "must be unregistered class");
|
|
+ DumpTimeSharedClassInfo* info = find_or_allocate_info_for(k);
|
|
+ if (info != NULL) {
|
|
+ info->set_classfile_timestamp(classfile_timestamp);
|
|
+ }
|
|
+}
|
|
+
|
|
+InstanceKlass* SystemDictionaryShared::lookup_trusted_share_class(Symbol* class_name,
|
|
+ Handle class_loader,
|
|
+ TRAPS) {
|
|
+ assert(UseAggressiveCDS, "sanity");
|
|
+ if (!UseSharedSpaces) {
|
|
+ return NULL;
|
|
+ }
|
|
+ if (class_name == NULL) { // don't do this for hidden classes
|
|
+ return NULL;
|
|
+ }
|
|
+ if (SystemDictionary::is_builtin_loader(class_loader)) {
|
|
+ // Do nothing for the BUILTIN loaders.
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ // Classloaders that support parallelism, e.g. bootstrap classloader,
|
|
+ // or all classloaders with UnsyncloadClass do not acquire lock here
|
|
+ bool DoObjectLock = true;
|
|
+ if (is_parallelCapable(class_loader)) {
|
|
+ DoObjectLock = false;
|
|
+ }
|
|
+
|
|
+ register_loader(class_loader, CHECK_NULL);
|
|
+
|
|
+ // Make sure we are synchronized on the class loader before we proceed
|
|
+ Handle lockObject = compute_loader_lock_object(class_loader, THREAD);
|
|
+ check_loader_lock_contention(lockObject, THREAD);
|
|
+ ObjectLocker ol(lockObject, THREAD, DoObjectLock);
|
|
+
|
|
+ const RunTimeSharedClassInfo* record = find_record(&_dynamic_unregistered_dictionary, class_name);
|
|
+ if (record == NULL) {
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ Handle protection_domain = SystemDictionaryShared::get_protection_domain(record->_klass, class_loader, CHECK_NULL);
|
|
+
|
|
+ if (protection_domain.is_null()) {
|
|
+ // URL not matched, which means should not be loaded by this classloader
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ instanceKlassHandle k = acquire_class_for_current_thread(record->_klass, class_loader, protection_domain, NULL, THREAD);
|
|
+ if (!HAS_PENDING_EXCEPTION && k() != NULL) {
|
|
+ if (is_parallelCapable(class_loader)) {
|
|
+ k = find_or_define_instance_class(class_name, class_loader, k, THREAD);
|
|
+ } else {
|
|
+ define_instance_class(k, THREAD);
|
|
+ }
|
|
+ }
|
|
+ return k();
|
|
+}
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
\ No newline at end of file
|
|
diff --git a/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp b/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp
|
|
index fb9583d4e..3025e7350 100644
|
|
--- a/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp
|
|
+++ b/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp
|
|
@@ -238,6 +238,19 @@ public:
|
|
TRAPS);
|
|
|
|
static InstanceKlass* find_dynamic_builtin_class(Symbol* name);
|
|
+
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ static bool is_jar_file(char* url_string);
|
|
+ static bool is_regular_file(char* url_string);
|
|
+ static char* get_filedir(char* url_string);
|
|
+ static int64_t get_timestamp(char* dir, Symbol* class_name);
|
|
+ static Handle get_protection_domain(InstanceKlass* k, Handle class_loader, TRAPS);
|
|
+ static void set_url_string(InstanceKlass* k, char* string_value);
|
|
+ static void save_timestamp(InstanceKlass* k, char* string_value);
|
|
+ static void set_classfile_timestamp(InstanceKlass* k, int64_t classfile_timestamp);
|
|
+ static int64_t get_classfile_timestamp(InstanceKlass* k);
|
|
+ static InstanceKlass* lookup_trusted_share_class(Symbol* class_name, Handle class_loader, TRAPS);
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
};
|
|
|
|
#endif // SHARE_VM_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP
|
|
diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp
|
|
index 79f15589f..2ddc6581e 100644
|
|
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp
|
|
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp
|
|
@@ -421,6 +421,8 @@
|
|
template(definePackageInternal_signature, "(Ljava/lang/String;Ljava/util/jar/Manifest;Ljava/net/URL;)V") \
|
|
template(getProtectionDomainInternal_name, "getProtectionDomainInternal") \
|
|
template(getProtectionDomainInternal_signature, "(Ljava/lang/String;)Ljava/security/ProtectionDomain;") \
|
|
+ template(getProtectionDomainByURLString_name, "getProtectionDomainByURLString") \
|
|
+ template(getLocationNoFragString_name, "getLocationNoFragString") \
|
|
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 166fe2b80..b60d77be6 100644
|
|
--- a/hotspot/src/share/vm/memory/filemap.cpp
|
|
+++ b/hotspot/src/share/vm/memory/filemap.cpp
|
|
@@ -208,7 +208,11 @@ size_t FileMapInfo::DynamicArchiveHeader::data_size() {
|
|
}
|
|
|
|
bool FileMapInfo::DynamicArchiveHeader::validate() {
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ if (_magic != (UseAggressiveCDS ? CDS_AGGRESSIVE_ARCHIVE_MAGIC : CDS_DYNAMIC_ARCHIVE_MAGIC)) {
|
|
+#else
|
|
if (_magic != CDS_DYNAMIC_ARCHIVE_MAGIC) {
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
FileMapInfo::fail_continue("The shared archive file has a bad magic number.");
|
|
return false;
|
|
}
|
|
@@ -243,9 +247,48 @@ bool FileMapInfo::DynamicArchiveHeader::validate() {
|
|
return true;
|
|
}
|
|
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+int FileMapInfo::DynamicArchiveHeader::get_current_program_crc() {
|
|
+ int cur_crc = 0;
|
|
+ const char* full_cmd = Arguments::java_command();
|
|
+ if (full_cmd == NULL) {
|
|
+ return 0;
|
|
+ }
|
|
+ const char* main_path = Arguments::get_appclasspath();
|
|
+ int main_path_len = strlen(main_path);
|
|
+ bool is_jar_file = strncmp(full_cmd, main_path, main_path_len) == 0;
|
|
+ if (is_jar_file) {
|
|
+ fio_fd fd = os::open(main_path, O_RDONLY | O_BINARY, 0);
|
|
+ assert(fd >= 0, "sanity");
|
|
+
|
|
+ uint32_t file_size = (uint32_t) os::lseek(fd, 0, SEEK_END);
|
|
+ os::lseek(fd, 0, SEEK_SET);
|
|
+ uint32_t max_size = 40 * 1024 * 1024; // 40M
|
|
+
|
|
+ ResourceMark rm;
|
|
+ char* buf = NEW_RESOURCE_ARRAY(char, max_size);
|
|
+
|
|
+ while(file_size) {
|
|
+ uint32_t size = MIN2(max_size, file_size);
|
|
+ size_t n = os::read(fd, buf, (unsigned int)size);
|
|
+ file_size -= n;
|
|
+ cur_crc = ClassLoader::crc32(cur_crc, buf, n);
|
|
+ }
|
|
+ }
|
|
+ return cur_crc;
|
|
+}
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
+
|
|
void FileMapInfo::FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) {
|
|
if (DynamicDumpSharedSpaces) {
|
|
- _magic = CDS_DYNAMIC_ARCHIVE_MAGIC;
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ if (UseAggressiveCDS) {
|
|
+ _magic = CDS_AGGRESSIVE_ARCHIVE_MAGIC;
|
|
+ } else
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
+ {
|
|
+ _magic = CDS_DYNAMIC_ARCHIVE_MAGIC;
|
|
+ }
|
|
} else {
|
|
_magic = CDS_ARCHIVE_MAGIC;
|
|
}
|
|
@@ -434,7 +477,11 @@ bool FileMapInfo::get_base_archive_name_from_header(const char* archive_name,
|
|
os::close(fd);
|
|
return false;
|
|
}
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ if (dynamic_header->magic() != (UseAggressiveCDS ? CDS_AGGRESSIVE_ARCHIVE_MAGIC : CDS_DYNAMIC_ARCHIVE_MAGIC)) {
|
|
+#else
|
|
if (dynamic_header->magic() != CDS_DYNAMIC_ARCHIVE_MAGIC) {
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
// Not a dynamic header, no need to proceed further.
|
|
*size = 0;
|
|
delete dynamic_header;
|
|
@@ -499,7 +546,11 @@ bool FileMapInfo::check_archive(const char* archive_name, bool is_static) {
|
|
}
|
|
} else {
|
|
DynamicArchiveHeader* dynamic_header = (DynamicArchiveHeader*)header;
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ if (dynamic_header->magic() != (UseAggressiveCDS ? CDS_AGGRESSIVE_ARCHIVE_MAGIC : CDS_DYNAMIC_ARCHIVE_MAGIC)) {
|
|
+#else
|
|
if (dynamic_header->magic() != CDS_DYNAMIC_ARCHIVE_MAGIC) {
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
delete header;
|
|
os::close(fd);
|
|
vm_exit_during_initialization("Not a top shared archive", archive_name);
|
|
diff --git a/hotspot/src/share/vm/memory/filemap.hpp b/hotspot/src/share/vm/memory/filemap.hpp
|
|
index f6cf43a64..c246f0367 100644
|
|
--- a/hotspot/src/share/vm/memory/filemap.hpp
|
|
+++ b/hotspot/src/share/vm/memory/filemap.hpp
|
|
@@ -41,6 +41,7 @@
|
|
|
|
#define CDS_ARCHIVE_MAGIC 0xf00baba2
|
|
#define CDS_DYNAMIC_ARCHIVE_MAGIC 0xf00baba8
|
|
+#define CDS_AGGRESSIVE_ARCHIVE_MAGIC 0xf00baba4
|
|
|
|
static const int JVM_IDENT_MAX = 256;
|
|
|
|
@@ -168,6 +169,9 @@ public:
|
|
struct DynamicArchiveHeader : FileMapHeader {
|
|
private:
|
|
int _base_header_crc;
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ int _program_crc;
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
int _base_region_crc[MetaspaceShared::n_regions];
|
|
char* _requested_base_address; // Archive relocation is not necessary if we map with this base address.
|
|
size_t _ptrmap_size_in_bits; // Size of pointer relocation bitmap
|
|
@@ -186,6 +190,11 @@ public:
|
|
_base_region_crc[i] = c;
|
|
}
|
|
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ int program_crc() const { return _program_crc; }
|
|
+ void set_program_crc(int c) { _program_crc = c; }
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
+
|
|
void set_requested_base(char* b) {
|
|
_requested_base_address = b;
|
|
}
|
|
@@ -199,6 +208,8 @@ public:
|
|
char* serialized_data() const { return from_mapped_offset(_serialized_data_offset); }
|
|
|
|
virtual bool validate();
|
|
+
|
|
+ static int get_current_program_crc();
|
|
};
|
|
|
|
FileMapHeader * _header;
|
|
diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp
|
|
index 55667ac32..2cc38cf66 100644
|
|
--- a/hotspot/src/share/vm/prims/jvm.cpp
|
|
+++ b/hotspot/src/share/vm/prims/jvm.cpp
|
|
@@ -3321,6 +3321,36 @@ JVM_ENTRY(jint, JVM_AdaptiveHeapGetG1PeriodicGCLoadThreshold(JNIEnv *env, jclass
|
|
#endif
|
|
JVM_END
|
|
|
|
+JVM_ENTRY(jclass, JVM_DefineTrustedSharedClass(JNIEnv *env, const char *name, jobject loader))
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ assert(UseAggressiveCDS, "sanity");
|
|
+
|
|
+ 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.
|
|
+ THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name);
|
|
+ }
|
|
+ class_name = SymbolTable::new_symbol(name, str_len, CHECK_NULL);
|
|
+ }
|
|
+
|
|
+ ResourceMark rm(THREAD);
|
|
+ Handle class_loader (THREAD, JNIHandles::resolve(loader));
|
|
+ InstanceKlass* k = SystemDictionaryShared::lookup_trusted_share_class(class_name,
|
|
+ class_loader,
|
|
+ CHECK_NULL);
|
|
+ if (k == NULL) {
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ return (jclass) JNIHandles::make_local(THREAD, k->java_mirror());
|
|
+#else
|
|
+ return NULL;
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
+JVM_END
|
|
+
|
|
JVM_ENTRY(void, JVM_Yield(JNIEnv *env, jclass threadClass))
|
|
JVMWrapper("JVM_Yield");
|
|
if (os::dont_yield()) return;
|
|
diff --git a/hotspot/src/share/vm/prims/jvm.h b/hotspot/src/share/vm/prims/jvm.h
|
|
index 0f22f7b12..46a65604c 100644
|
|
--- a/hotspot/src/share/vm/prims/jvm.h
|
|
+++ b/hotspot/src/share/vm/prims/jvm.h
|
|
@@ -1598,6 +1598,12 @@ JNIEXPORT jint JNICALL
|
|
JVM_AdaptiveHeapGetG1PeriodicGCLoadThreshold(JNIEnv *env, jclass clazz);
|
|
|
|
|
|
+/**
|
|
+ * Define the trusted shared class.
|
|
+ */
|
|
+JNIEXPORT jclass JNICALL
|
|
+JVM_DefineTrustedSharedClass(JNIEnv *env, const char *name, jobject loader);
|
|
+
|
|
/* =========================================================================
|
|
* The following defines a private JVM interface that the JDK can query
|
|
* for the JVM version and capabilities. sun.misc.Version defines
|
|
diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp
|
|
index 45fbc1423..557695791 100644
|
|
--- a/hotspot/src/share/vm/runtime/arguments.cpp
|
|
+++ b/hotspot/src/share/vm/runtime/arguments.cpp
|
|
@@ -4356,6 +4356,11 @@ jint Arguments::apply_ergo() {
|
|
|
|
ArgumentsExt::set_gc_specific_flags();
|
|
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ result = init_aggressive_cds_properties();
|
|
+ if (result != JNI_OK) return result;
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
+
|
|
// Initialize Metaspace flags and alignments.
|
|
Metaspace::ergo_initialize();
|
|
|
|
@@ -4640,3 +4645,14 @@ bool Arguments::copy_expand_pid(const char* src, size_t srclen,
|
|
*b = '\0';
|
|
return (p == src_end); // return false if not all of the source was copied
|
|
}
|
|
+
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+jint Arguments::init_aggressive_cds_properties() {
|
|
+ if (!is_dumping_archive() && SharedDynamicArchivePath != NULL && UseAggressiveCDS) {
|
|
+ bool added = false;
|
|
+ added = add_property("jdk.jbooster.aggressivecds.load=true");
|
|
+ if (!added) return JNI_ENOMEM;
|
|
+ }
|
|
+ return JNI_OK;
|
|
+}
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
\ No newline at end of file
|
|
diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp
|
|
index 4f7232e48..fdd1d14b0 100644
|
|
--- a/hotspot/src/share/vm/runtime/arguments.hpp
|
|
+++ b/hotspot/src/share/vm/runtime/arguments.hpp
|
|
@@ -576,6 +576,10 @@ class Arguments : AllStatic {
|
|
assert(Arguments::is_dumping_archive(), "dump time only");
|
|
}
|
|
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+ static jint init_aggressive_cds_properties();
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
+
|
|
static bool CompileMethod(char* className, char* methodName) {
|
|
return
|
|
methodExists(
|
|
diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp
|
|
index 77a4ff0b2..6aa53d2d2 100644
|
|
--- a/hotspot/src/share/vm/runtime/globals.hpp
|
|
+++ b/hotspot/src/share/vm/runtime/globals.hpp
|
|
@@ -4119,6 +4119,14 @@ class CommandLineFlags {
|
|
product(bool, UseAppCDS, false, \
|
|
"Enable Application Class Data Sharing (AppCDS)") \
|
|
\
|
|
+ experimental(bool, UseAggressiveCDS, false, \
|
|
+ "An aggressive stratage to improve start-up " \
|
|
+ "because we avoid decoding the classfile.") \
|
|
+ \
|
|
+ experimental(bool, CheckClassFileTimeStamp, true, \
|
|
+ "Check whether the modification time of the" \
|
|
+ "class file is changed during UseAggressiveCDS.") \
|
|
+ \
|
|
product(bool, EnableSplitVerifierForAppCDS, false, \
|
|
"Enable Type Check (AppCDS)") \
|
|
\
|
|
diff --git a/hotspot/src/share/vm/utilities/macros.hpp b/hotspot/src/share/vm/utilities/macros.hpp
|
|
index 599e1074d..f631c94c4 100644
|
|
--- a/hotspot/src/share/vm/utilities/macros.hpp
|
|
+++ b/hotspot/src/share/vm/utilities/macros.hpp
|
|
@@ -106,6 +106,7 @@
|
|
|
|
#ifndef INCLUDE_CDS
|
|
#define INCLUDE_CDS 1
|
|
+#define INCLUDE_AGGRESSIVE_CDS 1
|
|
#endif
|
|
|
|
#if INCLUDE_CDS
|
|
@@ -120,6 +121,14 @@
|
|
#define NOT_CDS_RETURN_(code) { return code; }
|
|
#endif // INCLUDE_CDS
|
|
|
|
+#if INCLUDE_AGGRESSIVE_CDS
|
|
+#define AGGRESSIVE_CDS_ONLY(x) x
|
|
+#define NOT_AGGRESSIVE_CDS(x)
|
|
+#else
|
|
+#define AGGRESSIVE_CDS_ONLY(x)
|
|
+#define NOT_AGGRESSIVE_CDS(x) x
|
|
+#endif // INCLUDE_AGGRESSIVE_CDS
|
|
+
|
|
#ifndef INCLUDE_MANAGEMENT
|
|
#define INCLUDE_MANAGEMENT 1
|
|
#endif // INCLUDE_MANAGEMENT
|
|
diff --git a/jdk/make/mapfiles/libjava/mapfile-linux b/jdk/make/mapfiles/libjava/mapfile-linux
|
|
index ae118af70..61ec28513 100644
|
|
--- a/jdk/make/mapfiles/libjava/mapfile-linux
|
|
+++ b/jdk/make/mapfiles/libjava/mapfile-linux
|
|
@@ -129,6 +129,7 @@ SUNWprivate_1.1 {
|
|
Java_java_lang_ClassLoader_defineClass0;
|
|
Java_java_lang_ClassLoader_defineClass1;
|
|
Java_java_lang_ClassLoader_defineClass2;
|
|
+ Java_java_lang_ClassLoader_defineClass3;
|
|
Java_java_lang_ClassLoader_findBuiltinLib;
|
|
Java_java_lang_ClassLoader_findLoadedClass0;
|
|
Java_java_lang_ClassLoader_resolveClass0;
|
|
diff --git a/jdk/make/mapfiles/libjava/mapfile-vers b/jdk/make/mapfiles/libjava/mapfile-vers
|
|
index 896db04f2..abfde04a9 100644
|
|
--- a/jdk/make/mapfiles/libjava/mapfile-vers
|
|
+++ b/jdk/make/mapfiles/libjava/mapfile-vers
|
|
@@ -129,6 +129,7 @@ SUNWprivate_1.1 {
|
|
Java_java_lang_ClassLoader_defineClass0;
|
|
Java_java_lang_ClassLoader_defineClass1;
|
|
Java_java_lang_ClassLoader_defineClass2;
|
|
+ Java_java_lang_ClassLoader_defineClass3;
|
|
Java_java_lang_ClassLoader_findBuiltinLib;
|
|
Java_java_lang_ClassLoader_findLoadedClass0;
|
|
Java_java_lang_ClassLoader_resolveClass0;
|
|
diff --git a/jdk/src/share/classes/java/lang/ClassLoader.java b/jdk/src/share/classes/java/lang/ClassLoader.java
|
|
index f305c1e36..d659eff0f 100644
|
|
--- a/jdk/src/share/classes/java/lang/ClassLoader.java
|
|
+++ b/jdk/src/share/classes/java/lang/ClassLoader.java
|
|
@@ -682,6 +682,20 @@ public abstract class ClassLoader {
|
|
}
|
|
}
|
|
|
|
+ /**
|
|
+ * Determine protection domain, and check it.
|
|
+ * This method is only for AggressiveCDS.
|
|
+ *
|
|
+ * @param name the name of the class
|
|
+ * @param c the class
|
|
+ * @param pd the ProtectionDomain of the class
|
|
+ */
|
|
+ private void defineClassProtectionDomain(String name, Class<?> c, ProtectionDomain pd)
|
|
+ {
|
|
+ pd = preDefineClass(name, pd);
|
|
+ postDefineClass(c, pd);
|
|
+ }
|
|
+
|
|
/**
|
|
* Converts an array of bytes into an instance of class <tt>Class</tt>,
|
|
* with an optional <tt>ProtectionDomain</tt>. If the domain is
|
|
@@ -857,6 +871,27 @@ public abstract class ClassLoader {
|
|
int off, int len, ProtectionDomain pd,
|
|
String source);
|
|
|
|
+ /**
|
|
+ * This method is only invoked when java.net.AggressiveCDSPlugin enabled.
|
|
+ */
|
|
+ private native Class<?> defineClass3(String name);
|
|
+
|
|
+ protected final Class<?> defineClass(String name) {
|
|
+ Class<?> trustedClass = defineClass3(name);
|
|
+ if (trustedClass != null) {
|
|
+ ProtectionDomain pd = AccessController.doPrivileged(
|
|
+ new PrivilegedAction<ProtectionDomain>() {
|
|
+ @Override
|
|
+ public ProtectionDomain run() {
|
|
+ return trustedClass.getProtectionDomain();
|
|
+ }
|
|
+ }
|
|
+ );
|
|
+ defineClassProtectionDomain(name, trustedClass, pd);
|
|
+ }
|
|
+ return trustedClass;
|
|
+ }
|
|
+
|
|
// true if the name is null or has the potential to be a valid binary name
|
|
private boolean checkName(String name) {
|
|
if ((name == null) || (name.length() == 0))
|
|
diff --git a/jdk/src/share/classes/java/net/AggressiveCDSPlugin.java b/jdk/src/share/classes/java/net/AggressiveCDSPlugin.java
|
|
new file mode 100644
|
|
index 000000000..90d1cd78a
|
|
--- /dev/null
|
|
+++ b/jdk/src/share/classes/java/net/AggressiveCDSPlugin.java
|
|
@@ -0,0 +1,45 @@
|
|
+/*
|
|
+ * Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved.
|
|
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
+ *
|
|
+ * This code is free software; you can redistribute it and/or modify it
|
|
+ * under the terms of the GNU General Public License version 2 only, as
|
|
+ * published by the Free Software Foundation.
|
|
+ *
|
|
+ * This code is distributed in the hope that it will be useful, but WITHOUT
|
|
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
+ * version 2 for more details (a copy is included in the LICENSE file that
|
|
+ * accompanied this code).
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License version
|
|
+ * 2 along with this work; if not, write to the Free Software Foundation,
|
|
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
+ *
|
|
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
+ * or visit www.oracle.com if you need additional information or have any
|
|
+ * questions.
|
|
+ */
|
|
+
|
|
+package java.net;
|
|
+
|
|
+import java.security.AccessController;
|
|
+import sun.security.action.GetBooleanAction;
|
|
+
|
|
+/**
|
|
+ * The Aggressive CDS plugin for {@link java.net.URLClassLoader}.
|
|
+ */
|
|
+final class AggressiveCDSPlugin {
|
|
+ private static final boolean IS_ENABLED =
|
|
+ AccessController.doPrivileged(
|
|
+ new GetBooleanAction("jdk.jbooster.aggressivecds.load"));
|
|
+
|
|
+ /**
|
|
+ * Check whether Aggressive CDS is enabled.
|
|
+ *
|
|
+ * @return Is Aggressive CDS enabled
|
|
+ */
|
|
+ public static boolean isEnabled() {
|
|
+ return IS_ENABLED;
|
|
+ }
|
|
+}
|
|
\ No newline at end of file
|
|
diff --git a/jdk/src/share/classes/java/net/URLClassLoader.java b/jdk/src/share/classes/java/net/URLClassLoader.java
|
|
index 876a88842..495964ee7 100644
|
|
--- a/jdk/src/share/classes/java/net/URLClassLoader.java
|
|
+++ b/jdk/src/share/classes/java/net/URLClassLoader.java
|
|
@@ -382,6 +382,17 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
|
|
result = AccessController.doPrivileged(
|
|
new PrivilegedExceptionAction<Class<?>>() {
|
|
public Class<?> run() throws ClassNotFoundException {
|
|
+ if (AggressiveCDSPlugin.isEnabled()) {
|
|
+ Class<?> trustedClass = defineClass(name);
|
|
+ if (trustedClass != null) {
|
|
+ int i = name.lastIndexOf('.');
|
|
+ if (i != -1) {
|
|
+ String pkgname = name.substring(0, i);
|
|
+ definePackageInternal(pkgname, null, null);
|
|
+ }
|
|
+ return trustedClass;
|
|
+ }
|
|
+ }
|
|
String path = name.replace('.', '/').concat(".class");
|
|
Resource res = ucp.getResource(path, false);
|
|
if (res != null) {
|
|
@@ -409,6 +420,22 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
|
|
return result;
|
|
}
|
|
|
|
+ /**
|
|
+ * get ProtectionDomain By URL String.
|
|
+ * This method is invoked only in C++ for AggressiveCDS.
|
|
+ *
|
|
+ * @param urlNoFragString the URL String.
|
|
+ *
|
|
+ * @return ProtectionDomain create from URL.
|
|
+ */
|
|
+ protected ProtectionDomain getProtectionDomainByURLString(String urlNoFragString) {
|
|
+ URL url = ucp.getURL(urlNoFragString);
|
|
+ if (url != null) {
|
|
+ return getProtectionDomainFromURL(url);
|
|
+ }
|
|
+ return null;
|
|
+ }
|
|
+
|
|
/*
|
|
* Retrieve the package using the specified package name.
|
|
* If non-null, verify the package using the specified code
|
|
diff --git a/jdk/src/share/classes/java/security/ProtectionDomain.java b/jdk/src/share/classes/java/security/ProtectionDomain.java
|
|
index 7a86115e2..727dc4427 100644
|
|
--- a/jdk/src/share/classes/java/security/ProtectionDomain.java
|
|
+++ b/jdk/src/share/classes/java/security/ProtectionDomain.java
|
|
@@ -25,6 +25,7 @@
|
|
|
|
package java.security;
|
|
|
|
+import java.net.URL;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.Enumeration;
|
|
@@ -35,6 +36,7 @@ import sun.misc.JavaSecurityAccess;
|
|
import sun.misc.JavaSecurityProtectionDomainAccess;
|
|
import static sun.misc.JavaSecurityProtectionDomainAccess.ProtectionDomainCache;
|
|
import sun.misc.SharedSecrets;
|
|
+import sun.net.util.URLUtil;
|
|
import sun.security.util.Debug;
|
|
import sun.security.util.SecurityConstants;
|
|
|
|
@@ -206,6 +208,20 @@ public class ProtectionDomain {
|
|
return this.codesource;
|
|
}
|
|
|
|
+ /**
|
|
+ * Returns a URL String.
|
|
+ *
|
|
+ * @return URL String.
|
|
+ */
|
|
+ public String getLocationNoFragString() {
|
|
+ if (codesource != null) {
|
|
+ URL url = codesource.getLocation();
|
|
+ if (url != null) {
|
|
+ return URLUtil.urlNoFragString(url);
|
|
+ }
|
|
+ }
|
|
+ return null;
|
|
+ }
|
|
|
|
/**
|
|
* Returns the ClassLoader of this domain.
|
|
diff --git a/jdk/src/share/classes/java/security/SecureClassLoader.java b/jdk/src/share/classes/java/security/SecureClassLoader.java
|
|
index cb5f017ba..4b0570104 100644
|
|
--- a/jdk/src/share/classes/java/security/SecureClassLoader.java
|
|
+++ b/jdk/src/share/classes/java/security/SecureClassLoader.java
|
|
@@ -215,6 +215,18 @@ public class SecureClassLoader extends ClassLoader {
|
|
return pd;
|
|
}
|
|
|
|
+ /**
|
|
+ * get ProtectionDomain From URL.
|
|
+ * This method is only for AggressiveCDS.
|
|
+ *
|
|
+ * @param url the URL.
|
|
+ *
|
|
+ * @return ProtectionDomain create from URL.
|
|
+ */
|
|
+ protected ProtectionDomain getProtectionDomainFromURL(URL url) {
|
|
+ CodeSource cs = new CodeSource(url, (CodeSigner[]) null);
|
|
+ return getProtectionDomain(cs);
|
|
+ }
|
|
|
|
/*
|
|
* Check to make sure the class loader has been initialized.
|
|
diff --git a/jdk/src/share/classes/sun/misc/URLClassPath.java b/jdk/src/share/classes/sun/misc/URLClassPath.java
|
|
index 70a194f50..6b4987cf3 100644
|
|
--- a/jdk/src/share/classes/sun/misc/URLClassPath.java
|
|
+++ b/jdk/src/share/classes/sun/misc/URLClassPath.java
|
|
@@ -255,6 +255,24 @@ public class URLClassPath {
|
|
return null;
|
|
}
|
|
|
|
+ /**
|
|
+ * Finds the URL which has the specified name.
|
|
+ * This method is only for AggressiveCDS.
|
|
+ *
|
|
+ * @param urlNoFragString the name of URL
|
|
+ * @return the URL, or null if not found
|
|
+ */
|
|
+ public URL getURL(String urlNoFragString) {
|
|
+ if (!urls.isEmpty()) {
|
|
+ int index = loaders.size();
|
|
+ while(getLoader(index) != null) {
|
|
+ index++;
|
|
+ }
|
|
+ }
|
|
+ Loader loader = lmap.get(urlNoFragString);
|
|
+ return loader != null ? loader.getBaseURL() : null;
|
|
+ }
|
|
+
|
|
/**
|
|
* Finds all resources on the URL search path with the given name.
|
|
* Returns an enumeration of the URL objects.
|
|
diff --git a/jdk/src/share/javavm/export/jvm.h b/jdk/src/share/javavm/export/jvm.h
|
|
index d27055622..c37f2ad34 100644
|
|
--- a/jdk/src/share/javavm/export/jvm.h
|
|
+++ b/jdk/src/share/javavm/export/jvm.h
|
|
@@ -1441,6 +1441,11 @@ JVM_AdaptiveHeapSetG1PeriodicGCLoadThreshold(JNIEnv *env, jclass clazz, jint loa
|
|
JNIEXPORT jint JNICALL
|
|
JVM_AdaptiveHeapGetG1PeriodicGCLoadThreshold(JNIEnv *env, jclass clazz);
|
|
|
|
+/**
|
|
+ * Define the trusted shared class.
|
|
+ */
|
|
+JNIEXPORT jclass JNICALL
|
|
+JVM_DefineTrustedSharedClass(JNIEnv *env, const char *name, jobject loader);
|
|
|
|
/* =========================================================================
|
|
* The following defines a private JVM interface that the JDK can query
|
|
diff --git a/jdk/src/share/native/java/lang/ClassLoader.c b/jdk/src/share/native/java/lang/ClassLoader.c
|
|
index 40b0b85bc..a5515f72f 100644
|
|
--- a/jdk/src/share/native/java/lang/ClassLoader.c
|
|
+++ b/jdk/src/share/native/java/lang/ClassLoader.c
|
|
@@ -224,6 +224,31 @@ Java_java_lang_ClassLoader_defineClass2(JNIEnv *env,
|
|
return result;
|
|
}
|
|
|
|
+JNIEXPORT jclass JNICALL
|
|
+Java_java_lang_ClassLoader_defineClass3(JNIEnv *env,
|
|
+ jobject loader,
|
|
+ jstring name)
|
|
+{
|
|
+ char *utfName;
|
|
+ jclass result = 0;
|
|
+ char buf[128];
|
|
+
|
|
+ if (name != NULL) {
|
|
+ utfName = getUTF(env, name, buf, sizeof(buf));
|
|
+ if (utfName == NULL) {
|
|
+ JNU_ThrowOutOfMemoryError(env, NULL);
|
|
+ return result;
|
|
+ }
|
|
+ VerifyFixClassname(utfName);
|
|
+ } else {
|
|
+ utfName = NULL;
|
|
+ }
|
|
+
|
|
+ result = JVM_DefineTrustedSharedClass(env, utfName, loader);
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
JNIEXPORT void JNICALL
|
|
Java_java_lang_ClassLoader_resolveClass0(JNIEnv *env, jobject this,
|
|
jclass cls)
|
|
--
|
|
2.23.0
|
|
|