< prev index next >
src/hotspot/share/classfile/systemDictionaryShared.cpp
Print this page
*** 34,54 ****
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/systemDictionaryShared.hpp"
#include "classfile/verificationType.hpp"
#include "classfile/vmSymbols.hpp"
#include "logging/log.hpp"
#include "memory/allocation.hpp"
#include "memory/archiveUtils.hpp"
#include "memory/filemap.hpp"
#include "memory/heapShared.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/metaspaceClosure.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
- #include "memory/dynamicArchive.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klass.inline.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp"
#include "oops/typeArrayOop.inline.hpp"
--- 34,55 ----
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/systemDictionaryShared.hpp"
#include "classfile/verificationType.hpp"
#include "classfile/vmSymbols.hpp"
+ #include "jfr/jfrEvents.hpp"
#include "logging/log.hpp"
#include "memory/allocation.hpp"
#include "memory/archiveUtils.hpp"
+ #include "memory/dynamicArchive.hpp"
#include "memory/filemap.hpp"
#include "memory/heapShared.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/metaspaceClosure.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klass.inline.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp"
#include "oops/typeArrayOop.inline.hpp"
*** 99,108 ****
--- 100,110 ----
int _id;
int _clsfile_size;
int _clsfile_crc32;
GrowableArray<DTVerifierConstraint>* _verifier_constraints;
GrowableArray<char>* _verifier_constraint_flags;
+ bool _is_archived_lambda_proxy;
GrowableArray<DTLoaderConstraint>* _loader_constraints;
DumpTimeSharedClassInfo() {
_klass = NULL;
_failed_verification = false;
*** 110,119 ****
--- 112,122 ----
_clsfile_size = -1;
_clsfile_crc32 = -1;
_excluded = false;
_verifier_constraints = NULL;
_verifier_constraint_flags = NULL;
+ _is_archived_lambda_proxy = false;
_loader_constraints = NULL;
}
void add_verification_constraint(InstanceKlass* k, Symbol* name,
Symbol* from_name, bool from_field_is_protected, bool from_is_array, bool from_is_object);
*** 240,249 ****
--- 243,404 ----
return _unregistered_count;
}
}
};
+ class LambdaProxyClassKey {
+ template <typename T> static void original_to_target(T& field) {
+ if (field != NULL) {
+ field = DynamicArchive::original_to_target(field);
+ ArchivePtrMarker::mark_pointer(&field);
+ }
+ }
+
+ InstanceKlass* _caller_ik;
+ Symbol* _invoked_name;
+ Symbol* _invoked_type;
+ Symbol* _method_type;
+ Method* _member_method;
+ Symbol* _instantiated_method_type;
+
+ public:
+ LambdaProxyClassKey(InstanceKlass* caller_ik,
+ Symbol* invoked_name,
+ Symbol* invoked_type,
+ Symbol* method_type,
+ Method* member_method,
+ Symbol* instantiated_method_type) :
+ _caller_ik(caller_ik),
+ _invoked_name(invoked_name),
+ _invoked_type(invoked_type),
+ _method_type(method_type),
+ _member_method(member_method),
+ _instantiated_method_type(instantiated_method_type) {}
+
+ void original_to_target() {
+ original_to_target(_caller_ik);
+ original_to_target(_instantiated_method_type);
+ original_to_target(_invoked_name);
+ original_to_target(_invoked_type);
+ original_to_target(_member_method);
+ original_to_target(_method_type);
+ }
+
+ bool equals(LambdaProxyClassKey const& other) const {
+ return _caller_ik == other._caller_ik &&
+ _invoked_name == other._invoked_name &&
+ _invoked_type == other._invoked_type &&
+ _method_type == other._method_type &&
+ _member_method == other._member_method &&
+ _instantiated_method_type == other._instantiated_method_type;
+ }
+
+ unsigned int hash() const {
+ return SystemDictionaryShared::hash_for_shared_dictionary(_caller_ik) +
+ SystemDictionaryShared::hash_for_shared_dictionary(_invoked_name) +
+ SystemDictionaryShared::hash_for_shared_dictionary(_invoked_type) +
+ SystemDictionaryShared::hash_for_shared_dictionary(_method_type) +
+ SystemDictionaryShared::hash_for_shared_dictionary(_instantiated_method_type);
+ }
+
+ unsigned int dumptime_hash() const {
+ return primitive_hash<InstanceKlass*>(_caller_ik) +
+ primitive_hash<Symbol*>(_invoked_name) +
+ primitive_hash<Symbol*>(_invoked_type) +
+ primitive_hash<Symbol*>(_method_type) +
+ primitive_hash<Symbol*>(_instantiated_method_type);
+ }
+
+ static inline unsigned int DUMPTIME_HASH(LambdaProxyClassKey const& key) {
+ return (key.dumptime_hash());
+ }
+
+ static inline bool DUMPTIME_EQUALS(
+ LambdaProxyClassKey const& k1, LambdaProxyClassKey const& k2) {
+ return (k1.equals(k2));
+ }
+ };
+
+
+ class DumpTimeLambdaProxyClassInfo {
+ public:
+ GrowableArray<InstanceKlass*>* _proxy_klass;
+ DumpTimeLambdaProxyClassInfo() : _proxy_klass(NULL) {}
+ void add_proxy_klass(InstanceKlass* proxy_klass) {
+ if (_proxy_klass == NULL) {
+ _proxy_klass = new (ResourceObj::C_HEAP, mtInternal)GrowableArray<InstanceKlass*>(5, true);
+ }
+ assert(_proxy_klass != NULL, "sanity");
+ _proxy_klass->append(proxy_klass);
+ }
+ };
+
+ class RunTimeLambdaProxyClassInfo {
+ LambdaProxyClassKey _key;
+ InstanceKlass* _proxy_klass;
+ public:
+ RunTimeLambdaProxyClassInfo(LambdaProxyClassKey key, InstanceKlass* proxy_klass) :
+ _key(key), _proxy_klass(proxy_klass) {}
+
+ InstanceKlass* proxy_klass() const { return _proxy_klass; }
+
+ // Used by LambdaProxyClassDictionary to implement OffsetCompactHashtable::EQUALS
+ static inline bool EQUALS(
+ const RunTimeLambdaProxyClassInfo* value, LambdaProxyClassKey* key, int len_unused) {
+ return (value->_key.equals(*key));
+ }
+ void init(LambdaProxyClassKey& key, DumpTimeLambdaProxyClassInfo& info) {
+ _key = key;
+ _key.original_to_target();
+ _proxy_klass = DynamicArchive::original_to_target(info._proxy_klass->at(0));
+ ArchivePtrMarker::mark_pointer(&_proxy_klass);
+ }
+
+ unsigned int hash() const {
+ return _key.hash();
+ }
+ };
+
+ class LambdaProxyClassDictionary : public OffsetCompactHashtable<
+ LambdaProxyClassKey*,
+ const RunTimeLambdaProxyClassInfo*,
+ RunTimeLambdaProxyClassInfo::EQUALS> {};
+
+ LambdaProxyClassDictionary _lambda_proxy_class_dictionary;
+
+ class DumpTimeLambdaProxyClassDictionary
+ : public ResourceHashtable<LambdaProxyClassKey,
+ DumpTimeLambdaProxyClassInfo,
+ LambdaProxyClassKey::DUMPTIME_HASH,
+ LambdaProxyClassKey::DUMPTIME_EQUALS,
+ 137, // prime number
+ ResourceObj::C_HEAP> {
+ public:
+ int _count;
+ };
+
+ DumpTimeLambdaProxyClassDictionary* _dumptime_lambda_proxy_class_dictionary = NULL;
+
+ static void add_to_dump_time_lambda_proxy_class_dictionary(LambdaProxyClassKey key,
+ InstanceKlass* proxy_klass) {
+ if (_dumptime_lambda_proxy_class_dictionary == NULL) {
+ _dumptime_lambda_proxy_class_dictionary =
+ new (ResourceObj::C_HEAP, mtClass)DumpTimeLambdaProxyClassDictionary();
+ }
+ DumpTimeLambdaProxyClassInfo* lambda_info = _dumptime_lambda_proxy_class_dictionary->get(key);
+ if (lambda_info == NULL) {
+ DumpTimeLambdaProxyClassInfo info;
+ info.add_proxy_klass(proxy_klass);
+ _dumptime_lambda_proxy_class_dictionary->put(key, info);
+ //lambda_info = _dumptime_lambda_proxy_class_dictionary->get(key);
+ //assert(lambda_info->_proxy_klass == proxy_klass, "must be"); // debug only -- remove
+ ++_dumptime_lambda_proxy_class_dictionary->_count;
+ } else {
+ lambda_info->add_proxy_klass(proxy_klass);
+ }
+ }
+
class RunTimeSharedClassInfo {
public:
struct CrcInfo {
int _clsfile_size;
int _clsfile_crc32;
*** 270,279 ****
--- 425,435 ----
InstanceKlass* _klass;
int _num_verifier_constraints;
int _num_loader_constraints;
// optional CrcInfo _crc; (only for UNREGISTERED classes)
+ // optional InstanceKlass* _nest_host
// optional RTLoaderConstraint _loader_constraint_types[_num_loader_constraints]
// optional RTVerifierConstraint _verifier_constraints[_num_verifier_constraints]
// optional char _verifier_constraint_flags[_num_verifier_constraints]
private:
*** 294,321 ****
return sizeof(char) * num_verifier_constraints;
}
static size_t loader_constraints_size(int num_loader_constraints) {
return sizeof(RTLoaderConstraint) * num_loader_constraints;
}
public:
static size_t byte_size(InstanceKlass* klass, int num_verifier_constraints, int num_loader_constraints) {
return header_size_size() +
crc_size(klass) +
loader_constraints_size(num_loader_constraints) +
verifier_constraints_size(num_verifier_constraints) +
verifier_constraint_flags_size(num_verifier_constraints);
}
private:
size_t crc_offset() const {
return header_size_size();
}
! size_t loader_constraints_offset() const {
return crc_offset() + crc_size(_klass);
}
size_t verifier_constraints_offset() const {
return loader_constraints_offset() + loader_constraints_size(_num_loader_constraints);
}
size_t verifier_constraint_flags_offset() const {
return verifier_constraints_offset() + verifier_constraints_size(_num_verifier_constraints);
--- 450,489 ----
return sizeof(char) * num_verifier_constraints;
}
static size_t loader_constraints_size(int num_loader_constraints) {
return sizeof(RTLoaderConstraint) * num_loader_constraints;
}
+ static size_t nest_host_size(InstanceKlass* klass) {
+ if (klass->is_hidden()) {
+ return sizeof(InstanceKlass*);
+ } else {
+ return 0;
+ }
+ }
public:
static size_t byte_size(InstanceKlass* klass, int num_verifier_constraints, int num_loader_constraints) {
return header_size_size() +
crc_size(klass) +
+ nest_host_size(klass) +
loader_constraints_size(num_loader_constraints) +
verifier_constraints_size(num_verifier_constraints) +
verifier_constraint_flags_size(num_verifier_constraints);
}
private:
size_t crc_offset() const {
return header_size_size();
}
! size_t nest_host_offset() const {
return crc_offset() + crc_size(_klass);
}
+
+ size_t loader_constraints_offset() const {
+ return nest_host_offset() + nest_host_size(_klass);
+ }
size_t verifier_constraints_offset() const {
return loader_constraints_offset() + loader_constraints_size(_num_loader_constraints);
}
size_t verifier_constraint_flags_offset() const {
return verifier_constraints_offset() + verifier_constraints_size(_num_verifier_constraints);
*** 346,355 ****
--- 514,535 ----
char* verifier_constraint_flags() {
assert(_num_verifier_constraints > 0, "sanity");
return (char*)(address(this) + verifier_constraint_flags_offset());
}
+ InstanceKlass** nest_host_addr() {
+ assert(_klass->is_hidden(), "sanity");
+ return (InstanceKlass**)(address(this) + nest_host_offset());
+ }
+ InstanceKlass* nest_host() {
+ return *nest_host_addr();
+ }
+ void set_nest_host(InstanceKlass* k) {
+ *nest_host_addr() = k;
+ ArchivePtrMarker::mark_pointer((address*)nest_host_addr());
+ }
+
RTLoaderConstraint* loader_constraints() {
assert(_num_loader_constraints > 0, "sanity");
return (RTLoaderConstraint*)(address(this) + loader_constraints_offset());
}
*** 394,403 ****
--- 574,590 ----
ld_constraints[i]._loader_type1 = info._loader_constraints->at(i)._loader_type1;
ld_constraints[i]._loader_type2 = info._loader_constraints->at(i)._loader_type2;
}
}
if (DynamicDumpSharedSpaces) {
+ if (_klass->is_hidden()) {
+ Thread* THREAD = Thread::current();
+ InstanceKlass* n_h = _klass->nest_host(THREAD);
+ n_h = DynamicArchive::original_to_target(n_h);
+ set_nest_host(n_h);
+ ArchivePtrMarker::mark_pointer(&n_h);
+ }
_klass = DynamicArchive::original_to_target(info._klass);
}
ArchivePtrMarker::mark_pointer(&_klass);
}
*** 424,433 ****
--- 611,621 ----
return &((RunTimeSharedClassInfo**)klass)[-1];
}
public:
static RunTimeSharedClassInfo* get_for(InstanceKlass* klass) {
+ assert(klass->is_shared(), "don't call for non-shared class");
return *info_pointer_addr(klass);
}
static void set_for(InstanceKlass* klass, RunTimeSharedClassInfo* record) {
if (DynamicDumpSharedSpaces) {
klass = DynamicArchive::original_to_buffer(klass);
*** 1149,1177 ****
k = k->java_super();
}
return false;
}
void SystemDictionaryShared::warn_excluded(InstanceKlass* k, const char* reason) {
ResourceMark rm;
log_warning(cds)("Skipping %s: %s", k->name()->as_C_string(), reason);
}
bool SystemDictionaryShared::should_be_excluded(InstanceKlass* k) {
! if (k->is_hidden() || k->is_unsafe_anonymous()) {
! warn_excluded(k, "Hidden or Unsafe anonymous class");
! return true; // hidden and unsafe anonymous classes are not archived, skip
}
if (k->is_in_error_state()) {
warn_excluded(k, "In error state");
return true;
}
if (k->has_been_redefined()) {
warn_excluded(k, "Has been redefined");
return true;
}
! if (k->shared_classpath_index() < 0 && is_builtin(k)) {
// These are classes loaded from unsupported locations (such as those loaded by JVMTI native
// agent during dump time).
warn_excluded(k, "Unsupported location");
return true;
}
--- 1337,1392 ----
k = k->java_super();
}
return false;
}
+ bool SystemDictionaryShared::is_registered_lambda_proxy_class(InstanceKlass* ik) {
+ DumpTimeSharedClassInfo* info = _dumptime_table->get(ik);
+ return (info != NULL) ? info->_is_archived_lambda_proxy && !ik->is_non_strong_hidden() : false;
+ }
+
+ bool SystemDictionaryShared::is_in_shared_lambda_proxy_table(InstanceKlass* ik) {
+ assert(!DumpSharedSpaces && UseSharedSpaces, "called at run time with CDS enabled only");
+ RunTimeSharedClassInfo* record = RunTimeSharedClassInfo::get_for(ik);
+ if (record != NULL && record->nest_host() != NULL) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ bool SystemDictionaryShared::is_hidden_lambda_proxy(InstanceKlass* ik) {
+ assert(ik->is_shared(), "applicable to only a shared class");
+ if (ik->is_hidden()) {
+ assert(is_in_shared_lambda_proxy_table(ik), "we don't archive other hidden classes");
+ return true;
+ } else {
+ return false;
+ }
+ }
+
void SystemDictionaryShared::warn_excluded(InstanceKlass* k, const char* reason) {
ResourceMark rm;
log_warning(cds)("Skipping %s: %s", k->name()->as_C_string(), reason);
}
bool SystemDictionaryShared::should_be_excluded(InstanceKlass* k) {
!
! if (k->is_unsafe_anonymous()) {
! warn_excluded(k, "Unsafe anonymous class");
! return true; // unsafe anonymous classes are not archived, skip
}
+
if (k->is_in_error_state()) {
warn_excluded(k, "In error state");
return true;
}
if (k->has_been_redefined()) {
warn_excluded(k, "Has been redefined");
return true;
}
! if (!k->is_hidden() && k->shared_classpath_index() < 0 && is_builtin(k)) {
// These are classes loaded from unsupported locations (such as those loaded by JVMTI native
// agent during dump time).
warn_excluded(k, "Unsupported location");
return true;
}
*** 1220,1229 ****
--- 1435,1449 ----
ResourceMark rm;
log_warning(cds)("Skipping %s: super class %s is excluded", k->name()->as_C_string(), super->name()->as_C_string());
return true;
}
+ if (k->is_hidden() && !is_registered_lambda_proxy_class(k)) {
+ warn_excluded(k, "Hidden class");
+ return true;
+ }
+
Array<InstanceKlass*>* interfaces = k->local_interfaces();
int len = interfaces->length();
for (int i = 0; i < len; i++) {
InstanceKlass* intf = interfaces->at(i);
if (should_be_excluded(intf)) {
*** 1242,1253 ****
--- 1462,1477 ----
DumpTimeSharedClassInfo* info = _dumptime_table->get(k);
assert(_no_class_loading_should_happen, "class loading must be disabled");
guarantee(info != NULL, "Class %s must be entered into _dumptime_table", name);
guarantee(!info->is_excluded(), "Should not attempt to archive excluded class %s", name);
if (is_builtin(k)) {
+ if (k->is_hidden()) {
+ assert(is_registered_lambda_proxy_class(k), "unexpected hidden class %s", name);
+ }
guarantee(!k->is_shared_unregistered_class(),
"Class loader type must be set for BUILTIN class %s", name);
+
} else {
guarantee(k->is_shared_unregistered_class(),
"Class loader type must not be set for UNREGISTERED class %s", name);
}
}
*** 1359,1372 ****
c |= from_is_object ? SystemDictionaryShared::FROM_IS_OBJECT : 0;
vcflags_array->append(c);
if (log_is_enabled(Trace, cds, verification)) {
ResourceMark rm;
! log_trace(cds, verification)("add_verification_constraint: %s: %s must be subclass of %s [0x%x]",
k->external_name(), from_name->as_klass_external_name(),
! name->as_klass_external_name(), c);
}
}
static char get_loader_type_by(oop loader) {
assert(SystemDictionary::is_builtin_class_loader(loader), "Must be built-in loader");
if (SystemDictionary::is_boot_class_loader(loader)) {
--- 1583,1720 ----
c |= from_is_object ? SystemDictionaryShared::FROM_IS_OBJECT : 0;
vcflags_array->append(c);
if (log_is_enabled(Trace, cds, verification)) {
ResourceMark rm;
! log_trace(cds, verification)("add_verification_constraint: %s: %s must be subclass of %s [0x%x] array len %d flags len %d",
k->external_name(), from_name->as_klass_external_name(),
! name->as_klass_external_name(), c, vc_array->length(), vcflags_array->length());
! }
! }
!
! void SystemDictionaryShared::add_lambda_proxy_class(InstanceKlass* caller_ik,
! InstanceKlass* lambda_ik,
! Symbol* invoked_name,
! Symbol* invoked_type,
! Symbol* method_type,
! Method* member_method,
! Symbol* instantiated_method_type) {
!
! assert(caller_ik->class_loader() == lambda_ik->class_loader(), "mismatched class loader");
! assert(caller_ik->class_loader_data() == lambda_ik->class_loader_data(), "mismatched class loader data");
!
! MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag);
!
! lambda_ik->assign_class_loader_type();
!
! DumpTimeSharedClassInfo* info = _dumptime_table->get(lambda_ik);
! if (info != NULL) {
! // Set _is_archived_lambda_proxy in DumpTimeSharedClassInfo so that the lambda_ik
! // won't be excluded during dumping of shared archive. See ExcludeDumpTimeSharedClasses.
! info->_is_archived_lambda_proxy = true;
! }
!
! LambdaProxyClassKey key(caller_ik,
! invoked_name,
! invoked_type,
! method_type,
! member_method,
! instantiated_method_type);
! add_to_dump_time_lambda_proxy_class_dictionary(key, lambda_ik);
! }
!
! InstanceKlass* SystemDictionaryShared::get_shared_lambda_proxy_class(InstanceKlass* caller_ik,
! Symbol* invoked_name,
! Symbol* invoked_type,
! Symbol* method_type,
! Method* member_method,
! Symbol* instantiated_method_type) {
! MutexLocker ml(CDSLambda_lock, Mutex::_no_safepoint_check_flag);
! LambdaProxyClassKey key(caller_ik, invoked_name, invoked_type,
! method_type, member_method, instantiated_method_type);
! const RunTimeLambdaProxyClassInfo* info = _lambda_proxy_class_dictionary.lookup(&key, key.hash(), 0);
! InstanceKlass* proxy_klass = NULL;
! if (info != NULL) {
! InstanceKlass* curr_klass = info->proxy_klass();
! InstanceKlass* prev_klass = curr_klass;
! if (curr_klass->lambda_proxy_is_available()) {
! while (curr_klass->next_link() != NULL) {
! prev_klass = curr_klass;
! curr_klass = InstanceKlass::cast(curr_klass->next_link());
! }
! assert(curr_klass->is_hidden(), "must be");
! assert(curr_klass->lambda_proxy_is_available(), "must be");
!
! prev_klass->set_next_link(NULL);
! proxy_klass = curr_klass;
! proxy_klass->clear_lambda_proxy_is_available();
! if (log_is_enabled(Debug, cds)) {
! ResourceMark rm;
! log_debug(cds)("Loaded lambda proxy: %s", proxy_klass->external_name());
! }
! } else {
! if (log_is_enabled(Debug, cds)) {
! ResourceMark rm;
! log_debug(cds)("Used all archived lambda proxy classes for: %s %s%s",
! caller_ik->external_name(), invoked_name->as_C_string(), invoked_type->as_C_string());
! }
! }
! }
! return proxy_klass;
! }
!
! InstanceKlass* SystemDictionaryShared::get_shared_nest_host(InstanceKlass* lambda_ik) {
! assert(!DumpSharedSpaces && UseSharedSpaces, "called at run time with CDS enabled only");
! RunTimeSharedClassInfo* record = RunTimeSharedClassInfo::get_for(lambda_ik);
! return record->nest_host();
! }
!
! InstanceKlass* SystemDictionaryShared::prepare_shared_lambda_proxy_class(InstanceKlass* lambda_ik,
! InstanceKlass* caller_ik,
! bool initialize, TRAPS) {
! Handle class_loader(THREAD, caller_ik->class_loader());
! Handle protection_domain;
! PackageEntry* pkg_entry = get_package_entry_from_class_name(class_loader, caller_ik->name());
! if (caller_ik->class_loader() != NULL) {
! protection_domain = SystemDictionaryShared::init_security_info(class_loader, caller_ik, pkg_entry, CHECK_NULL);
}
+
+ InstanceKlass* shared_nest_host = get_shared_nest_host(lambda_ik);
+ assert(shared_nest_host != NULL, "unexpected NULL _nest_host");
+
+ InstanceKlass* loaded_lambda =
+ SystemDictionary::load_shared_lambda_proxy_class(lambda_ik, class_loader, protection_domain, pkg_entry, CHECK_NULL);
+
+ // Ensures the nest host is the same as the lambda proxy's
+ // nest host recorded at dump time.
+ InstanceKlass* nest_host = caller_ik->nest_host(THREAD);
+ assert(nest_host == shared_nest_host, "mismatched nest host");
+
+ EventClassLoad class_load_start_event;
+ {
+ MutexLocker mu_r(THREAD, Compile_lock);
+
+ // Add to class hierarchy, initialize vtables, and do possible
+ // deoptimizations.
+ SystemDictionary::add_to_hierarchy(loaded_lambda, CHECK_NULL); // No exception, but can block
+ // But, do not add to dictionary.
+ }
+ loaded_lambda->link_class(CHECK_NULL);
+ // notify jvmti
+ if (JvmtiExport::should_post_class_load()) {
+ assert(THREAD->is_Java_thread(), "thread->is_Java_thread()");
+ JvmtiExport::post_class_load((JavaThread *) THREAD, loaded_lambda);
+ }
+ if (class_load_start_event.should_commit()) {
+ SystemDictionary::post_class_load_event(&class_load_start_event, loaded_lambda, ClassLoaderData::class_loader_data(class_loader()));
+ }
+
+ if (initialize) {
+ loaded_lambda->initialize(CHECK_NULL);
+ }
+
+ return loaded_lambda;
}
static char get_loader_type_by(oop loader) {
assert(SystemDictionary::is_builtin_class_loader(loader), "Must be built-in loader");
if (SystemDictionary::is_boot_class_loader(loader)) {
*** 1595,1609 ****
};
size_t SystemDictionaryShared::estimate_size_for_archive() {
EstimateSizeForArchive est;
_dumptime_table->iterate(&est);
! return est.total() +
CompactHashtableWriter::estimate_size(_dumptime_table->count_of(true)) +
CompactHashtableWriter::estimate_size(_dumptime_table->count_of(false));
}
class CopySharedClassInfoToArchive : StackObj {
CompactHashtableWriter* _writer;
bool _is_builtin;
public:
CopySharedClassInfoToArchive(CompactHashtableWriter* writer,
--- 1943,2013 ----
};
size_t SystemDictionaryShared::estimate_size_for_archive() {
EstimateSizeForArchive est;
_dumptime_table->iterate(&est);
! size_t total_size = est.total() +
CompactHashtableWriter::estimate_size(_dumptime_table->count_of(true)) +
CompactHashtableWriter::estimate_size(_dumptime_table->count_of(false));
+ if (_dumptime_lambda_proxy_class_dictionary != NULL) {
+ total_size +=
+ (sizeof(RunTimeLambdaProxyClassInfo) * _dumptime_lambda_proxy_class_dictionary->_count) +
+ CompactHashtableWriter::estimate_size(_dumptime_lambda_proxy_class_dictionary->_count);
+ } else {
+ total_size += CompactHashtableWriter::estimate_size(0);
+ }
+ return total_size;
}
+ class CopyLambdaProxyClassInfoToArchive : StackObj {
+ CompactHashtableWriter* _writer;
+ public:
+ CopyLambdaProxyClassInfoToArchive(CompactHashtableWriter* writer)
+ : _writer(writer) {}
+ bool do_entry(LambdaProxyClassKey& key, DumpTimeLambdaProxyClassInfo& info) {
+ if (SystemDictionaryShared::is_excluded_class(info._proxy_klass->at(0))) {
+ return true;
+ }
+ ResourceMark rm;
+ log_info(cds,dynamic)("Archiving hidden %s", info._proxy_klass->at(0)->external_name());
+ size_t byte_size = sizeof(RunTimeLambdaProxyClassInfo);
+ RunTimeLambdaProxyClassInfo* runtime_info =
+ (RunTimeLambdaProxyClassInfo*)MetaspaceShared::read_only_space_alloc(byte_size);
+ runtime_info->init(key, info);
+ unsigned int hash = runtime_info->hash(); // Fields in runtime_info->_key already point to target space.
+ u4 delta = MetaspaceShared::object_delta_u4(DynamicArchive::buffer_to_target(runtime_info));
+ _writer->add(hash, delta);
+ return true;
+ }
+ };
+
+ class AdjustLambdaProxyClassInfo : StackObj {
+ public:
+ AdjustLambdaProxyClassInfo() {}
+ bool do_entry(LambdaProxyClassKey& key, DumpTimeLambdaProxyClassInfo& info) {
+ if (SystemDictionaryShared::is_excluded_class(info._proxy_klass->at(0))) {
+ return true;
+ }
+ int len = info._proxy_klass->length();
+ if (len > 1) {
+ for (int i = 0; i < len-1; i++) {
+ InstanceKlass* ok0 = info._proxy_klass->at(i+0); // this is original klass
+ InstanceKlass* ok1 = info._proxy_klass->at(i+1); // this is original klass
+ InstanceKlass* bk0 = DynamicArchive::original_to_buffer(ok0);
+ InstanceKlass* bk1 = DynamicArchive::original_to_buffer(ok1);
+ assert(bk0->next_link() == 0, "must be called after Klass::remove_unshareable_info()");
+ assert(bk1->next_link() == 0, "must be called after Klass::remove_unshareable_info()");
+ bk0->set_next_link(bk1);
+ bk1->set_lambda_proxy_is_available();
+ ArchivePtrMarker::mark_pointer(bk0->next_link_addr());
+ }
+ }
+ DynamicArchive::original_to_buffer(info._proxy_klass->at(0))->set_lambda_proxy_is_available();
+ return true;
+ }
+ };
+
class CopySharedClassInfoToArchive : StackObj {
CompactHashtableWriter* _writer;
bool _is_builtin;
public:
CopySharedClassInfoToArchive(CompactHashtableWriter* writer,
*** 1628,1638 ****
--- 2032,2046 ----
if (DynamicDumpSharedSpaces) {
delta = MetaspaceShared::object_delta_u4(DynamicArchive::buffer_to_target(record));
} else {
delta = MetaspaceShared::object_delta_u4(record);
}
+ if (_is_builtin && info._klass->is_hidden()) {
+ // skip
+ } else {
_writer->add(hash, delta);
+ }
if (log_is_enabled(Trace, cds, hashtables)) {
ResourceMark rm;
log_trace(cds,hashtables)("%s dictionary: %s", (_is_builtin ? "builtin" : "unregistered"), info._klass->external_name());
}
*** 1641,1650 ****
--- 2049,2067 ----
}
return true; // keep on iterating
}
};
+ void SystemDictionaryShared::write_lambda_proxy_class_dictionary(LambdaProxyClassDictionary *dictionary) {
+ CompactHashtableStats stats;
+ dictionary->reset();
+ CompactHashtableWriter writer(_dumptime_lambda_proxy_class_dictionary->_count, &stats);
+ CopyLambdaProxyClassInfoToArchive copy(&writer);
+ _dumptime_lambda_proxy_class_dictionary->iterate(©);
+ writer.dump(dictionary, "lambda proxy class dictionary");
+ }
+
void SystemDictionaryShared::write_dictionary(RunTimeSharedDictionary* dictionary,
bool is_builtin,
bool is_static_archive) {
CompactHashtableStats stats;
dictionary->reset();
*** 1660,1679 ****
--- 2077,2107 ----
write_dictionary(&_unregistered_dictionary, false);
} else {
write_dictionary(&_dynamic_builtin_dictionary, true);
write_dictionary(&_dynamic_unregistered_dictionary, false);
}
+ if (_dumptime_lambda_proxy_class_dictionary != NULL) {
+ write_lambda_proxy_class_dictionary(&_lambda_proxy_class_dictionary);
+ }
+ }
+
+ void SystemDictionaryShared::adjust_lambda_proxy_class_dictionary() {
+ if (_dumptime_lambda_proxy_class_dictionary != NULL) {
+ AdjustLambdaProxyClassInfo adjuster;
+ _dumptime_lambda_proxy_class_dictionary->iterate(&adjuster);
+ }
}
void SystemDictionaryShared::serialize_dictionary_headers(SerializeClosure* soc,
bool is_static_archive) {
if (is_static_archive) {
_builtin_dictionary.serialize_header(soc);
_unregistered_dictionary.serialize_header(soc);
} else {
_dynamic_builtin_dictionary.serialize_header(soc);
_dynamic_unregistered_dictionary.serialize_header(soc);
+ _lambda_proxy_class_dictionary.serialize_header(soc);
}
}
void SystemDictionaryShared::serialize_well_known_klasses(SerializeClosure* soc) {
for (int i = FIRST_WKID; i < WKID_LIMIT; i++) {
*** 1704,1713 ****
--- 2132,2142 ----
}
InstanceKlass* SystemDictionaryShared::find_builtin_class(Symbol* name) {
const RunTimeSharedClassInfo* record = find_record(&_builtin_dictionary, &_dynamic_builtin_dictionary, name);
if (record != NULL) {
+ assert(!record->_klass->is_hidden(), "hidden class cannot be looked up by name");
return record->_klass;
} else {
return NULL;
}
}
*** 1728,1746 ****
--- 2157,2197 ----
ResourceMark rm;
_st->print_cr("%4d: %s", (_index++), record->_klass->external_name());
}
};
+ class SharedLambdaDictionaryPrinter : StackObj {
+ outputStream* _st;
+ int _index;
+ public:
+ SharedLambdaDictionaryPrinter(outputStream* st) : _st(st), _index(0) {}
+
+ void do_value(const RunTimeLambdaProxyClassInfo* record) {
+ ResourceMark rm;
+ _st->print_cr("%4d: %s", (_index++), record->proxy_klass()->external_name());
+ Klass* k = record->proxy_klass()->next_link();
+ while (k != NULL) {
+ _st->print_cr("%4d: %s", (_index++), k->external_name());
+ k = k->next_link();
+ }
+ }
+ };
+
void SystemDictionaryShared::print_on(outputStream* st) {
if (UseSharedSpaces) {
st->print_cr("Shared Dictionary");
SharedDictionaryPrinter p(st);
_builtin_dictionary.iterate(&p);
_unregistered_dictionary.iterate(&p);
if (DynamicArchive::is_mapped()) {
_dynamic_builtin_dictionary.iterate(&p);
_unregistered_dictionary.iterate(&p);
+ if (!_lambda_proxy_class_dictionary.empty()) {
+ st->print_cr("Shared Lambda Dictionary");
+ SharedLambdaDictionaryPrinter ldp(st);
+ _lambda_proxy_class_dictionary.iterate(&ldp);
+ }
}
}
}
void SystemDictionaryShared::print_table_statistics(outputStream* st) {
*** 1748,1757 ****
--- 2199,2209 ----
_builtin_dictionary.print_table_statistics(st, "Builtin Shared Dictionary");
_unregistered_dictionary.print_table_statistics(st, "Unregistered Shared Dictionary");
if (DynamicArchive::is_mapped()) {
_dynamic_builtin_dictionary.print_table_statistics(st, "Dynamic Builtin Shared Dictionary");
_dynamic_unregistered_dictionary.print_table_statistics(st, "Unregistered Shared Dictionary");
+ _lambda_proxy_class_dictionary.print_table_statistics(st, "Lambda Shared Dictionary");
}
}
}
bool SystemDictionaryShared::empty_dumptime_table() {
< prev index next >