Projects
openEuler:24.03:SP1:Everything
openjdk-1.8.0
_service:tar_scm:Huawei-Add-Aggressive-CDS.patch
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:Huawei-Add-Aggressive-CDS.patch of Package openjdk-1.8.0
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
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2