8341916: Remove ProtectionDomain related hotspot code and tests
Reviewed-by: dholmes, iklam, jrose
This commit is contained in:
parent
5eb0733f5f
commit
dfddbcaab8
@ -170,9 +170,7 @@ void AOTConstantPoolResolver::dumptime_resolve_constants(InstanceKlass* ik, TRAP
|
||||
Klass* AOTConstantPoolResolver::find_loaded_class(Thread* current, oop class_loader, Symbol* name) {
|
||||
HandleMark hm(current);
|
||||
Handle h_loader(current, class_loader);
|
||||
Klass* k = SystemDictionary::find_instance_or_array_klass(current, name,
|
||||
h_loader,
|
||||
Handle());
|
||||
Klass* k = SystemDictionary::find_instance_or_array_klass(current, name, h_loader);
|
||||
if (k != nullptr) {
|
||||
return k;
|
||||
}
|
||||
|
@ -306,7 +306,7 @@ void AOTLinkedClassBulkLoader::load_hidden_class(ClassLoaderData* loader_data, I
|
||||
// use any special ClassLoaderData.
|
||||
Handle loader(THREAD, loader_data->class_loader());
|
||||
ResourceMark rm(THREAD);
|
||||
assert(SystemDictionary::resolve_or_null(ik->name(), loader, pd, THREAD) == nullptr,
|
||||
assert(SystemDictionary::resolve_or_null(ik->name(), loader, THREAD) == nullptr,
|
||||
"hidden classes cannot be accessible by name: %s", ik->external_name());
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
|
@ -612,8 +612,7 @@ void ClassListParser::resolve_indy_impl(Symbol* class_name_symbol, TRAPS) {
|
||||
// resolve the CP entry for the invokedynamic instruction, which may result in
|
||||
// generation of LambdaForm classes.
|
||||
Handle class_loader(THREAD, SystemDictionary::java_system_loader());
|
||||
Handle protection_domain;
|
||||
Klass* klass = SystemDictionary::resolve_or_fail(class_name_symbol, class_loader, protection_domain, true, CHECK);
|
||||
Klass* klass = SystemDictionary::resolve_or_fail(class_name_symbol, class_loader, true, CHECK);
|
||||
if (klass->is_instance_klass()) {
|
||||
InstanceKlass* ik = InstanceKlass::cast(klass);
|
||||
MetaspaceShared::try_link_class(THREAD, ik);
|
||||
@ -781,8 +780,7 @@ InstanceKlass* ClassListParser::lookup_interface_for_current_class(Symbol* inter
|
||||
|
||||
InstanceKlass* ClassListParser::find_builtin_class_helper(JavaThread* current, Symbol* class_name_symbol, oop class_loader_oop) {
|
||||
Handle class_loader(current, class_loader_oop);
|
||||
Handle protection_domain;
|
||||
return SystemDictionary::find_instance_klass(current, class_name_symbol, class_loader, protection_domain);
|
||||
return SystemDictionary::find_instance_klass(current, class_name_symbol, class_loader);
|
||||
}
|
||||
|
||||
InstanceKlass* ClassListParser::find_builtin_class(JavaThread* current, const char* class_name) {
|
||||
|
@ -2436,7 +2436,7 @@ void HeapShared::print_stats() {
|
||||
|
||||
bool HeapShared::is_archived_boot_layer_available(JavaThread* current) {
|
||||
TempNewSymbol klass_name = SymbolTable::new_symbol(ARCHIVED_BOOT_LAYER_CLASS);
|
||||
InstanceKlass* k = SystemDictionary::find_instance_klass(current, klass_name, Handle(), Handle());
|
||||
InstanceKlass* k = SystemDictionary::find_instance_klass(current, klass_name, Handle());
|
||||
if (k == nullptr) {
|
||||
return false;
|
||||
} else {
|
||||
|
@ -462,14 +462,12 @@ ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass,
|
||||
}
|
||||
|
||||
Handle loader;
|
||||
Handle domain;
|
||||
if (accessing_klass != nullptr) {
|
||||
loader = Handle(current, accessing_klass->loader());
|
||||
domain = Handle(current, accessing_klass->protection_domain());
|
||||
}
|
||||
|
||||
Klass* found_klass = require_local ?
|
||||
SystemDictionary::find_instance_or_array_klass(current, sym, loader, domain) :
|
||||
SystemDictionary::find_instance_or_array_klass(current, sym, loader) :
|
||||
SystemDictionary::find_constrained_instance_or_array_klass(current, sym, loader);
|
||||
|
||||
// If we fail to find an array klass, look again for its element type.
|
||||
@ -1611,8 +1609,7 @@ void ciEnv::dump_replay_data_helper(outputStream* out) {
|
||||
GrowableArray<ciMetadata*>* objects = _factory->get_ci_metadata();
|
||||
out->print_cr("# %d ciObject found", objects->length());
|
||||
|
||||
// The very first entry is the InstanceKlass of the root method of the current compilation in order to get the right
|
||||
// protection domain to load subsequent classes during replay compilation.
|
||||
// The very first entry is the InstanceKlass of the root method of the current compilation.
|
||||
ciInstanceKlass::dump_replay_instanceKlass(out, task()->method()->method_holder());
|
||||
|
||||
for (int i = 0; i < objects->length(); i++) {
|
||||
|
@ -114,8 +114,6 @@ class CompileReplay : public StackObj {
|
||||
private:
|
||||
FILE* _stream;
|
||||
Thread* _thread;
|
||||
Handle _protection_domain;
|
||||
bool _protection_domain_initialized;
|
||||
Handle _loader;
|
||||
int _version;
|
||||
|
||||
@ -144,8 +142,6 @@ class CompileReplay : public StackObj {
|
||||
CompileReplay(const char* filename, TRAPS) {
|
||||
_thread = THREAD;
|
||||
_loader = Handle(_thread, SystemDictionary::java_system_loader());
|
||||
_protection_domain = Handle();
|
||||
_protection_domain_initialized = false;
|
||||
|
||||
_stream = os::fopen(filename, "rt");
|
||||
if (_stream == nullptr) {
|
||||
@ -558,7 +554,7 @@ class CompileReplay : public StackObj {
|
||||
if (_iklass != nullptr) {
|
||||
k = (Klass*)_iklass->find_klass(ciSymbol::make(klass_name->as_C_string()))->constant_encoding();
|
||||
} else {
|
||||
k = SystemDictionary::resolve_or_fail(klass_name, _loader, _protection_domain, true, THREAD);
|
||||
k = SystemDictionary::resolve_or_fail(klass_name, _loader, true, THREAD);
|
||||
}
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
oop throwable = PENDING_EXCEPTION;
|
||||
@ -579,7 +575,7 @@ class CompileReplay : public StackObj {
|
||||
// Lookup a klass
|
||||
Klass* resolve_klass(const char* klass, TRAPS) {
|
||||
Symbol* klass_name = SymbolTable::new_symbol(klass);
|
||||
return SystemDictionary::resolve_or_fail(klass_name, _loader, _protection_domain, true, THREAD);
|
||||
return SystemDictionary::resolve_or_fail(klass_name, _loader, true, THREAD);
|
||||
}
|
||||
|
||||
// Parse the standard tuple of <klass> <name> <signature>
|
||||
@ -896,18 +892,6 @@ class CompileReplay : public StackObj {
|
||||
// just load the referenced class
|
||||
Klass* k = parse_klass(CHECK);
|
||||
|
||||
if (_version >= 1) {
|
||||
if (!_protection_domain_initialized && k != nullptr) {
|
||||
assert(_protection_domain() == nullptr, "must be uninitialized");
|
||||
// The first entry is the holder class of the method for which a replay compilation is requested.
|
||||
// Use the same protection domain to load all subsequent classes in order to resolve all classes
|
||||
// in signatures of inlinees. This ensures that inlining can be done as stated in the replay file.
|
||||
_protection_domain = Handle(_thread, k->protection_domain());
|
||||
}
|
||||
|
||||
_protection_domain_initialized = true;
|
||||
}
|
||||
|
||||
if (k == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
@ -822,7 +822,6 @@ void ClassFileParser::parse_interfaces(const ClassFileStream* const stream,
|
||||
interf = SystemDictionary::resolve_super_or_fail(_class_name,
|
||||
unresolved_klass,
|
||||
Handle(THREAD, _loader_data->class_loader()),
|
||||
_protection_domain,
|
||||
false, CHECK);
|
||||
}
|
||||
|
||||
@ -5691,7 +5690,6 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st
|
||||
SystemDictionary::resolve_super_or_fail(_class_name,
|
||||
super_class_name,
|
||||
loader,
|
||||
_protection_domain,
|
||||
true,
|
||||
CHECK);
|
||||
}
|
||||
|
@ -26,26 +26,14 @@
|
||||
#include "cds/cdsConfig.hpp"
|
||||
#include "classfile/classLoaderData.inline.hpp"
|
||||
#include "classfile/dictionary.hpp"
|
||||
#include "classfile/javaClasses.hpp"
|
||||
#include "classfile/protectionDomainCache.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "classfile/vmSymbols.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "logging/logStream.hpp"
|
||||
#include "memory/iterator.hpp"
|
||||
#include "memory/metaspaceClosure.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "memory/universe.hpp"
|
||||
#include "oops/klass.inline.hpp"
|
||||
#include "oops/method.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "oops/oopHandle.inline.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
#include "runtime/javaCalls.hpp"
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
#include "runtime/safepointVerifiers.hpp"
|
||||
#include "oops/instanceKlass.hpp"
|
||||
#include "utilities/concurrentHashTable.inline.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
#include "utilities/ostream.hpp"
|
||||
#include "utilities/tableStatistics.hpp"
|
||||
|
||||
// 2^24 is max size, like StringTable.
|
||||
@ -69,7 +57,7 @@ Dictionary::~Dictionary() {
|
||||
}
|
||||
|
||||
uintx Dictionary::Config::get_hash(Value const& value, bool* is_dead) {
|
||||
return value->instance_klass()->name()->identity_hash();
|
||||
return value->name()->identity_hash();
|
||||
}
|
||||
|
||||
void* Dictionary::Config::allocate_node(void* context, size_t size, Value const& value) {
|
||||
@ -77,26 +65,9 @@ void* Dictionary::Config::allocate_node(void* context, size_t size, Value const&
|
||||
}
|
||||
|
||||
void Dictionary::Config::free_node(void* context, void* memory, Value const& value) {
|
||||
delete value; // Call DictionaryEntry destructor
|
||||
FreeHeap(memory);
|
||||
}
|
||||
|
||||
DictionaryEntry::DictionaryEntry(InstanceKlass* klass) : _instance_klass(klass) {
|
||||
release_set_package_access_cache(nullptr);
|
||||
}
|
||||
|
||||
DictionaryEntry::~DictionaryEntry() {
|
||||
// avoid recursion when deleting linked list
|
||||
// package_access_cache is accessed during a safepoint.
|
||||
// This doesn't require a lock because nothing is reading this
|
||||
// entry anymore. The ClassLoader is dead.
|
||||
while (package_access_cache_acquire() != nullptr) {
|
||||
ProtectionDomainEntry* to_delete = package_access_cache_acquire();
|
||||
release_set_package_access_cache(to_delete->next_acquire());
|
||||
delete to_delete;
|
||||
}
|
||||
}
|
||||
|
||||
const int _resize_load_trigger = 5; // load factor that will trigger the resize
|
||||
|
||||
int Dictionary::table_size() const {
|
||||
@ -108,86 +79,10 @@ bool Dictionary::check_if_needs_resize() {
|
||||
!_table->is_max_size_reached());
|
||||
}
|
||||
|
||||
bool DictionaryEntry::has_package_access_been_granted(Handle protection_domain) {
|
||||
return protection_domain() == nullptr || !java_lang_System::allow_security_manager()
|
||||
? true
|
||||
: is_in_package_access_cache(protection_domain());
|
||||
}
|
||||
|
||||
// Reading the package_access_cache on each DictionaryEntry is lock free and cannot safepoint.
|
||||
// Adding and deleting entries is under the SystemDictionary_lock
|
||||
// Deleting unloaded entries on ClassLoaderData for dictionaries that are not unloaded
|
||||
// is a three step process:
|
||||
// moving the entries to a separate list, handshake to wait for
|
||||
// readers to complete (see NSV here), and then actually deleting the entries.
|
||||
// Deleting entries is done by the ServiceThread when triggered by class unloading.
|
||||
|
||||
bool DictionaryEntry::is_in_package_access_cache(oop protection_domain) const {
|
||||
assert(Thread::current()->is_Java_thread() || SafepointSynchronize::is_at_safepoint(),
|
||||
"can only be called by a JavaThread or at safepoint");
|
||||
// This cannot safepoint while reading the protection domain set.
|
||||
NoSafepointVerifier nsv;
|
||||
#ifdef ASSERT
|
||||
if (protection_domain == instance_klass()->protection_domain()) {
|
||||
// Ensure this doesn't show up in the package_access_cache (invariant)
|
||||
bool in_package_access_cache = false;
|
||||
for (ProtectionDomainEntry* current = package_access_cache_acquire();
|
||||
current != nullptr;
|
||||
current = current->next_acquire()) {
|
||||
if (current->object_no_keepalive() == protection_domain) {
|
||||
in_package_access_cache = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (in_package_access_cache) {
|
||||
assert(false, "A klass's protection domain should not show up "
|
||||
"in its sys. dict. PD set");
|
||||
}
|
||||
}
|
||||
#endif /* ASSERT */
|
||||
|
||||
if (protection_domain == instance_klass()->protection_domain()) {
|
||||
// Succeeds trivially
|
||||
return true;
|
||||
}
|
||||
|
||||
for (ProtectionDomainEntry* current = package_access_cache_acquire();
|
||||
current != nullptr;
|
||||
current = current->next_acquire()) {
|
||||
if (current->object_no_keepalive() == protection_domain) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DictionaryEntry::add_to_package_access_cache(ClassLoaderData* loader_data, Handle protection_domain) {
|
||||
assert_lock_strong(SystemDictionary_lock);
|
||||
if (!is_in_package_access_cache(protection_domain())) {
|
||||
WeakHandle obj = ProtectionDomainCacheTable::add_if_absent(protection_domain);
|
||||
// Additions and deletions hold the SystemDictionary_lock, readers are lock-free
|
||||
ProtectionDomainEntry* new_head = new ProtectionDomainEntry(obj, _package_access_cache);
|
||||
release_set_package_access_cache(new_head);
|
||||
}
|
||||
LogTarget(Trace, protectiondomain) lt;
|
||||
if (lt.is_enabled()) {
|
||||
ResourceMark rm;
|
||||
LogStream ls(lt);
|
||||
ls.print("adding protection domain that can access class %s", instance_klass()->name()->as_C_string());
|
||||
ls.print(" class loader: ");
|
||||
loader_data->class_loader()->print_value_on(&ls);
|
||||
ls.print(" protection domain: ");
|
||||
protection_domain->print_value_on(&ls);
|
||||
ls.print(" ");
|
||||
print_count(&ls);
|
||||
ls.cr();
|
||||
}
|
||||
}
|
||||
|
||||
// Just the classes from defining class loaders
|
||||
void Dictionary::classes_do(void f(InstanceKlass*)) {
|
||||
auto doit = [&] (DictionaryEntry** value) {
|
||||
InstanceKlass* k = (*value)->instance_klass();
|
||||
auto doit = [&] (InstanceKlass** value) {
|
||||
InstanceKlass* k = (*value);
|
||||
if (loader_data() == k->class_loader_data()) {
|
||||
f(k);
|
||||
}
|
||||
@ -199,8 +94,8 @@ void Dictionary::classes_do(void f(InstanceKlass*)) {
|
||||
|
||||
// All classes, and their class loaders, including initiating class loaders
|
||||
void Dictionary::all_entries_do(KlassClosure* closure) {
|
||||
auto all_doit = [&] (DictionaryEntry** value) {
|
||||
InstanceKlass* k = (*value)->instance_klass();
|
||||
auto all_doit = [&] (InstanceKlass** value) {
|
||||
InstanceKlass* k = (*value);
|
||||
closure->do_klass(k);
|
||||
return true;
|
||||
};
|
||||
@ -212,9 +107,8 @@ void Dictionary::all_entries_do(KlassClosure* closure) {
|
||||
void Dictionary::classes_do(MetaspaceClosure* it) {
|
||||
assert(CDSConfig::is_dumping_archive(), "sanity");
|
||||
|
||||
auto push = [&] (DictionaryEntry** value) {
|
||||
InstanceKlass** k = (*value)->instance_klass_addr();
|
||||
it->push(k);
|
||||
auto push = [&] (InstanceKlass** value) {
|
||||
it->push(value);
|
||||
return true;
|
||||
};
|
||||
_table->do_scan(Thread::current(), push);
|
||||
@ -228,26 +122,25 @@ public:
|
||||
uintx get_hash() const {
|
||||
return _name->identity_hash();
|
||||
}
|
||||
bool equals(DictionaryEntry** value) {
|
||||
DictionaryEntry *entry = *value;
|
||||
return (entry->instance_klass()->name() == _name);
|
||||
bool equals(InstanceKlass** value) {
|
||||
InstanceKlass* entry = *value;
|
||||
return (entry->name() == _name);
|
||||
}
|
||||
bool is_dead(DictionaryEntry** value) {
|
||||
bool is_dead(InstanceKlass** value) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// Add a loaded class to the dictionary.
|
||||
void Dictionary::add_klass(JavaThread* current, Symbol* class_name,
|
||||
InstanceKlass* obj) {
|
||||
InstanceKlass* klass) {
|
||||
assert_locked_or_safepoint(SystemDictionary_lock); // doesn't matter now
|
||||
assert(obj != nullptr, "adding nullptr obj");
|
||||
assert(obj->name() == class_name, "sanity check on name");
|
||||
assert(klass != nullptr, "adding nullptr obj");
|
||||
assert(klass->name() == class_name, "sanity check on name");
|
||||
|
||||
DictionaryEntry* entry = new DictionaryEntry(obj);
|
||||
DictionaryLookup lookup(class_name);
|
||||
bool needs_rehashing, clean_hint;
|
||||
bool created = _table->insert(current, lookup, entry, &needs_rehashing, &clean_hint);
|
||||
bool created = _table->insert(current, lookup, klass, &needs_rehashing, &clean_hint);
|
||||
assert(created, "should be because we have a lock");
|
||||
assert (!needs_rehashing, "should never need rehashing");
|
||||
assert(!clean_hint, "no class should be unloaded");
|
||||
@ -277,11 +170,10 @@ void Dictionary::add_klass(JavaThread* current, Symbol* class_name,
|
||||
// Callers should be aware that an entry could be added just after
|
||||
// the table is read here, so the caller will not see the new entry.
|
||||
// The entry may be accessed by the VM thread in verification.
|
||||
DictionaryEntry* Dictionary::get_entry(Thread* current,
|
||||
Symbol* class_name) {
|
||||
InstanceKlass* Dictionary::find_class(Thread* current, Symbol* class_name) {
|
||||
DictionaryLookup lookup(class_name);
|
||||
DictionaryEntry* result = nullptr;
|
||||
auto get = [&] (DictionaryEntry** value) {
|
||||
InstanceKlass* result = nullptr;
|
||||
auto get = [&] (InstanceKlass** value) {
|
||||
// function called if value is found so is never null
|
||||
result = (*value);
|
||||
};
|
||||
@ -291,137 +183,6 @@ DictionaryEntry* Dictionary::get_entry(Thread* current,
|
||||
return result;
|
||||
}
|
||||
|
||||
// If SecurityManager is allowed, return the class ONLY IF the protection_domain has been
|
||||
// granted access to this class by a previous call to Dictionary::check_package_access()
|
||||
InstanceKlass* Dictionary::find(Thread* current, Symbol* name,
|
||||
Handle protection_domain) {
|
||||
NoSafepointVerifier nsv;
|
||||
|
||||
DictionaryEntry* entry = get_entry(current, name);
|
||||
if (entry != nullptr && entry->has_package_access_been_granted(protection_domain)) {
|
||||
return entry->instance_klass();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
InstanceKlass* Dictionary::find_class(Thread* current,
|
||||
Symbol* name) {
|
||||
assert_locked_or_safepoint(SystemDictionary_lock);
|
||||
DictionaryEntry* entry = get_entry(current, name);
|
||||
return (entry != nullptr) ? entry->instance_klass() : nullptr;
|
||||
}
|
||||
|
||||
void Dictionary::add_to_package_access_cache(JavaThread* current,
|
||||
InstanceKlass* klass,
|
||||
Handle protection_domain) {
|
||||
assert(java_lang_System::allow_security_manager(), "only needed if security manager allowed");
|
||||
Symbol* klass_name = klass->name();
|
||||
DictionaryEntry* entry = get_entry(current, klass_name);
|
||||
|
||||
assert(entry != nullptr,"entry must be present, we just created it");
|
||||
assert(protection_domain() != nullptr,
|
||||
"real protection domain should be present");
|
||||
|
||||
entry->add_to_package_access_cache(loader_data(), protection_domain);
|
||||
|
||||
#ifdef ASSERT
|
||||
assert(loader_data() != ClassLoaderData::the_null_class_loader_data(), "doesn't make sense");
|
||||
#endif
|
||||
|
||||
assert(entry->is_in_package_access_cache(protection_domain()),
|
||||
"now protection domain should be present");
|
||||
}
|
||||
|
||||
inline bool Dictionary::is_in_package_access_cache(JavaThread* current,
|
||||
Symbol* name,
|
||||
Handle protection_domain) {
|
||||
DictionaryEntry* entry = get_entry(current, name);
|
||||
return entry->has_package_access_been_granted(protection_domain);
|
||||
}
|
||||
|
||||
void Dictionary::check_package_access(InstanceKlass* klass,
|
||||
Handle class_loader,
|
||||
Handle protection_domain,
|
||||
TRAPS) {
|
||||
|
||||
assert(class_loader() != nullptr, "Should not call this");
|
||||
assert(protection_domain() != nullptr, "Should not call this");
|
||||
}
|
||||
|
||||
// During class loading we may have cached a protection domain that has
|
||||
// since been unreferenced, so this entry should be cleared.
|
||||
void Dictionary::remove_from_package_access_cache(GrowableArray<ProtectionDomainEntry*>* delete_list) {
|
||||
assert(Thread::current()->is_Java_thread(), "only called by JavaThread");
|
||||
assert_lock_strong(SystemDictionary_lock);
|
||||
assert(!loader_data()->has_class_mirror_holder(), "cld should have a ClassLoader holder not a Class holder");
|
||||
|
||||
if (loader_data()->is_the_null_class_loader_data()) {
|
||||
// Classes in the boot loader are not loaded with protection domains
|
||||
return;
|
||||
}
|
||||
|
||||
auto clean_entries = [&] (DictionaryEntry** value) {
|
||||
DictionaryEntry* probe = *value;
|
||||
Klass* e = probe->instance_klass();
|
||||
|
||||
ProtectionDomainEntry* current = probe->package_access_cache_acquire();
|
||||
ProtectionDomainEntry* prev = nullptr;
|
||||
while (current != nullptr) {
|
||||
if (current->object_no_keepalive() == nullptr) {
|
||||
LogTarget(Debug, protectiondomain) lt;
|
||||
if (lt.is_enabled()) {
|
||||
ResourceMark rm;
|
||||
// Print out trace information
|
||||
LogStream ls(lt);
|
||||
ls.print_cr("PD in set is not alive:");
|
||||
ls.print("class loader: "); _loader_data->class_loader()->print_value_on(&ls);
|
||||
ls.print(" loading: "); probe->instance_klass()->print_value_on(&ls);
|
||||
ls.cr();
|
||||
}
|
||||
if (probe->package_access_cache_acquire() == current) {
|
||||
probe->release_set_package_access_cache(current->next_acquire());
|
||||
} else {
|
||||
assert(prev != nullptr, "should be set by alive entry");
|
||||
prev->release_set_next(current->next_acquire());
|
||||
}
|
||||
// Mark current for deletion but in the meantime it can still be
|
||||
// traversed.
|
||||
delete_list->push(current);
|
||||
current = current->next_acquire();
|
||||
} else {
|
||||
prev = current;
|
||||
current = current->next_acquire();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
_table->do_scan(Thread::current(), clean_entries);
|
||||
}
|
||||
|
||||
void DictionaryEntry::verify_package_access_cache() {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "must only be called as safepoint");
|
||||
for (ProtectionDomainEntry* current = package_access_cache_acquire(); // accessed at a safepoint
|
||||
current != nullptr;
|
||||
current = current->next_acquire()) {
|
||||
guarantee(oopDesc::is_oop_or_null(current->object_no_keepalive()), "Invalid oop");
|
||||
}
|
||||
}
|
||||
|
||||
void DictionaryEntry::print_count(outputStream *st) {
|
||||
assert_locked_or_safepoint(SystemDictionary_lock);
|
||||
int count = 0;
|
||||
for (ProtectionDomainEntry* current = package_access_cache_acquire();
|
||||
current != nullptr;
|
||||
current = current->next_acquire()) {
|
||||
count++;
|
||||
}
|
||||
st->print("pd set count = #%d", count);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void Dictionary::print_size(outputStream* st) const {
|
||||
st->print_cr("Java dictionary (table_size=%d, classes=%d)",
|
||||
table_size(), _number_of_entries);
|
||||
@ -435,9 +196,8 @@ void Dictionary::print_on(outputStream* st) const {
|
||||
print_size(st);
|
||||
st->print_cr("^ indicates that initiating loader is different from defining loader");
|
||||
|
||||
auto printer = [&] (DictionaryEntry** entry) {
|
||||
DictionaryEntry* probe = *entry;
|
||||
Klass* e = probe->instance_klass();
|
||||
auto printer = [&] (InstanceKlass** entry) {
|
||||
InstanceKlass* e = *entry;
|
||||
bool is_defining_class =
|
||||
(_loader_data == e->class_loader_data());
|
||||
st->print(" %s%s", is_defining_class ? " " : "^", e->external_name());
|
||||
@ -448,7 +208,6 @@ void Dictionary::print_on(outputStream* st) const {
|
||||
st->print(", ");
|
||||
cld->print_value_on(st);
|
||||
st->print(", ");
|
||||
probe->print_count(st);
|
||||
}
|
||||
st->cr();
|
||||
return true;
|
||||
@ -462,14 +221,6 @@ void Dictionary::print_on(outputStream* st) const {
|
||||
tty->cr();
|
||||
}
|
||||
|
||||
void DictionaryEntry::verify() {
|
||||
Klass* e = instance_klass();
|
||||
guarantee(e->is_instance_klass(),
|
||||
"Verify of dictionary failed");
|
||||
e->verify();
|
||||
verify_package_access_cache();
|
||||
}
|
||||
|
||||
void Dictionary::verify() {
|
||||
guarantee(_number_of_entries >= 0, "Verify of dictionary failed");
|
||||
|
||||
@ -480,7 +231,7 @@ void Dictionary::verify() {
|
||||
(cld->is_the_null_class_loader_data() || cld->class_loader_no_keepalive()->is_instance()),
|
||||
"checking type of class_loader");
|
||||
|
||||
auto verifier = [&] (DictionaryEntry** val) {
|
||||
auto verifier = [&] (InstanceKlass** val) {
|
||||
(*val)->verify();
|
||||
return true;
|
||||
};
|
||||
@ -490,7 +241,7 @@ void Dictionary::verify() {
|
||||
|
||||
void Dictionary::print_table_statistics(outputStream* st, const char* table_name) {
|
||||
static TableStatistics ts;
|
||||
auto sz = [&] (DictionaryEntry** val) {
|
||||
auto sz = [&] (InstanceKlass** val) {
|
||||
return sizeof(**val);
|
||||
};
|
||||
ts = _table->statistics_get(Thread::current(), sz, ts);
|
||||
|
@ -25,27 +25,21 @@
|
||||
#ifndef SHARE_CLASSFILE_DICTIONARY_HPP
|
||||
#define SHARE_CLASSFILE_DICTIONARY_HPP
|
||||
|
||||
#include "oops/instanceKlass.hpp"
|
||||
#include "oops/oop.hpp"
|
||||
#include "oops/oopHandle.hpp"
|
||||
#include "utilities/concurrentHashTable.hpp"
|
||||
#include "utilities/ostream.hpp"
|
||||
|
||||
class DictionaryEntry;
|
||||
class ProtectionDomainEntry;
|
||||
template <typename T> class GrowableArray;
|
||||
class ClassLoaderData;
|
||||
class InstanceKlass;
|
||||
class outputStream;
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// The data structure for the class loader data dictionaries.
|
||||
|
||||
class DictionaryEntry;
|
||||
|
||||
class Dictionary : public CHeapObj<mtClass> {
|
||||
int _number_of_entries;
|
||||
|
||||
class Config {
|
||||
public:
|
||||
using Value = DictionaryEntry*;
|
||||
using Value = InstanceKlass*;
|
||||
static uintx get_hash(Value const& value, bool* is_dead);
|
||||
static void* allocate_node(void* context, size_t size, Value const& value);
|
||||
static void free_node(void* context, void* memory, Value const& value);
|
||||
@ -57,7 +51,6 @@ class Dictionary : public CHeapObj<mtClass> {
|
||||
ClassLoaderData* _loader_data; // backpointer to owning loader
|
||||
ClassLoaderData* loader_data() const { return _loader_data; }
|
||||
|
||||
DictionaryEntry* get_entry(Thread* current, Symbol* name);
|
||||
bool check_if_needs_resize();
|
||||
int table_size() const;
|
||||
|
||||
@ -73,58 +66,11 @@ public:
|
||||
void all_entries_do(KlassClosure* closure);
|
||||
void classes_do(MetaspaceClosure* it);
|
||||
|
||||
void remove_from_package_access_cache(GrowableArray<ProtectionDomainEntry*>* delete_list);
|
||||
|
||||
InstanceKlass* find(Thread* current, Symbol* name, Handle protection_domain);
|
||||
|
||||
// May make Java upcalls to ClassLoader.checkPackageAccess() when a SecurityManager
|
||||
// is installed.
|
||||
void check_package_access(InstanceKlass* klass,
|
||||
Handle class_loader,
|
||||
Handle protection_domain,
|
||||
TRAPS);
|
||||
|
||||
void print_table_statistics(outputStream* st, const char* table_name);
|
||||
|
||||
void print_on(outputStream* st) const;
|
||||
void print_size(outputStream* st) const;
|
||||
void verify();
|
||||
|
||||
private:
|
||||
bool is_in_package_access_cache(JavaThread* current, Symbol* name,
|
||||
Handle protection_domain);
|
||||
void add_to_package_access_cache(JavaThread* current, InstanceKlass* klass,
|
||||
Handle protection_domain);
|
||||
};
|
||||
|
||||
class DictionaryEntry : public CHeapObj<mtClass> {
|
||||
private:
|
||||
InstanceKlass* _instance_klass;
|
||||
|
||||
// A cache of the ProtectionDomains that have been granted
|
||||
// access to the package of _instance_klass by Java up-calls to
|
||||
// ClassLoader.checkPackageAccess(). See Dictionary::check_package_access().
|
||||
//
|
||||
// We use a cache to avoid repeat Java up-calls that can be expensive.
|
||||
ProtectionDomainEntry* volatile _package_access_cache;
|
||||
|
||||
public:
|
||||
DictionaryEntry(InstanceKlass* instance_klass);
|
||||
~DictionaryEntry();
|
||||
|
||||
bool is_in_package_access_cache(oop protection_domain) const;
|
||||
void add_to_package_access_cache(ClassLoaderData* loader_data, Handle protection_domain);
|
||||
inline bool has_package_access_been_granted(Handle protection_domain);
|
||||
void verify_package_access_cache();
|
||||
|
||||
InstanceKlass* instance_klass() const { return _instance_klass; }
|
||||
InstanceKlass** instance_klass_addr() { return &_instance_klass; }
|
||||
|
||||
ProtectionDomainEntry* package_access_cache_acquire() const { return Atomic::load_acquire(&_package_access_cache); }
|
||||
void release_set_package_access_cache(ProtectionDomainEntry* entry) { Atomic::release_store(&_package_access_cache, entry); }
|
||||
|
||||
void print_count(outputStream *st);
|
||||
void verify();
|
||||
};
|
||||
|
||||
#endif // SHARE_CLASSFILE_DICTIONARY_HPP
|
||||
|
@ -1646,7 +1646,7 @@ JFR_ONLY(int java_lang_Thread::_jfr_epoch_offset;)
|
||||
#define THREAD_FIELDS_DO(macro) \
|
||||
macro(_holder_offset, k, "holder", thread_fieldholder_signature, false); \
|
||||
macro(_name_offset, k, vmSymbols::name_name(), string_signature, false); \
|
||||
macro(_contextClassLoader_offset, k, vmSymbols::contextClassLoader_name(), classloader_signature, false); \
|
||||
macro(_contextClassLoader_offset, k, "contextClassLoader", classloader_signature, false); \
|
||||
macro(_eetop_offset, k, "eetop", long_signature, false); \
|
||||
macro(_interrupted_offset, k, "interrupted", bool_signature, false); \
|
||||
macro(_interruptLock_offset, k, "interruptLock", object_signature, false); \
|
||||
@ -4721,47 +4721,6 @@ DependencyContext java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdepend
|
||||
return dep_ctx;
|
||||
}
|
||||
|
||||
// Support for java_security_AccessControlContext
|
||||
|
||||
int java_security_AccessControlContext::_context_offset;
|
||||
int java_security_AccessControlContext::_privilegedContext_offset;
|
||||
int java_security_AccessControlContext::_isPrivileged_offset;
|
||||
int java_security_AccessControlContext::_isAuthorized_offset;
|
||||
|
||||
#define ACCESSCONTROLCONTEXT_FIELDS_DO(macro) \
|
||||
macro(_context_offset, k, "context", protectiondomain_signature, false); \
|
||||
macro(_privilegedContext_offset, k, "privilegedContext", accesscontrolcontext_signature, false); \
|
||||
macro(_isPrivileged_offset, k, "isPrivileged", bool_signature, false); \
|
||||
macro(_isAuthorized_offset, k, "isAuthorized", bool_signature, false)
|
||||
|
||||
void java_security_AccessControlContext::compute_offsets() {
|
||||
assert(_isPrivileged_offset == 0, "offsets should be initialized only once");
|
||||
InstanceKlass* k = vmClasses::AccessControlContext_klass();
|
||||
ACCESSCONTROLCONTEXT_FIELDS_DO(FIELD_COMPUTE_OFFSET);
|
||||
}
|
||||
|
||||
#if INCLUDE_CDS
|
||||
void java_security_AccessControlContext::serialize_offsets(SerializeClosure* f) {
|
||||
ACCESSCONTROLCONTEXT_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
|
||||
}
|
||||
#endif
|
||||
|
||||
oop java_security_AccessControlContext::create(objArrayHandle context, bool isPrivileged, Handle privileged_context, TRAPS) {
|
||||
assert(_isPrivileged_offset != 0, "offsets should have been initialized");
|
||||
assert(_isAuthorized_offset != 0, "offsets should have been initialized");
|
||||
// Ensure klass is initialized
|
||||
vmClasses::AccessControlContext_klass()->initialize(CHECK_NULL);
|
||||
// Allocate result
|
||||
oop result = vmClasses::AccessControlContext_klass()->allocate_instance(CHECK_NULL);
|
||||
// Fill in values
|
||||
result->obj_field_put(_context_offset, context());
|
||||
result->obj_field_put(_privilegedContext_offset, privileged_context());
|
||||
result->bool_field_put(_isPrivileged_offset, isPrivileged);
|
||||
result->bool_field_put(_isAuthorized_offset, true);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Support for java_lang_ClassLoader
|
||||
|
||||
int java_lang_ClassLoader::_loader_data_offset;
|
||||
@ -4898,17 +4857,6 @@ void java_lang_System::compute_offsets() {
|
||||
SYSTEM_FIELDS_DO(FIELD_COMPUTE_OFFSET);
|
||||
}
|
||||
|
||||
// This field tells us that a security manager can never be installed so we
|
||||
// can completely skip populating the ProtectionDomainCacheTable.
|
||||
bool java_lang_System::allow_security_manager() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This field tells us that a security manager is installed.
|
||||
bool java_lang_System::has_security_manager() {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if INCLUDE_CDS
|
||||
void java_lang_System::serialize_offsets(SerializeClosure* f) {
|
||||
SYSTEM_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
|
||||
@ -5423,7 +5371,6 @@ void java_lang_InternalError::serialize_offsets(SerializeClosure* f) {
|
||||
f(java_lang_invoke_CallSite) \
|
||||
f(java_lang_invoke_ConstantCallSite) \
|
||||
f(java_lang_invoke_MethodHandleNatives_CallSiteContext) \
|
||||
f(java_security_AccessControlContext) \
|
||||
f(java_lang_reflect_AccessibleObject) \
|
||||
f(java_lang_reflect_Method) \
|
||||
f(java_lang_reflect_Constructor) \
|
||||
|
@ -1480,27 +1480,6 @@ public:
|
||||
static bool is_instance(oop obj);
|
||||
};
|
||||
|
||||
// Interface to java.security.AccessControlContext objects
|
||||
|
||||
class java_security_AccessControlContext: AllStatic {
|
||||
private:
|
||||
// Note that for this class the layout changed between JDK1.2 and JDK1.3,
|
||||
// so we compute the offsets at startup rather than hard-wiring them.
|
||||
static int _context_offset;
|
||||
static int _privilegedContext_offset;
|
||||
static int _isPrivileged_offset;
|
||||
static int _isAuthorized_offset;
|
||||
|
||||
static void compute_offsets();
|
||||
public:
|
||||
static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
static oop create(objArrayHandle context, bool isPrivileged, Handle privileged_context, TRAPS);
|
||||
|
||||
// Debugging/initialization
|
||||
friend class JavaClasses;
|
||||
};
|
||||
|
||||
|
||||
// Interface to java.lang.ClassLoader objects
|
||||
|
||||
#define CLASSLOADER_INJECTED_FIELDS(macro) \
|
||||
@ -1557,16 +1536,11 @@ class java_lang_System : AllStatic {
|
||||
static int _static_in_offset;
|
||||
static int _static_out_offset;
|
||||
static int _static_err_offset;
|
||||
static int _static_security_offset;
|
||||
static int _static_allow_security_offset;
|
||||
static int _static_never_offset;
|
||||
|
||||
public:
|
||||
static int in_offset() { CHECK_INIT(_static_in_offset); }
|
||||
static int out_offset() { CHECK_INIT(_static_out_offset); }
|
||||
static int err_offset() { CHECK_INIT(_static_err_offset); }
|
||||
static bool allow_security_manager();
|
||||
static bool has_security_manager();
|
||||
|
||||
static void compute_offsets();
|
||||
static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
@ -1,228 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/classLoaderDataGraph.hpp"
|
||||
#include "classfile/dictionary.hpp"
|
||||
#include "classfile/javaClasses.hpp"
|
||||
#include "classfile/protectionDomainCache.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "logging/logStream.hpp"
|
||||
#include "memory/iterator.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "memory/universe.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "oops/weakHandle.inline.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
#include "utilities/resourceHash.hpp"
|
||||
|
||||
unsigned int ProtectionDomainCacheTable::compute_hash(const WeakHandle& protection_domain) {
|
||||
// The protection domain in the hash computation is passed from a Handle so cannot resolve to null.
|
||||
assert(protection_domain.peek() != nullptr, "Must be live");
|
||||
return (unsigned int)(protection_domain.resolve()->identity_hash());
|
||||
}
|
||||
|
||||
bool ProtectionDomainCacheTable::equals(const WeakHandle& protection_domain1, const WeakHandle& protection_domain2) {
|
||||
return protection_domain1.peek() == protection_domain2.peek();
|
||||
}
|
||||
|
||||
// WeakHandle is both the key and the value. We need it as the key to compare the oops that each point to
|
||||
// for equality. We need it as the value to return the one that already exists to link in the DictionaryEntry.
|
||||
using InternalProtectionDomainCacheTable = ResourceHashtable<WeakHandle, WeakHandle, 1009, AnyObj::C_HEAP, mtClass,
|
||||
ProtectionDomainCacheTable::compute_hash,
|
||||
ProtectionDomainCacheTable::equals>;
|
||||
static InternalProtectionDomainCacheTable* _pd_cache_table;
|
||||
|
||||
bool ProtectionDomainCacheTable::_dead_entries = false;
|
||||
int ProtectionDomainCacheTable::_total_oops_removed = 0;
|
||||
|
||||
void ProtectionDomainCacheTable::initialize(){
|
||||
_pd_cache_table = new (mtClass) InternalProtectionDomainCacheTable();
|
||||
}
|
||||
void ProtectionDomainCacheTable::trigger_cleanup() {
|
||||
MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
|
||||
_dead_entries = true;
|
||||
Service_lock->notify_all();
|
||||
}
|
||||
|
||||
class CleanProtectionDomainEntries : public CLDClosure {
|
||||
GrowableArray<ProtectionDomainEntry*>* _delete_list;
|
||||
public:
|
||||
CleanProtectionDomainEntries(GrowableArray<ProtectionDomainEntry*>* delete_list) :
|
||||
_delete_list(delete_list) {}
|
||||
|
||||
void do_cld(ClassLoaderData* data) {
|
||||
Dictionary* dictionary = data->dictionary();
|
||||
if (dictionary != nullptr) {
|
||||
dictionary->remove_from_package_access_cache(_delete_list);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static GrowableArray<ProtectionDomainEntry*>* _delete_list = nullptr;
|
||||
|
||||
class HandshakeForPD : public HandshakeClosure {
|
||||
public:
|
||||
HandshakeForPD() : HandshakeClosure("HandshakeForPD") {}
|
||||
|
||||
void do_thread(Thread* thread) {
|
||||
log_trace(protectiondomain)("HandshakeForPD::do_thread: thread="
|
||||
INTPTR_FORMAT, p2i(thread));
|
||||
}
|
||||
};
|
||||
|
||||
static void purge_deleted_entries() {
|
||||
// If there are any deleted entries, Handshake-all then they'll be
|
||||
// safe to remove since traversing the package_access_cache list does not stop for
|
||||
// safepoints and only JavaThreads will read the package_access_cache.
|
||||
// This is actually quite rare because the protection domain is generally associated
|
||||
// with the caller class and class loader, which if still alive will keep this
|
||||
// protection domain entry alive.
|
||||
if (_delete_list->length() >= 10) {
|
||||
HandshakeForPD hs_pd;
|
||||
Handshake::execute(&hs_pd);
|
||||
|
||||
for (int i = _delete_list->length() - 1; i >= 0; i--) {
|
||||
ProtectionDomainEntry* entry = _delete_list->at(i);
|
||||
_delete_list->remove_at(i);
|
||||
delete entry;
|
||||
}
|
||||
assert(_delete_list->length() == 0, "should be cleared");
|
||||
}
|
||||
}
|
||||
|
||||
void ProtectionDomainCacheTable::unlink() {
|
||||
// DictionaryEntry::_package_access_cache should be null also, so nothing to do.
|
||||
assert(java_lang_System::allow_security_manager(), "should not be called otherwise");
|
||||
|
||||
// Create a list for holding deleted entries
|
||||
if (_delete_list == nullptr) {
|
||||
_delete_list = new (mtClass)
|
||||
GrowableArray<ProtectionDomainEntry*>(20, mtClass);
|
||||
}
|
||||
|
||||
{
|
||||
// First clean cached pd lists in loaded CLDs
|
||||
// It's unlikely, but some loaded classes in a dictionary might
|
||||
// point to a protection_domain that has been unloaded.
|
||||
// DictionaryEntry::_package_access_cache points at entries in the ProtectionDomainCacheTable.
|
||||
MutexLocker ml(ClassLoaderDataGraph_lock);
|
||||
MutexLocker mldict(SystemDictionary_lock); // need both.
|
||||
CleanProtectionDomainEntries clean(_delete_list);
|
||||
ClassLoaderDataGraph::loaded_cld_do(&clean);
|
||||
}
|
||||
|
||||
// Purge any deleted entries outside of the SystemDictionary_lock.
|
||||
purge_deleted_entries();
|
||||
|
||||
// Reacquire the lock to remove entries from the hashtable.
|
||||
MutexLocker ml(SystemDictionary_lock);
|
||||
|
||||
struct Deleter {
|
||||
int _oops_removed;
|
||||
Deleter() : _oops_removed(0) {}
|
||||
|
||||
bool do_entry(WeakHandle& key, WeakHandle& value) {
|
||||
oop pd = value.peek();
|
||||
if (value.peek() == nullptr) {
|
||||
_oops_removed++;
|
||||
LogTarget(Debug, protectiondomain, table) lt;
|
||||
if (lt.is_enabled()) {
|
||||
LogStream ls(lt);
|
||||
ls.print_cr("protection domain unlinked %d", _oops_removed);
|
||||
}
|
||||
value.release(Universe::vm_weak());
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Deleter deleter;
|
||||
_pd_cache_table->unlink(&deleter);
|
||||
|
||||
_total_oops_removed += deleter._oops_removed;
|
||||
_dead_entries = false;
|
||||
}
|
||||
|
||||
void ProtectionDomainCacheTable::print_on(outputStream* st) {
|
||||
assert_locked_or_safepoint(SystemDictionary_lock);
|
||||
auto printer = [&] (WeakHandle& key, WeakHandle& value) {
|
||||
st->print_cr(" protection_domain: " PTR_FORMAT, p2i(value.peek()));
|
||||
};
|
||||
st->print_cr("Protection domain cache table (table_size=%d, protection domains=%d)",
|
||||
_pd_cache_table->table_size(), _pd_cache_table->number_of_entries());
|
||||
_pd_cache_table->iterate_all(printer);
|
||||
}
|
||||
|
||||
void ProtectionDomainCacheTable::verify() {
|
||||
auto verifier = [&] (WeakHandle& key, WeakHandle& value) {
|
||||
guarantee(value.peek() == nullptr || oopDesc::is_oop(value.peek()), "must be an oop");
|
||||
};
|
||||
_pd_cache_table->iterate_all(verifier);
|
||||
}
|
||||
|
||||
// The object_no_keepalive() call peeks at the phantomly reachable oop without
|
||||
// keeping it alive. This is used for traversing DictionaryEntry::_package_access_cache.
|
||||
oop ProtectionDomainEntry::object_no_keepalive() {
|
||||
return _object.peek();
|
||||
}
|
||||
|
||||
WeakHandle ProtectionDomainCacheTable::add_if_absent(Handle protection_domain) {
|
||||
assert_locked_or_safepoint(SystemDictionary_lock);
|
||||
WeakHandle w(Universe::vm_weak(), protection_domain);
|
||||
bool created;
|
||||
WeakHandle* wk = _pd_cache_table->put_if_absent(w, w, &created);
|
||||
if (!created) {
|
||||
// delete the one created since we already had it in the table
|
||||
w.release(Universe::vm_weak());
|
||||
} else {
|
||||
LogTarget(Debug, protectiondomain, table) lt;
|
||||
if (lt.is_enabled()) {
|
||||
LogStream ls(lt);
|
||||
ls.print("protection domain added ");
|
||||
protection_domain->print_value_on(&ls);
|
||||
ls.cr();
|
||||
}
|
||||
}
|
||||
// Keep entry alive
|
||||
(void)wk->resolve();
|
||||
return *wk;
|
||||
}
|
||||
|
||||
void ProtectionDomainCacheTable::print_table_statistics(outputStream* st) {
|
||||
auto size = [&] (WeakHandle& key, WeakHandle& value) {
|
||||
// The only storage is in OopStorage for an oop
|
||||
return sizeof(oop);
|
||||
};
|
||||
TableStatistics ts = _pd_cache_table->statistics_calculate(size);
|
||||
ts.print(st, "ProtectionDomainCacheTable");
|
||||
}
|
||||
|
||||
int ProtectionDomainCacheTable::number_of_entries() {
|
||||
return _pd_cache_table->number_of_entries();
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_CLASSFILE_PROTECTIONDOMAINCACHE_HPP
|
||||
#define SHARE_CLASSFILE_PROTECTIONDOMAINCACHE_HPP
|
||||
|
||||
#include "oops/oop.hpp"
|
||||
#include "oops/weakHandle.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
|
||||
// The ProtectionDomainCacheTable maps all java.security.ProtectionDomain objects that are
|
||||
// registered by DictionaryEntry::add_to_package_access_cache() to a unique WeakHandle.
|
||||
// The amount of different protection domains used is typically magnitudes smaller
|
||||
// than the number of system dictionary entries (loaded classes).
|
||||
class ProtectionDomainCacheTable : public AllStatic {
|
||||
|
||||
static bool _dead_entries;
|
||||
static int _total_oops_removed;
|
||||
|
||||
public:
|
||||
static void initialize();
|
||||
static unsigned int compute_hash(const WeakHandle& protection_domain);
|
||||
static bool equals(const WeakHandle& protection_domain1, const WeakHandle& protection_domain2);
|
||||
|
||||
static WeakHandle add_if_absent(Handle protection_domain);
|
||||
static void unlink();
|
||||
|
||||
static void print_on(outputStream* st);
|
||||
static void verify();
|
||||
|
||||
static bool has_work() { return _dead_entries; }
|
||||
static void trigger_cleanup();
|
||||
|
||||
static int removed_entries_count() { return _total_oops_removed; };
|
||||
static int number_of_entries();
|
||||
static void print_table_statistics(outputStream* st);
|
||||
};
|
||||
|
||||
|
||||
// This describes the linked list protection domain for each DictionaryEntry in its package_access_cache.
|
||||
class ProtectionDomainEntry :public CHeapObj<mtClass> {
|
||||
WeakHandle _object;
|
||||
ProtectionDomainEntry* volatile _next;
|
||||
public:
|
||||
|
||||
ProtectionDomainEntry(WeakHandle obj,
|
||||
ProtectionDomainEntry* head) : _object(obj), _next(head) {}
|
||||
|
||||
ProtectionDomainEntry* next_acquire() { return Atomic::load_acquire(&_next); }
|
||||
void release_set_next(ProtectionDomainEntry* entry) { Atomic::release_store(&_next, entry); }
|
||||
oop object_no_keepalive();
|
||||
};
|
||||
#endif // SHARE_CLASSFILE_PROTECTIONDOMAINCACHE_HPP
|
@ -38,7 +38,6 @@
|
||||
#include "classfile/loaderConstraints.hpp"
|
||||
#include "classfile/packageEntry.hpp"
|
||||
#include "classfile/placeholders.hpp"
|
||||
#include "classfile/protectionDomainCache.hpp"
|
||||
#include "classfile/resolutionErrors.hpp"
|
||||
#include "classfile/stringTable.hpp"
|
||||
#include "classfile/symbolTable.hpp"
|
||||
@ -331,9 +330,9 @@ static void handle_resolution_exception(Symbol* class_name, bool throw_error, TR
|
||||
|
||||
// Forwards to resolve_or_null
|
||||
|
||||
Klass* SystemDictionary::resolve_or_fail(Symbol* class_name, Handle class_loader, Handle protection_domain,
|
||||
Klass* SystemDictionary::resolve_or_fail(Symbol* class_name, Handle class_loader,
|
||||
bool throw_error, TRAPS) {
|
||||
Klass* klass = resolve_or_null(class_name, class_loader, protection_domain, THREAD);
|
||||
Klass* klass = resolve_or_null(class_name, class_loader, THREAD);
|
||||
// Check for pending exception or null klass, and throw exception
|
||||
if (HAS_PENDING_EXCEPTION || klass == nullptr) {
|
||||
handle_resolution_exception(class_name, throw_error, CHECK_NULL);
|
||||
@ -343,9 +342,9 @@ Klass* SystemDictionary::resolve_or_fail(Symbol* class_name, Handle class_loader
|
||||
|
||||
// Forwards to resolve_array_class_or_null or resolve_instance_class_or_null
|
||||
|
||||
Klass* SystemDictionary::resolve_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS) {
|
||||
Klass* SystemDictionary::resolve_or_null(Symbol* class_name, Handle class_loader, TRAPS) {
|
||||
if (Signature::is_array(class_name)) {
|
||||
return resolve_array_class_or_null(class_name, class_loader, protection_domain, THREAD);
|
||||
return resolve_array_class_or_null(class_name, class_loader, THREAD);
|
||||
} else {
|
||||
assert(class_name != nullptr && !Signature::is_array(class_name), "must be");
|
||||
if (Signature::has_envelope(class_name)) {
|
||||
@ -353,9 +352,9 @@ Klass* SystemDictionary::resolve_or_null(Symbol* class_name, Handle class_loader
|
||||
// Ignore wrapping L and ;.
|
||||
TempNewSymbol name = SymbolTable::new_symbol(class_name->as_C_string() + 1,
|
||||
class_name->utf8_length() - 2);
|
||||
return resolve_instance_class_or_null(name, class_loader, protection_domain, THREAD);
|
||||
return resolve_instance_class_or_null(name, class_loader, THREAD);
|
||||
} else {
|
||||
return resolve_instance_class_or_null(class_name, class_loader, protection_domain, THREAD);
|
||||
return resolve_instance_class_or_null(class_name, class_loader, THREAD);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -364,7 +363,6 @@ Klass* SystemDictionary::resolve_or_null(Symbol* class_name, Handle class_loader
|
||||
|
||||
Klass* SystemDictionary::resolve_array_class_or_null(Symbol* class_name,
|
||||
Handle class_loader,
|
||||
Handle protection_domain,
|
||||
TRAPS) {
|
||||
assert(Signature::is_array(class_name), "must be array");
|
||||
ResourceMark rm(THREAD);
|
||||
@ -376,7 +374,6 @@ Klass* SystemDictionary::resolve_array_class_or_null(Symbol* class_name,
|
||||
Symbol* obj_class = ss.as_symbol();
|
||||
k = SystemDictionary::resolve_instance_class_or_null(obj_class,
|
||||
class_loader,
|
||||
protection_domain,
|
||||
CHECK_NULL);
|
||||
if (k != nullptr) {
|
||||
k = k->array_klass(ndims, CHECK_NULL);
|
||||
@ -422,7 +419,6 @@ static inline void log_circularity_error(Symbol* name, PlaceholderEntry* probe)
|
||||
InstanceKlass* SystemDictionary::resolve_with_circularity_detection(Symbol* class_name,
|
||||
Symbol* next_name,
|
||||
Handle class_loader,
|
||||
Handle protection_domain,
|
||||
bool is_superclass,
|
||||
TRAPS) {
|
||||
|
||||
@ -487,7 +483,6 @@ InstanceKlass* SystemDictionary::resolve_with_circularity_detection(Symbol* clas
|
||||
InstanceKlass* superk =
|
||||
SystemDictionary::resolve_instance_class_or_null(next_name,
|
||||
class_loader,
|
||||
protection_domain,
|
||||
THREAD);
|
||||
|
||||
// Clean up placeholder entry.
|
||||
@ -514,7 +509,7 @@ InstanceKlass* SystemDictionary::resolve_with_circularity_detection(Symbol* clas
|
||||
static void handle_parallel_super_load(Symbol* name,
|
||||
Symbol* superclassname,
|
||||
Handle class_loader,
|
||||
Handle protection_domain, TRAPS) {
|
||||
TRAPS) {
|
||||
|
||||
// The result superk is not used; resolve_with_circularity_detection is called for circularity check only.
|
||||
// This passes true to is_superclass even though it might not be the super class in order to perform the
|
||||
@ -522,7 +517,6 @@ static void handle_parallel_super_load(Symbol* name,
|
||||
Klass* superk = SystemDictionary::resolve_with_circularity_detection(name,
|
||||
superclassname,
|
||||
class_loader,
|
||||
protection_domain,
|
||||
true,
|
||||
CHECK);
|
||||
}
|
||||
@ -588,7 +582,6 @@ void SystemDictionary::post_class_load_event(EventClassLoad* event, const Instan
|
||||
// This can return null, an exception or an InstanceKlass.
|
||||
InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
||||
Handle class_loader,
|
||||
Handle protection_domain,
|
||||
TRAPS) {
|
||||
// name must be in the form of "java/lang/Object" -- cannot be "Ljava/lang/Object;"
|
||||
DEBUG_ONLY(ResourceMark rm(THREAD));
|
||||
@ -602,12 +595,8 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
||||
ClassLoaderData* loader_data = register_loader(class_loader);
|
||||
Dictionary* dictionary = loader_data->dictionary();
|
||||
|
||||
// Do lookup to see if class already exists and the protection domain
|
||||
// has the right access.
|
||||
// This call uses find which checks protection domain already matches
|
||||
// All subsequent calls use find_class, and set loaded_class so that
|
||||
// before we return a result, we call out to java to check for valid protection domain.
|
||||
InstanceKlass* probe = dictionary->find(THREAD, name, protection_domain);
|
||||
// Do lookup to see if class already exists.
|
||||
InstanceKlass* probe = dictionary->find_class(THREAD, name);
|
||||
if (probe != nullptr) return probe;
|
||||
|
||||
// Non-bootstrap class loaders will call out to class loader and
|
||||
@ -653,7 +642,6 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
||||
if (circularity_detection_in_progress) {
|
||||
handle_parallel_super_load(name, superclassname,
|
||||
class_loader,
|
||||
protection_domain,
|
||||
CHECK_NULL);
|
||||
}
|
||||
|
||||
@ -738,12 +726,6 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
||||
// Make sure we have the right class in the dictionary
|
||||
DEBUG_ONLY(verify_dictionary_entry(name, loaded_class));
|
||||
|
||||
if (protection_domain() != nullptr) {
|
||||
// A SecurityManager (if installed) may prevent this protection_domain from accessing loaded_class
|
||||
// by throwing a SecurityException.
|
||||
dictionary->check_package_access(loaded_class, class_loader, protection_domain, CHECK_NULL);
|
||||
}
|
||||
|
||||
return loaded_class;
|
||||
}
|
||||
|
||||
@ -761,8 +743,7 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
||||
|
||||
InstanceKlass* SystemDictionary::find_instance_klass(Thread* current,
|
||||
Symbol* class_name,
|
||||
Handle class_loader,
|
||||
Handle protection_domain) {
|
||||
Handle class_loader) {
|
||||
|
||||
ClassLoaderData* loader_data = ClassLoaderData::class_loader_data_or_null(class_loader());
|
||||
if (loader_data == nullptr) {
|
||||
@ -772,15 +753,14 @@ InstanceKlass* SystemDictionary::find_instance_klass(Thread* current,
|
||||
}
|
||||
|
||||
Dictionary* dictionary = loader_data->dictionary();
|
||||
return dictionary->find(current, class_name, protection_domain);
|
||||
return dictionary->find_class(current, class_name);
|
||||
}
|
||||
|
||||
// Look for a loaded instance or array klass by name. Do not do any loading.
|
||||
// return null in case of error.
|
||||
Klass* SystemDictionary::find_instance_or_array_klass(Thread* current,
|
||||
Symbol* class_name,
|
||||
Handle class_loader,
|
||||
Handle protection_domain) {
|
||||
Handle class_loader) {
|
||||
Klass* k = nullptr;
|
||||
assert(class_name != nullptr, "class name must be non nullptr");
|
||||
|
||||
@ -794,13 +774,13 @@ Klass* SystemDictionary::find_instance_or_array_klass(Thread* current,
|
||||
if (t != T_OBJECT) {
|
||||
k = Universe::typeArrayKlass(t);
|
||||
} else {
|
||||
k = SystemDictionary::find_instance_klass(current, ss.as_symbol(), class_loader, protection_domain);
|
||||
k = SystemDictionary::find_instance_klass(current, ss.as_symbol(), class_loader);
|
||||
}
|
||||
if (k != nullptr) {
|
||||
k = k->array_klass_or_null(ndims);
|
||||
}
|
||||
} else {
|
||||
k = find_instance_klass(current, class_name, class_loader, protection_domain);
|
||||
k = find_instance_klass(current, class_name, class_loader);
|
||||
}
|
||||
return k;
|
||||
}
|
||||
@ -1044,8 +1024,7 @@ bool SystemDictionary::is_shared_class_visible_impl(Symbol* class_name,
|
||||
}
|
||||
|
||||
bool SystemDictionary::check_shared_class_super_type(InstanceKlass* klass, InstanceKlass* super_type,
|
||||
Handle class_loader, Handle protection_domain,
|
||||
bool is_superclass, TRAPS) {
|
||||
Handle class_loader, bool is_superclass, TRAPS) {
|
||||
assert(super_type->is_shared(), "must be");
|
||||
|
||||
// Quick check if the super type has been already loaded.
|
||||
@ -1055,14 +1034,14 @@ bool SystemDictionary::check_shared_class_super_type(InstanceKlass* klass, Insta
|
||||
if (!super_type->is_shared_unregistered_class() && super_type->class_loader_data() != nullptr) {
|
||||
// Check if the superclass is loaded by the current class_loader
|
||||
Symbol* name = super_type->name();
|
||||
InstanceKlass* check = find_instance_klass(THREAD, name, class_loader, protection_domain);
|
||||
InstanceKlass* check = find_instance_klass(THREAD, name, class_loader);
|
||||
if (check == super_type) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Klass *found = resolve_with_circularity_detection(klass->name(), super_type->name(),
|
||||
class_loader, protection_domain, is_superclass, CHECK_false);
|
||||
class_loader, is_superclass, CHECK_false);
|
||||
if (found == super_type) {
|
||||
return true;
|
||||
} else {
|
||||
@ -1072,8 +1051,7 @@ bool SystemDictionary::check_shared_class_super_type(InstanceKlass* klass, Insta
|
||||
}
|
||||
}
|
||||
|
||||
bool SystemDictionary::check_shared_class_super_types(InstanceKlass* ik, Handle class_loader,
|
||||
Handle protection_domain, TRAPS) {
|
||||
bool SystemDictionary::check_shared_class_super_types(InstanceKlass* ik, Handle class_loader, TRAPS) {
|
||||
// Check the superclass and interfaces. They must be the same
|
||||
// as in dump time, because the layout of <ik> depends on
|
||||
// the specific layout of ik->super() and ik->local_interfaces().
|
||||
@ -1083,7 +1061,7 @@ bool SystemDictionary::check_shared_class_super_types(InstanceKlass* ik, Handle
|
||||
|
||||
if (ik->super() != nullptr) {
|
||||
bool check_super = check_shared_class_super_type(ik, InstanceKlass::cast(ik->super()),
|
||||
class_loader, protection_domain, true,
|
||||
class_loader, true,
|
||||
CHECK_false);
|
||||
if (!check_super) {
|
||||
return false;
|
||||
@ -1093,7 +1071,7 @@ bool SystemDictionary::check_shared_class_super_types(InstanceKlass* ik, Handle
|
||||
Array<InstanceKlass*>* interfaces = ik->local_interfaces();
|
||||
int num_interfaces = interfaces->length();
|
||||
for (int index = 0; index < num_interfaces; index++) {
|
||||
bool check_interface = check_shared_class_super_type(ik, interfaces->at(index), class_loader, protection_domain, false,
|
||||
bool check_interface = check_shared_class_super_type(ik, interfaces->at(index), class_loader, false,
|
||||
CHECK_false);
|
||||
if (!check_interface) {
|
||||
return false;
|
||||
@ -1111,7 +1089,7 @@ InstanceKlass* SystemDictionary::load_shared_lambda_proxy_class(InstanceKlass* i
|
||||
InstanceKlass* shared_nest_host = SystemDictionaryShared::get_shared_nest_host(ik);
|
||||
assert(shared_nest_host->is_shared(), "nest host must be in CDS archive");
|
||||
Symbol* cn = shared_nest_host->name();
|
||||
Klass *s = resolve_or_fail(cn, class_loader, protection_domain, true, CHECK_NULL);
|
||||
Klass *s = resolve_or_fail(cn, class_loader, true, CHECK_NULL);
|
||||
if (s != shared_nest_host) {
|
||||
// The dynamically resolved nest_host is not the same as the one we used during dump time,
|
||||
// so we cannot use ik.
|
||||
@ -1151,7 +1129,7 @@ InstanceKlass* SystemDictionary::load_shared_class(InstanceKlass* ik,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool check = check_shared_class_super_types(ik, class_loader, protection_domain, CHECK_NULL);
|
||||
bool check = check_shared_class_super_types(ik, class_loader, CHECK_NULL);
|
||||
if (!check) {
|
||||
ik->set_shared_loading_failed();
|
||||
return nullptr;
|
||||
@ -1579,17 +1557,6 @@ bool SystemDictionary::do_unloading(GCTimer* gc_timer) {
|
||||
if (unloading_occurred) {
|
||||
SymbolTable::trigger_cleanup();
|
||||
|
||||
if (java_lang_System::allow_security_manager()) {
|
||||
// Oops referenced by the protection domain cache table may get unreachable independently
|
||||
// of the class loader (eg. cached protection domain oops). So we need to
|
||||
// explicitly unlink them here.
|
||||
// All protection domain oops are linked to the caller class, so if nothing
|
||||
// unloads, this is not needed.
|
||||
ProtectionDomainCacheTable::trigger_cleanup();
|
||||
} else {
|
||||
assert(ProtectionDomainCacheTable::number_of_entries() == 0, "should be empty");
|
||||
}
|
||||
|
||||
ConditionalMutexLocker ml(ClassInitError_lock, is_concurrent);
|
||||
InstanceKlass::clean_initialization_error_table();
|
||||
}
|
||||
@ -1627,7 +1594,6 @@ void SystemDictionary::initialize(TRAPS) {
|
||||
ResolutionErrorTable::initialize();
|
||||
LoaderConstraintTable::initialize();
|
||||
PlaceholderTable::initialize();
|
||||
ProtectionDomainCacheTable::initialize();
|
||||
#if INCLUDE_CDS
|
||||
SystemDictionaryShared::initialize();
|
||||
#endif
|
||||
@ -1744,10 +1710,7 @@ Klass* SystemDictionary::find_constrained_instance_or_array_klass(
|
||||
Thread* current, Symbol* class_name, Handle class_loader) {
|
||||
|
||||
// First see if it has been loaded directly.
|
||||
// Force the protection domain to be null. (This removes protection checks.)
|
||||
Handle no_protection_domain;
|
||||
Klass* klass = find_instance_or_array_klass(current, class_name, class_loader,
|
||||
no_protection_domain);
|
||||
Klass* klass = find_instance_or_array_klass(current, class_name, class_loader);
|
||||
if (klass != nullptr)
|
||||
return klass;
|
||||
|
||||
@ -2195,21 +2158,18 @@ static bool is_always_visible_class(oop mirror) {
|
||||
// N.B. Code in reflection should use this entry point.
|
||||
Handle SystemDictionary::find_java_mirror_for_type(Symbol* signature,
|
||||
Klass* accessing_klass,
|
||||
Handle class_loader,
|
||||
Handle protection_domain,
|
||||
SignatureStream::FailureMode failure_mode,
|
||||
TRAPS) {
|
||||
assert(accessing_klass == nullptr || (class_loader.is_null() && protection_domain.is_null()),
|
||||
"one or the other, or perhaps neither");
|
||||
|
||||
Handle class_loader;
|
||||
|
||||
// What we have here must be a valid field descriptor,
|
||||
// and all valid field descriptors are supported.
|
||||
// Produce the same java.lang.Class that reflection reports.
|
||||
if (accessing_klass != nullptr) {
|
||||
class_loader = Handle(THREAD, accessing_klass->class_loader());
|
||||
protection_domain = Handle(THREAD, accessing_klass->protection_domain());
|
||||
}
|
||||
ResolvingSignatureStream ss(signature, class_loader, protection_domain, false);
|
||||
ResolvingSignatureStream ss(signature, class_loader, false);
|
||||
oop mirror_oop = ss.as_java_mirror(failure_mode, CHECK_NH);
|
||||
if (mirror_oop == nullptr) {
|
||||
return Handle(); // report failure this way
|
||||
@ -2250,10 +2210,9 @@ Handle SystemDictionary::find_method_handle_type(Symbol* signature,
|
||||
return Handle(); // do not attempt from within compiler, unless it was cached
|
||||
}
|
||||
|
||||
Handle class_loader, protection_domain;
|
||||
Handle class_loader;
|
||||
if (accessing_klass != nullptr) {
|
||||
class_loader = Handle(THREAD, accessing_klass->class_loader());
|
||||
protection_domain = Handle(THREAD, accessing_klass->protection_domain());
|
||||
}
|
||||
bool can_be_cached = true;
|
||||
int npts = ArgumentCount(signature).size();
|
||||
@ -2265,8 +2224,7 @@ Handle SystemDictionary::find_method_handle_type(Symbol* signature,
|
||||
oop mirror = nullptr;
|
||||
if (can_be_cached) {
|
||||
// Use neutral class loader to lookup candidate classes to be placed in the cache.
|
||||
mirror = ss.as_java_mirror(Handle(), Handle(),
|
||||
SignatureStream::ReturnNull, CHECK_(empty));
|
||||
mirror = ss.as_java_mirror(Handle(), SignatureStream::ReturnNull, CHECK_(empty));
|
||||
if (mirror == nullptr || (ss.is_reference() && !is_always_visible_class(mirror))) {
|
||||
// Fall back to accessing_klass context.
|
||||
can_be_cached = false;
|
||||
@ -2274,8 +2232,7 @@ Handle SystemDictionary::find_method_handle_type(Symbol* signature,
|
||||
}
|
||||
if (!can_be_cached) {
|
||||
// Resolve, throwing a real error if it doesn't work.
|
||||
mirror = ss.as_java_mirror(class_loader, protection_domain,
|
||||
SignatureStream::NCDFError, CHECK_(empty));
|
||||
mirror = ss.as_java_mirror(class_loader, SignatureStream::NCDFError, CHECK_(empty));
|
||||
}
|
||||
assert(mirror != nullptr, "%s", ss.as_symbol()->as_C_string());
|
||||
if (ss.at_return_type())
|
||||
@ -2328,12 +2285,11 @@ Handle SystemDictionary::find_field_handle_type(Symbol* signature,
|
||||
ResourceMark rm(THREAD);
|
||||
SignatureStream ss(signature, /*is_method=*/ false);
|
||||
if (!ss.is_done()) {
|
||||
Handle class_loader, protection_domain;
|
||||
Handle class_loader;
|
||||
if (accessing_klass != nullptr) {
|
||||
class_loader = Handle(THREAD, accessing_klass->class_loader());
|
||||
protection_domain = Handle(THREAD, accessing_klass->protection_domain());
|
||||
}
|
||||
oop mirror = ss.as_java_mirror(class_loader, protection_domain, SignatureStream::NCDFError, CHECK_(empty));
|
||||
oop mirror = ss.as_java_mirror(class_loader, SignatureStream::NCDFError, CHECK_(empty));
|
||||
ss.next();
|
||||
if (ss.is_done()) {
|
||||
return Handle(THREAD, mirror);
|
||||
@ -2471,9 +2427,6 @@ void SystemDictionary::print_on(outputStream *st) {
|
||||
// loader constraints - print under SD_lock
|
||||
LoaderConstraintTable::print_on(st);
|
||||
st->cr();
|
||||
|
||||
ProtectionDomainCacheTable::print_on(st);
|
||||
st->cr();
|
||||
}
|
||||
|
||||
void SystemDictionary::print() { print_on(tty); }
|
||||
@ -2487,9 +2440,6 @@ void SystemDictionary::verify() {
|
||||
|
||||
// Verify constraint table
|
||||
LoaderConstraintTable::verify();
|
||||
|
||||
// Verify protection domain table
|
||||
ProtectionDomainCacheTable::verify();
|
||||
}
|
||||
|
||||
void SystemDictionary::dump(outputStream *st, bool verbose) {
|
||||
@ -2500,7 +2450,6 @@ void SystemDictionary::dump(outputStream *st, bool verbose) {
|
||||
CDS_ONLY(SystemDictionaryShared::print_table_statistics(st));
|
||||
ClassLoaderDataGraph::print_table_statistics(st);
|
||||
LoaderConstraintTable::print_table_statistics(st);
|
||||
ProtectionDomainCacheTable::print_table_statistics(st);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,12 +33,12 @@
|
||||
// The dictionary in each ClassLoaderData stores all loaded classes, either
|
||||
// initiatied by its class loader or defined by its class loader:
|
||||
//
|
||||
// class loader -> ClassLoaderData -> [class, protection domain set]
|
||||
// class loader -> ClassLoaderData -> Loaded and initiated loaded classes
|
||||
//
|
||||
// Classes are loaded lazily. The default VM class loader is
|
||||
// represented as null.
|
||||
|
||||
// The underlying data structure is an open hash table (Dictionary) per
|
||||
// The underlying data structure is a concurrent hash table (Dictionary) per
|
||||
// ClassLoaderData with a fixed number of buckets. During loading the
|
||||
// class loader object is locked, (for the VM loader a private lock object is used).
|
||||
// The global SystemDictionary_lock is held for all additions into the ClassLoaderData
|
||||
@ -49,9 +49,7 @@
|
||||
// a side data structure, and is used to detect ClassCircularityErrors.
|
||||
//
|
||||
// When class loading is finished, a new entry is added to the dictionary
|
||||
// of the class loader and the placeholder is removed. Note that the protection
|
||||
// domain field of the dictionary entry has not yet been filled in when
|
||||
// the "real" dictionary entry is created.
|
||||
// of the class loader and the placeholder is removed.
|
||||
//
|
||||
// Clients of this class who are interested in finding if a class has
|
||||
// been completely loaded -- not classes in the process of being loaded --
|
||||
@ -91,24 +89,23 @@ class SystemDictionary : AllStatic {
|
||||
// throw_error flag. For most uses the throw_error argument should be set
|
||||
// to true.
|
||||
|
||||
static Klass* resolve_or_fail(Symbol* class_name, Handle class_loader, Handle protection_domain, bool throw_error, TRAPS);
|
||||
static Klass* resolve_or_fail(Symbol* class_name, Handle class_loader, bool throw_error, TRAPS);
|
||||
// Convenient call for null loader and protection domain.
|
||||
static Klass* resolve_or_fail(Symbol* class_name, bool throw_error, TRAPS) {
|
||||
return resolve_or_fail(class_name, Handle(), Handle(), throw_error, THREAD);
|
||||
return resolve_or_fail(class_name, Handle(), throw_error, THREAD);
|
||||
}
|
||||
|
||||
// Returns a class with a given class name and class loader.
|
||||
// Loads the class if needed. If not found null is returned.
|
||||
static Klass* resolve_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS);
|
||||
static Klass* resolve_or_null(Symbol* class_name, Handle class_loader, TRAPS);
|
||||
// Version with null loader and protection domain
|
||||
static Klass* resolve_or_null(Symbol* class_name, TRAPS) {
|
||||
return resolve_or_null(class_name, Handle(), Handle(), THREAD);
|
||||
return resolve_or_null(class_name, Handle(), THREAD);
|
||||
}
|
||||
|
||||
static InstanceKlass* resolve_with_circularity_detection(Symbol* class_name,
|
||||
Symbol* next_name,
|
||||
Handle class_loader,
|
||||
Handle protection_domain,
|
||||
bool is_superclass,
|
||||
TRAPS);
|
||||
|
||||
@ -117,9 +114,8 @@ class SystemDictionary : AllStatic {
|
||||
// "class_name" is the class whose super class or interface is being resolved.
|
||||
static InstanceKlass* resolve_super_or_fail(Symbol* class_name, Symbol* super_name,
|
||||
Handle class_loader,
|
||||
Handle protection_domain, bool is_superclass, TRAPS) {
|
||||
return resolve_with_circularity_detection(class_name, super_name, class_loader, protection_domain,
|
||||
is_superclass, THREAD);
|
||||
bool is_superclass, TRAPS) {
|
||||
return resolve_with_circularity_detection(class_name, super_name, class_loader, is_superclass, THREAD);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -152,14 +148,13 @@ class SystemDictionary : AllStatic {
|
||||
|
||||
// Lookup an already loaded class. If not found null is returned.
|
||||
static InstanceKlass* find_instance_klass(Thread* current, Symbol* class_name,
|
||||
Handle class_loader, Handle protection_domain);
|
||||
Handle class_loader);
|
||||
|
||||
// Lookup an already loaded instance or array class.
|
||||
// Do not make any queries to class loaders; consult only the cache.
|
||||
// If not found null is returned.
|
||||
static Klass* find_instance_or_array_klass(Thread* current, Symbol* class_name,
|
||||
Handle class_loader,
|
||||
Handle protection_domain);
|
||||
Handle class_loader);
|
||||
|
||||
// Lookup an instance or array class that has already been loaded
|
||||
// either into the given class loader, or else into another class
|
||||
@ -246,21 +241,10 @@ public:
|
||||
static void restore_archived_method_handle_intrinsics() NOT_CDS_RETURN;
|
||||
|
||||
// compute java_mirror (java.lang.Class instance) for a type ("I", "[[B", "LFoo;", etc.)
|
||||
// Either the accessing_klass or the CL/PD can be non-null, but not both.
|
||||
static Handle find_java_mirror_for_type(Symbol* signature,
|
||||
Klass* accessing_klass,
|
||||
Handle class_loader,
|
||||
Handle protection_domain,
|
||||
SignatureStream::FailureMode failure_mode,
|
||||
TRAPS);
|
||||
static Handle find_java_mirror_for_type(Symbol* signature,
|
||||
Klass* accessing_klass,
|
||||
SignatureStream::FailureMode failure_mode,
|
||||
TRAPS) {
|
||||
// callee will fill in CL/PD from AK, if they are needed
|
||||
return find_java_mirror_for_type(signature, accessing_klass, Handle(), Handle(),
|
||||
failure_mode, THREAD);
|
||||
}
|
||||
|
||||
// find a java.lang.invoke.MethodType object for a given signature
|
||||
// (asks Java to compute it if necessary, except in a compiler thread)
|
||||
@ -309,10 +293,10 @@ private:
|
||||
// Basic loading operations
|
||||
static InstanceKlass* resolve_instance_class_or_null(Symbol* class_name,
|
||||
Handle class_loader,
|
||||
Handle protection_domain, TRAPS);
|
||||
TRAPS);
|
||||
static Klass* resolve_array_class_or_null(Symbol* class_name,
|
||||
Handle class_loader,
|
||||
Handle protection_domain, TRAPS);
|
||||
TRAPS);
|
||||
static void define_instance_class(InstanceKlass* k, Handle class_loader, TRAPS);
|
||||
static InstanceKlass* find_or_define_helper(Symbol* class_name,
|
||||
Handle class_loader,
|
||||
@ -334,10 +318,9 @@ private:
|
||||
PackageEntry* pkg_entry,
|
||||
Handle class_loader);
|
||||
static bool check_shared_class_super_type(InstanceKlass* klass, InstanceKlass* super,
|
||||
Handle class_loader, Handle protection_domain,
|
||||
Handle class_loader,
|
||||
bool is_superclass, TRAPS);
|
||||
static bool check_shared_class_super_types(InstanceKlass* ik, Handle class_loader,
|
||||
Handle protection_domain, TRAPS);
|
||||
static bool check_shared_class_super_types(InstanceKlass* ik, Handle class_loader, TRAPS);
|
||||
// Second part of load_shared_class
|
||||
static void load_shared_class_misc(InstanceKlass* ik, ClassLoaderData* loader_data) NOT_CDS_RETURN;
|
||||
static void restore_archived_method_handle_intrinsics_impl(TRAPS) NOT_CDS_RETURN;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. 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
|
||||
@ -57,8 +57,7 @@ bool VerificationType::resolve_and_check_assignability(InstanceKlass* klass, Sym
|
||||
this_class = klass;
|
||||
} else {
|
||||
this_class = SystemDictionary::resolve_or_fail(
|
||||
name, Handle(THREAD, klass->class_loader()),
|
||||
Handle(THREAD, klass->protection_domain()), true, CHECK_false);
|
||||
name, Handle(THREAD, klass->class_loader()), true, CHECK_false);
|
||||
if (log_is_enabled(Debug, class, resolve)) {
|
||||
Verifier::trace_class_resolution(this_class, klass);
|
||||
}
|
||||
@ -79,8 +78,7 @@ bool VerificationType::resolve_and_check_assignability(InstanceKlass* klass, Sym
|
||||
from_class = klass;
|
||||
} else {
|
||||
from_class = SystemDictionary::resolve_or_fail(
|
||||
from_name, Handle(THREAD, klass->class_loader()),
|
||||
Handle(THREAD, klass->protection_domain()), true, CHECK_false);
|
||||
from_name, Handle(THREAD, klass->class_loader()), true, CHECK_false);
|
||||
if (log_is_enabled(Debug, class, resolve)) {
|
||||
Verifier::trace_class_resolution(from_class, klass);
|
||||
}
|
||||
|
@ -2092,15 +2092,13 @@ void ClassVerifier::class_format_error(const char* msg, ...) {
|
||||
|
||||
Klass* ClassVerifier::load_class(Symbol* name, TRAPS) {
|
||||
HandleMark hm(THREAD);
|
||||
// Get current loader and protection domain first.
|
||||
// Get current loader first.
|
||||
oop loader = current_class()->class_loader();
|
||||
oop protection_domain = current_class()->protection_domain();
|
||||
|
||||
assert(name_in_supers(name, current_class()), "name should be a super class");
|
||||
|
||||
Klass* kls = SystemDictionary::resolve_or_fail(
|
||||
name, Handle(THREAD, loader), Handle(THREAD, protection_domain),
|
||||
true, THREAD);
|
||||
name, Handle(THREAD, loader), true, THREAD);
|
||||
|
||||
if (kls != nullptr) {
|
||||
if (log_is_enabled(Debug, class, resolve)) {
|
||||
|
@ -60,10 +60,7 @@
|
||||
do_klass(Error_klass, java_lang_Error ) \
|
||||
do_klass(Exception_klass, java_lang_Exception ) \
|
||||
do_klass(RuntimeException_klass, java_lang_RuntimeException ) \
|
||||
do_klass(SecurityManager_klass, java_lang_SecurityManager ) \
|
||||
do_klass(ProtectionDomain_klass, java_security_ProtectionDomain ) \
|
||||
do_klass(AccessControlContext_klass, java_security_AccessControlContext ) \
|
||||
do_klass(AccessController_klass, java_security_AccessController ) \
|
||||
do_klass(SecureClassLoader_klass, java_security_SecureClassLoader ) \
|
||||
do_klass(ClassNotFoundException_klass, java_lang_ClassNotFoundException ) \
|
||||
do_klass(Record_klass, java_lang_Record ) \
|
||||
|
@ -118,12 +118,8 @@ class SerializeClosure;
|
||||
template(java_lang_reflect_RecordComponent, "java/lang/reflect/RecordComponent") \
|
||||
template(java_lang_StringBuffer, "java/lang/StringBuffer") \
|
||||
template(java_lang_StringBuilder, "java/lang/StringBuilder") \
|
||||
template(java_lang_SecurityManager, "java/lang/SecurityManager") \
|
||||
template(java_lang_ScopedValue, "java/lang/ScopedValue") \
|
||||
template(java_lang_ScopedValue_Carrier, "java/lang/ScopedValue$Carrier") \
|
||||
template(java_security_AccessControlContext, "java/security/AccessControlContext") \
|
||||
template(java_security_AccessController, "java/security/AccessController") \
|
||||
template(executePrivileged_name, "executePrivileged") \
|
||||
template(java_security_CodeSource, "java/security/CodeSource") \
|
||||
template(java_security_ProtectionDomain, "java/security/ProtectionDomain") \
|
||||
template(java_security_SecureClassLoader, "java/security/SecureClassLoader") \
|
||||
@ -440,9 +436,6 @@ class SerializeClosure;
|
||||
template(getCause_name, "getCause") \
|
||||
template(initCause_name, "initCause") \
|
||||
template(getProperty_name, "getProperty") \
|
||||
template(context_name, "context") \
|
||||
template(contextClassLoader_name, "contextClassLoader") \
|
||||
template(getClassContext_name, "getClassContext") \
|
||||
template(wait_name, "wait0") \
|
||||
template(forName_name, "forName") \
|
||||
template(forName0_name, "forName0") \
|
||||
@ -490,7 +483,6 @@ class SerializeClosure;
|
||||
template(input_stream_void_signature, "(Ljava/io/InputStream;)V") \
|
||||
template(input_stream_signature, "Ljava/io/InputStream;") \
|
||||
template(print_stream_signature, "Ljava/io/PrintStream;") \
|
||||
template(security_manager_signature, "Ljava/lang/SecurityManager;") \
|
||||
template(defineOrCheckPackage_name, "defineOrCheckPackage") \
|
||||
template(defineOrCheckPackage_signature, "(Ljava/lang/String;Ljava/util/jar/Manifest;Ljava/net/URL;)Ljava/lang/Package;") \
|
||||
template(getProtectionDomain_name, "getProtectionDomain") \
|
||||
@ -604,9 +596,6 @@ class SerializeClosure;
|
||||
template(void_string_signature, "()Ljava/lang/String;") \
|
||||
template(object_array_object_signature, "([Ljava/lang/Object;)Ljava/lang/Object;") \
|
||||
template(object_object_array_object_signature, "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;")\
|
||||
template(protectiondomain_signature, "[Ljava/security/ProtectionDomain;") \
|
||||
template(accesscontrolcontext_signature, "Ljava/security/AccessControlContext;") \
|
||||
template(class_protectiondomain_signature, "(Ljava/lang/Class;Ljava/security/ProtectionDomain;)V") \
|
||||
template(thread_signature, "Ljava/lang/Thread;") \
|
||||
template(thread_fieldholder_signature, "Ljava/lang/Thread$FieldHolder;") \
|
||||
template(threadgroup_signature, "Ljava/lang/ThreadGroup;") \
|
||||
|
@ -326,12 +326,6 @@ JVM_GetNextThreadIdOffset(JNIEnv *env, jclass threadClass);
|
||||
JNIEXPORT void JNICALL
|
||||
JVM_RegisterContinuationMethods(JNIEnv *env, jclass cls);
|
||||
|
||||
/*
|
||||
* java.lang.SecurityManager
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL
|
||||
JVM_GetClassContext(JNIEnv *env);
|
||||
|
||||
/*
|
||||
* java.lang.Package
|
||||
*/
|
||||
|
@ -496,7 +496,6 @@ Method* LinkResolver::lookup_polymorphic_method(const LinkInfo& link_info,
|
||||
Klass* natives = vmClasses::MethodHandleNatives_klass();
|
||||
if (natives == nullptr || InstanceKlass::cast(natives)->is_not_initialized()) {
|
||||
SystemDictionary::resolve_or_fail(vmSymbols::java_lang_invoke_MethodHandleNatives(),
|
||||
Handle(),
|
||||
Handle(),
|
||||
true,
|
||||
CHECK_NULL);
|
||||
|
@ -613,10 +613,8 @@ C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, ARGU
|
||||
JVMCIKlassHandle resolved_klass(THREAD);
|
||||
Klass* accessing_klass = UNPACK_PAIR(Klass, accessing_klass);
|
||||
Handle class_loader;
|
||||
Handle protection_domain;
|
||||
if (accessing_klass != nullptr) {
|
||||
class_loader = Handle(THREAD, accessing_klass->class_loader());
|
||||
protection_domain = Handle(THREAD, accessing_klass->protection_domain());
|
||||
} else {
|
||||
switch (accessing_klass_loader) {
|
||||
case 0: break; // class_loader is already null, the boot loader
|
||||
@ -629,23 +627,21 @@ C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, ARGU
|
||||
}
|
||||
|
||||
if (resolve) {
|
||||
resolved_klass = SystemDictionary::resolve_or_fail(class_name, class_loader, protection_domain, true, CHECK_NULL);
|
||||
resolved_klass = SystemDictionary::resolve_or_fail(class_name, class_loader, true, CHECK_NULL);
|
||||
} else {
|
||||
if (Signature::has_envelope(class_name)) {
|
||||
// This is a name from a signature. Strip off the trimmings.
|
||||
// Call recursive to keep scope of strippedsym.
|
||||
TempNewSymbol strippedsym = Signature::strip_envelope(class_name);
|
||||
resolved_klass = SystemDictionary::find_instance_klass(THREAD, strippedsym,
|
||||
class_loader,
|
||||
protection_domain);
|
||||
class_loader);
|
||||
} else if (Signature::is_array(class_name)) {
|
||||
SignatureStream ss(class_name, false);
|
||||
int ndim = ss.skip_array_prefix();
|
||||
if (ss.type() == T_OBJECT) {
|
||||
Symbol* strippedsym = ss.as_symbol();
|
||||
resolved_klass = SystemDictionary::find_instance_klass(THREAD, strippedsym,
|
||||
class_loader,
|
||||
protection_domain);
|
||||
class_loader);
|
||||
if (!resolved_klass.is_null()) {
|
||||
resolved_klass = resolved_klass->array_klass(ndim, CHECK_NULL);
|
||||
}
|
||||
@ -654,8 +650,7 @@ C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, ARGU
|
||||
}
|
||||
} else {
|
||||
resolved_klass = SystemDictionary::find_instance_klass(THREAD, class_name,
|
||||
class_loader,
|
||||
protection_domain);
|
||||
class_loader);
|
||||
}
|
||||
}
|
||||
JVMCIObject result = JVMCIENV->get_jvmci_type(resolved_klass, JVMCI_CHECK_NULL);
|
||||
|
@ -941,9 +941,8 @@ void JVMCIEnv::fthrow_error(const char* file, int line, const char* format, ...)
|
||||
va_end(ap);
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
if (is_hotspot()) {
|
||||
Handle h_loader = Handle();
|
||||
Handle h_protection_domain = Handle();
|
||||
Exceptions::_throw_msg(THREAD, file, line, vmSymbols::jdk_vm_ci_common_JVMCIError(), msg, h_loader, h_protection_domain);
|
||||
Handle h_loader;
|
||||
Exceptions::_throw_msg(THREAD, file, line, vmSymbols::jdk_vm_ci_common_JVMCIError(), msg, h_loader );
|
||||
} else {
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jni()->ThrowNew(JNIJVMCI::JVMCIError::clazz(), msg);
|
||||
|
@ -1678,14 +1678,12 @@ Klass* JVMCIRuntime::get_klass_by_name_impl(Klass*& accessing_klass,
|
||||
}
|
||||
|
||||
Handle loader;
|
||||
Handle domain;
|
||||
if (accessing_klass != nullptr) {
|
||||
loader = Handle(THREAD, accessing_klass->class_loader());
|
||||
domain = Handle(THREAD, accessing_klass->protection_domain());
|
||||
}
|
||||
|
||||
Klass* found_klass = require_local ?
|
||||
SystemDictionary::find_instance_or_array_klass(THREAD, sym, loader, domain) :
|
||||
SystemDictionary::find_instance_or_array_klass(THREAD, sym, loader) :
|
||||
SystemDictionary::find_constrained_instance_or_array_klass(THREAD, sym, loader);
|
||||
|
||||
// If we fail to find an array klass, look again for its element type.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. 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
|
||||
@ -59,7 +59,6 @@ class LogDiagnosticCommand : public DCmdWithParser {
|
||||
return "Lists current log configuration, enables/disables/configures a log output, or rotates all logs.";
|
||||
}
|
||||
|
||||
// Used by SecurityManager. This DCMD requires ManagementPermission = control.
|
||||
static const JavaPermission permission() {
|
||||
JavaPermission p = {"java.lang.management.ManagementPermission", "control", nullptr};
|
||||
return p;
|
||||
|
@ -161,7 +161,6 @@ class outputStream;
|
||||
LOG_TAG(preorder) /* Trace all classes loaded in order referenced (not loaded) */ \
|
||||
LOG_TAG(preview) /* Trace loading of preview feature types */ \
|
||||
LOG_TAG(promotion) \
|
||||
LOG_TAG(protectiondomain) /* "Trace protection domain verification" */ \
|
||||
LOG_TAG(ptrqueue) \
|
||||
LOG_TAG(purge) \
|
||||
LOG_TAG(record) \
|
||||
|
@ -680,13 +680,12 @@ Klass* ConstantPool::klass_at_impl(const constantPoolHandle& this_cp, int cp_ind
|
||||
Handle mirror_handle;
|
||||
Symbol* name = this_cp->symbol_at(name_index);
|
||||
Handle loader (THREAD, this_cp->pool_holder()->class_loader());
|
||||
Handle protection_domain (THREAD, this_cp->pool_holder()->protection_domain());
|
||||
|
||||
Klass* k;
|
||||
{
|
||||
// Turn off the single stepping while doing class resolution
|
||||
JvmtiHideSingleStepping jhss(javaThread);
|
||||
k = SystemDictionary::resolve_or_fail(name, loader, protection_domain, true, THREAD);
|
||||
k = SystemDictionary::resolve_or_fail(name, loader, true, THREAD);
|
||||
} // JvmtiHideSingleStepping jhss(javaThread);
|
||||
|
||||
if (!HAS_PENDING_EXCEPTION) {
|
||||
@ -756,10 +755,8 @@ Klass* ConstantPool::klass_at_if_loaded(const constantPoolHandle& this_cp, int w
|
||||
HandleMark hm(current);
|
||||
Symbol* name = this_cp->symbol_at(name_index);
|
||||
oop loader = this_cp->pool_holder()->class_loader();
|
||||
oop protection_domain = this_cp->pool_holder()->protection_domain();
|
||||
Handle h_prot (current, protection_domain);
|
||||
Handle h_loader (current, loader);
|
||||
Klass* k = SystemDictionary::find_instance_klass(current, name, h_loader, h_prot);
|
||||
Klass* k = SystemDictionary::find_instance_klass(current, name, h_loader);
|
||||
|
||||
// Avoid constant pool verification at a safepoint, as it takes the Module_lock.
|
||||
if (k != nullptr && current->is_Java_thread()) {
|
||||
|
@ -927,8 +927,7 @@ bool Method::is_klass_loaded_by_klass_index(int klass_index) const {
|
||||
Thread *thread = Thread::current();
|
||||
Symbol* klass_name = constants()->klass_name_at(klass_index);
|
||||
Handle loader(thread, method_holder()->class_loader());
|
||||
Handle prot (thread, method_holder()->protection_domain());
|
||||
return SystemDictionary::find_instance_klass(thread, klass_name, loader, prot) != nullptr;
|
||||
return SystemDictionary::find_instance_klass(thread, klass_name, loader) != nullptr;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
@ -321,8 +321,6 @@ JNI_ENTRY(jclass, jni_FindClass(JNIEnv *env, const char *name))
|
||||
SystemDictionary::class_name_symbol(name, vmSymbols::java_lang_NoClassDefFoundError(),
|
||||
CHECK_NULL);
|
||||
|
||||
//%note jni_3
|
||||
Handle protection_domain;
|
||||
// Find calling class
|
||||
Klass* k = thread->security_get_caller_class(0);
|
||||
// default to the system loader when no context
|
||||
@ -344,15 +342,13 @@ JNI_ENTRY(jclass, jni_FindClass(JNIEnv *env, const char *name))
|
||||
if (mirror != nullptr) {
|
||||
Klass* fromClass = java_lang_Class::as_Klass(mirror);
|
||||
loader = Handle(THREAD, fromClass->class_loader());
|
||||
protection_domain = Handle(THREAD, fromClass->protection_domain());
|
||||
}
|
||||
} else {
|
||||
loader = Handle(THREAD, k->class_loader());
|
||||
}
|
||||
}
|
||||
|
||||
result = find_class_from_class_loader(env, class_name, true, loader,
|
||||
protection_domain, true, thread);
|
||||
result = find_class_from_class_loader(env, class_name, true, loader, true, thread);
|
||||
|
||||
if (log_is_enabled(Debug, class, resolve) && result != nullptr) {
|
||||
trace_class_resolution(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(result)));
|
||||
@ -537,8 +533,7 @@ JNI_ENTRY(jint, jni_ThrowNew(JNIEnv *env, jclass clazz, const char *message))
|
||||
InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
|
||||
Symbol* name = k->name();
|
||||
Handle class_loader (THREAD, k->class_loader());
|
||||
Handle protection_domain (THREAD, k->protection_domain());
|
||||
THROW_MSG_LOADER_(name, (char *)message, class_loader, protection_domain, JNI_OK);
|
||||
THROW_MSG_LOADER_(name, (char *)message, class_loader, JNI_OK);
|
||||
ShouldNotReachHere();
|
||||
return 0; // Mute compiler.
|
||||
JNI_END
|
||||
@ -2929,10 +2924,9 @@ static jfieldID bufferCapacityField = nullptr;
|
||||
|
||||
static jclass lookupOne(JNIEnv* env, const char* name, TRAPS) {
|
||||
Handle loader; // null (bootstrap) loader
|
||||
Handle protection_domain; // null protection domain
|
||||
|
||||
TempNewSymbol sym = SymbolTable::new_symbol(name);
|
||||
jclass result = find_class_from_class_loader(env, sym, true, loader, protection_domain, true, CHECK_NULL);
|
||||
jclass result = find_class_from_class_loader(env, sym, true, loader, true, CHECK_NULL);
|
||||
|
||||
if (log_is_enabled(Debug, class, resolve) && result != nullptr) {
|
||||
trace_class_resolution(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(result)));
|
||||
|
@ -151,29 +151,22 @@
|
||||
and thus can only support use of handles passed in.
|
||||
*/
|
||||
|
||||
static void trace_class_resolution_impl(Klass* to_class, TRAPS) {
|
||||
extern void trace_class_resolution(Klass* to_class) {
|
||||
ResourceMark rm;
|
||||
int line_number = -1;
|
||||
const char * source_file = nullptr;
|
||||
const char * trace = "explicit";
|
||||
InstanceKlass* caller = nullptr;
|
||||
JavaThread* jthread = THREAD;
|
||||
JavaThread* jthread = JavaThread::current();
|
||||
if (jthread->has_last_Java_frame()) {
|
||||
vframeStream vfst(jthread);
|
||||
|
||||
// scan up the stack skipping ClassLoader, AccessController and PrivilegedAction frames
|
||||
TempNewSymbol access_controller = SymbolTable::new_symbol("java/security/AccessController");
|
||||
Klass* access_controller_klass = SystemDictionary::resolve_or_fail(access_controller, false, CHECK);
|
||||
TempNewSymbol privileged_action = SymbolTable::new_symbol("java/security/PrivilegedAction");
|
||||
Klass* privileged_action_klass = SystemDictionary::resolve_or_fail(privileged_action, false, CHECK);
|
||||
|
||||
// Scan up the stack skipping ClassLoader frames.
|
||||
Method* last_caller = nullptr;
|
||||
|
||||
while (!vfst.at_end()) {
|
||||
Method* m = vfst.method();
|
||||
if (!vfst.method()->method_holder()->is_subclass_of(vmClasses::ClassLoader_klass())&&
|
||||
!vfst.method()->method_holder()->is_subclass_of(access_controller_klass) &&
|
||||
!vfst.method()->method_holder()->is_subclass_of(privileged_action_klass)) {
|
||||
if (!vfst.method()->method_holder()->is_subclass_of(vmClasses::ClassLoader_klass())) {
|
||||
break;
|
||||
}
|
||||
last_caller = m;
|
||||
@ -232,14 +225,6 @@ static void trace_class_resolution_impl(Klass* to_class, TRAPS) {
|
||||
}
|
||||
}
|
||||
|
||||
void trace_class_resolution(Klass* to_class) {
|
||||
EXCEPTION_MARK;
|
||||
trace_class_resolution_impl(to_class, THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
}
|
||||
}
|
||||
|
||||
// java.lang.System //////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@ -833,20 +818,10 @@ JVM_ENTRY(jclass, JVM_FindClassFromCaller(JNIEnv* env, const char* name,
|
||||
|
||||
oop loader_oop = JNIHandles::resolve(loader);
|
||||
oop from_class = JNIHandles::resolve(caller);
|
||||
oop protection_domain = nullptr;
|
||||
// If loader is null, shouldn't call ClassLoader.checkPackageAccess; otherwise get
|
||||
// NPE. Put it in another way, the bootstrap class loader has all permission and
|
||||
// thus no checkPackageAccess equivalence in the VM class loader.
|
||||
// The caller is also passed as null by the java code if there is no security
|
||||
// manager to avoid the performance cost of getting the calling class.
|
||||
if (from_class != nullptr && loader_oop != nullptr) {
|
||||
protection_domain = java_lang_Class::as_Klass(from_class)->protection_domain();
|
||||
}
|
||||
|
||||
Handle h_loader(THREAD, loader_oop);
|
||||
Handle h_prot(THREAD, protection_domain);
|
||||
|
||||
jclass result = find_class_from_class_loader(env, h_name, init, h_loader,
|
||||
h_prot, false, THREAD);
|
||||
false, THREAD);
|
||||
|
||||
if (log_is_enabled(Debug, class, resolve) && result != nullptr) {
|
||||
trace_class_resolution(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(result)));
|
||||
@ -865,15 +840,11 @@ JVM_ENTRY(jclass, JVM_FindClassFromClass(JNIEnv *env, const char *name,
|
||||
? (Klass*)nullptr
|
||||
: java_lang_Class::as_Klass(from_class_oop);
|
||||
oop class_loader = nullptr;
|
||||
oop protection_domain = nullptr;
|
||||
if (from_class != nullptr) {
|
||||
class_loader = from_class->class_loader();
|
||||
protection_domain = from_class->protection_domain();
|
||||
}
|
||||
Handle h_loader(THREAD, class_loader);
|
||||
Handle h_prot (THREAD, protection_domain);
|
||||
jclass result = find_class_from_class_loader(env, h_name, init, h_loader,
|
||||
h_prot, true, thread);
|
||||
jclass result = find_class_from_class_loader(env, h_name, init, h_loader, true, thread);
|
||||
|
||||
if (log_is_enabled(Debug, class, resolve) && result != nullptr) {
|
||||
// this function is generally only used for class loading during verification.
|
||||
@ -1121,9 +1092,7 @@ JVM_ENTRY(jclass, JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name)
|
||||
// The Java level wrapper will perform the necessary security check allowing
|
||||
// us to pass the null as the initiating class loader.
|
||||
Handle h_loader(THREAD, JNIHandles::resolve(loader));
|
||||
Klass* k = SystemDictionary::find_instance_or_array_klass(THREAD, klass_name,
|
||||
h_loader,
|
||||
Handle());
|
||||
Klass* k = SystemDictionary::find_instance_or_array_klass(THREAD, klass_name, h_loader);
|
||||
#if INCLUDE_CDS
|
||||
if (k == nullptr) {
|
||||
// If the class is not already loaded, try to see if it's in the shared
|
||||
@ -3069,45 +3038,6 @@ JVM_ENTRY(void, JVM_SetScopedValueCache(JNIEnv* env, jclass threadClass,
|
||||
thread->set_scopedValueCache(objs);
|
||||
JVM_END
|
||||
|
||||
// java.lang.SecurityManager ///////////////////////////////////////////////////////////////////////
|
||||
|
||||
JVM_ENTRY(jobjectArray, JVM_GetClassContext(JNIEnv *env))
|
||||
ResourceMark rm(THREAD);
|
||||
JvmtiVMObjectAllocEventCollector oam;
|
||||
vframeStream vfst(thread);
|
||||
|
||||
if (vmClasses::reflect_CallerSensitive_klass() != nullptr) {
|
||||
// This must only be called from SecurityManager.getClassContext
|
||||
Method* m = vfst.method();
|
||||
if (!(m->method_holder() == vmClasses::SecurityManager_klass() &&
|
||||
m->name() == vmSymbols::getClassContext_name() &&
|
||||
m->signature() == vmSymbols::void_class_array_signature())) {
|
||||
THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "JVM_GetClassContext must only be called from SecurityManager.getClassContext");
|
||||
}
|
||||
}
|
||||
|
||||
// Collect method holders
|
||||
GrowableArray<Klass*>* klass_array = new GrowableArray<Klass*>();
|
||||
for (; !vfst.at_end(); vfst.security_next()) {
|
||||
Method* m = vfst.method();
|
||||
// Native frames are not returned
|
||||
if (!m->is_ignored_by_security_stack_walk() && !m->is_native()) {
|
||||
Klass* holder = m->method_holder();
|
||||
assert(holder->is_klass(), "just checking");
|
||||
klass_array->append(holder);
|
||||
}
|
||||
}
|
||||
|
||||
// Create result array of type [Ljava/lang/Class;
|
||||
objArrayOop result = oopFactory::new_objArray(vmClasses::Class_klass(), klass_array->length(), CHECK_NULL);
|
||||
// Fill in mirrors corresponding to method holders
|
||||
for (int i = 0; i < klass_array->length(); i++) {
|
||||
result->obj_at_put(i, klass_array->at(i)->java_mirror());
|
||||
}
|
||||
|
||||
return (jobjectArray) JNIHandles::make_local(THREAD, result);
|
||||
JVM_END
|
||||
|
||||
|
||||
// java.lang.Package ////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -3421,15 +3351,8 @@ JNIEXPORT void JNICALL JVM_RawMonitorExit(void *mon) {
|
||||
// Shared JNI/JVM entry points //////////////////////////////////////////////////////////////
|
||||
|
||||
jclass find_class_from_class_loader(JNIEnv* env, Symbol* name, jboolean init,
|
||||
Handle loader, Handle protection_domain,
|
||||
jboolean throwError, TRAPS) {
|
||||
// Security Note:
|
||||
// The Java level wrapper will perform the necessary security check allowing
|
||||
// us to pass the null as the initiating class loader. The VM is responsible for
|
||||
// the checkPackageAccess relative to the initiating class loader via the
|
||||
// protection_domain. The protection_domain is passed as null by the java code
|
||||
// if there is no security manager in 3-arg Class.forName().
|
||||
Klass* klass = SystemDictionary::resolve_or_fail(name, loader, protection_domain, throwError != 0, CHECK_NULL);
|
||||
Handle loader, jboolean throwError, TRAPS) {
|
||||
Klass* klass = SystemDictionary::resolve_or_fail(name, loader, throwError != 0, CHECK_NULL);
|
||||
|
||||
// Check if we should initialize the class
|
||||
if (init && klass->is_instance_klass()) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2024, Oracle and/or its affiliates. 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
|
||||
@ -31,7 +31,7 @@
|
||||
// Useful entry points shared by JNI and JVM interface.
|
||||
// We do not allow real JNI or JVM entry point to call each other.
|
||||
|
||||
jclass find_class_from_class_loader(JNIEnv* env, Symbol* name, jboolean init, Handle loader, Handle protection_domain, jboolean throwError, TRAPS);
|
||||
jclass find_class_from_class_loader(JNIEnv* env, Symbol* name, jboolean init, Handle loader, jboolean throwError, TRAPS);
|
||||
|
||||
void trace_class_resolution(Klass* to_class);
|
||||
|
||||
|
@ -35,7 +35,6 @@
|
||||
#include "classfile/classPrinter.hpp"
|
||||
#include "classfile/javaClasses.inline.hpp"
|
||||
#include "classfile/modules.hpp"
|
||||
#include "classfile/protectionDomainCache.hpp"
|
||||
#include "classfile/stringTable.hpp"
|
||||
#include "classfile/symbolTable.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
@ -2536,10 +2535,6 @@ WB_ENTRY(jlong, WB_ResolvedMethodItemsCount(JNIEnv* env, jobject o))
|
||||
return (jlong) ResolvedMethodTable::items_count();
|
||||
WB_END
|
||||
|
||||
WB_ENTRY(jint, WB_ProtectionDomainRemovedCount(JNIEnv* env, jobject o))
|
||||
return (jint) ProtectionDomainCacheTable::removed_entries_count();
|
||||
WB_END
|
||||
|
||||
WB_ENTRY(jint, WB_GetKlassMetadataSize(JNIEnv* env, jobject wb, jclass mirror))
|
||||
Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(mirror));
|
||||
// Return size in bytes.
|
||||
@ -2966,7 +2961,6 @@ static JNINativeMethod methods[] = {
|
||||
{CC"printOsInfo", CC"()V", (void*)&WB_PrintOsInfo },
|
||||
{CC"disableElfSectionCache", CC"()V", (void*)&WB_DisableElfSectionCache },
|
||||
{CC"resolvedMethodItemsCount", CC"()J", (void*)&WB_ResolvedMethodItemsCount },
|
||||
{CC"protectionDomainRemovedCount", CC"()I", (void*)&WB_ProtectionDomainRemovedCount },
|
||||
{CC"getKlassMetadataSize", CC"(Ljava/lang/Class;)I",(void*)&WB_GetKlassMetadataSize},
|
||||
|
||||
{CC"createMetaspaceTestContext", CC"(JJ)J", (void*)&WB_CreateMetaspaceTestContext},
|
||||
|
@ -1065,7 +1065,7 @@ protected:
|
||||
static InstanceKlass* find_cache_klass(Thread* thread, Symbol* klass_name) {
|
||||
ResourceMark rm(thread);
|
||||
char* klass_name_str = klass_name->as_C_string();
|
||||
InstanceKlass* ik = SystemDictionary::find_instance_klass(thread, klass_name, Handle(), Handle());
|
||||
InstanceKlass* ik = SystemDictionary::find_instance_klass(thread, klass_name, Handle());
|
||||
guarantee(ik != nullptr, "%s must be loaded", klass_name_str);
|
||||
if (!ik->is_in_error_state()) {
|
||||
guarantee(ik->is_initialized(), "%s must be initialized", klass_name_str);
|
||||
|
@ -25,11 +25,8 @@
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/classLoaderDataGraph.inline.hpp"
|
||||
#include "classfile/javaClasses.hpp"
|
||||
#include "classfile/protectionDomainCache.hpp"
|
||||
#include "classfile/stringTable.hpp"
|
||||
#include "classfile/symbolTable.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "classfile/vmClasses.hpp"
|
||||
#include "gc/shared/oopStorage.hpp"
|
||||
#include "gc/shared/oopStorageSet.hpp"
|
||||
#include "interpreter/oopMapCache.hpp"
|
||||
@ -40,15 +37,10 @@
|
||||
#include "prims/resolvedMethodTable.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
#include "runtime/interfaceSupport.inline.hpp"
|
||||
#include "runtime/java.hpp"
|
||||
#include "runtime/javaCalls.hpp"
|
||||
#include "runtime/jniHandles.hpp"
|
||||
#include "runtime/lightweightSynchronizer.hpp"
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "runtime/serviceThread.hpp"
|
||||
#include "services/diagnosticArgument.hpp"
|
||||
#include "services/diagnosticFramework.hpp"
|
||||
#include "services/finalizerService.hpp"
|
||||
#include "services/gcNotifier.hpp"
|
||||
#include "services/lowMemoryDetector.hpp"
|
||||
@ -88,7 +80,6 @@ void ServiceThread::service_thread_entry(JavaThread* jt, TRAPS) {
|
||||
bool finalizerservice_work = false;
|
||||
bool resolved_method_table_work = false;
|
||||
bool thread_id_table_work = false;
|
||||
bool protection_domain_table_work = false;
|
||||
bool oopstorage_work = false;
|
||||
JvmtiDeferredEvent jvmti_event;
|
||||
bool oop_handles_to_release = false;
|
||||
@ -118,7 +109,6 @@ void ServiceThread::service_thread_entry(JavaThread* jt, TRAPS) {
|
||||
(finalizerservice_work = FinalizerService::has_work()) |
|
||||
(resolved_method_table_work = ResolvedMethodTable::has_work()) |
|
||||
(thread_id_table_work = ThreadIdTable::has_work()) |
|
||||
(protection_domain_table_work = ProtectionDomainCacheTable::has_work()) |
|
||||
(oopstorage_work = OopStorage::has_cleanup_work_and_reset()) |
|
||||
(oop_handles_to_release = JavaThread::has_oop_handles_to_release()) |
|
||||
(cldg_cleanup_work = ClassLoaderDataGraph::should_clean_metaspaces_and_reset()) |
|
||||
@ -163,10 +153,6 @@ void ServiceThread::service_thread_entry(JavaThread* jt, TRAPS) {
|
||||
ThreadIdTable::do_concurrent_work(jt);
|
||||
}
|
||||
|
||||
if (protection_domain_table_work) {
|
||||
ProtectionDomainCacheTable::unlink();
|
||||
}
|
||||
|
||||
if (oopstorage_work) {
|
||||
cleanup_oopstorages();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. 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
|
||||
@ -501,8 +501,7 @@ Symbol* SignatureStream::find_symbol() {
|
||||
return name;
|
||||
}
|
||||
|
||||
Klass* SignatureStream::as_klass(Handle class_loader, Handle protection_domain,
|
||||
FailureMode failure_mode, TRAPS) {
|
||||
Klass* SignatureStream::as_klass(Handle class_loader, FailureMode failure_mode, TRAPS) {
|
||||
if (!is_reference()) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -511,11 +510,11 @@ Klass* SignatureStream::as_klass(Handle class_loader, Handle protection_domain,
|
||||
if (failure_mode == ReturnNull) {
|
||||
// Note: SD::resolve_or_null returns null for most failure modes,
|
||||
// but not all. Circularity errors, invalid PDs, etc., throw.
|
||||
k = SystemDictionary::resolve_or_null(name, class_loader, protection_domain, CHECK_NULL);
|
||||
k = SystemDictionary::resolve_or_null(name, class_loader, CHECK_NULL);
|
||||
} else if (failure_mode == CachedOrNull) {
|
||||
NoSafepointVerifier nsv; // no loading, now, we mean it!
|
||||
assert(!HAS_PENDING_EXCEPTION, "");
|
||||
k = SystemDictionary::find_instance_klass(THREAD, name, class_loader, protection_domain);
|
||||
k = SystemDictionary::find_instance_klass(THREAD, name, class_loader);
|
||||
// SD::find does not trigger loading, so there should be no throws
|
||||
// Still, bad things can happen, so we CHECK_NULL and ask callers
|
||||
// to do likewise.
|
||||
@ -525,18 +524,17 @@ Klass* SignatureStream::as_klass(Handle class_loader, Handle protection_domain,
|
||||
// The test here allows for an additional mode CNFException
|
||||
// if callers need to request the reflective error instead.
|
||||
bool throw_error = (failure_mode == NCDFError);
|
||||
k = SystemDictionary::resolve_or_fail(name, class_loader, protection_domain, throw_error, CHECK_NULL);
|
||||
k = SystemDictionary::resolve_or_fail(name, class_loader, throw_error, CHECK_NULL);
|
||||
}
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
oop SignatureStream::as_java_mirror(Handle class_loader, Handle protection_domain,
|
||||
FailureMode failure_mode, TRAPS) {
|
||||
oop SignatureStream::as_java_mirror(Handle class_loader, FailureMode failure_mode, TRAPS) {
|
||||
if (!is_reference()) {
|
||||
return Universe::java_mirror(type());
|
||||
}
|
||||
Klass* klass = as_klass(class_loader, protection_domain, failure_mode, CHECK_NULL);
|
||||
Klass* klass = as_klass(class_loader, failure_mode, CHECK_NULL);
|
||||
if (klass == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -551,10 +549,8 @@ void SignatureStream::skip_to_return_type() {
|
||||
|
||||
ResolvingSignatureStream::ResolvingSignatureStream(Symbol* signature,
|
||||
Handle class_loader,
|
||||
Handle protection_domain,
|
||||
bool is_method)
|
||||
: SignatureStream(signature, is_method),
|
||||
_class_loader(class_loader), _protection_domain(protection_domain)
|
||||
: SignatureStream(signature, is_method), _class_loader(class_loader)
|
||||
{
|
||||
initialize_load_origin(nullptr);
|
||||
}
|
||||
@ -576,7 +572,6 @@ void ResolvingSignatureStream::cache_handles() {
|
||||
assert(_load_origin != nullptr, "");
|
||||
JavaThread* current = JavaThread::current();
|
||||
_class_loader = Handle(current, _load_origin->class_loader());
|
||||
_protection_domain = Handle(current, _load_origin->protection_domain());
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, Azul Systems, Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -562,8 +562,8 @@ class SignatureStream : public StackObj {
|
||||
|
||||
// free-standing lookups (bring your own CL/PD pair)
|
||||
enum FailureMode { ReturnNull, NCDFError, CachedOrNull };
|
||||
Klass* as_klass(Handle class_loader, Handle protection_domain, FailureMode failure_mode, TRAPS);
|
||||
oop as_java_mirror(Handle class_loader, Handle protection_domain, FailureMode failure_mode, TRAPS);
|
||||
Klass* as_klass(Handle class_loader, FailureMode failure_mode, TRAPS);
|
||||
oop as_java_mirror(Handle class_loader, FailureMode failure_mode, TRAPS);
|
||||
};
|
||||
|
||||
// Specialized SignatureStream: used for invoking SystemDictionary to either find
|
||||
@ -573,7 +573,6 @@ class ResolvingSignatureStream : public SignatureStream {
|
||||
Klass* _load_origin;
|
||||
bool _handles_cached;
|
||||
Handle _class_loader; // cached when needed
|
||||
Handle _protection_domain; // cached when needed
|
||||
|
||||
void initialize_load_origin(Klass* load_origin) {
|
||||
_load_origin = load_origin;
|
||||
@ -589,20 +588,18 @@ class ResolvingSignatureStream : public SignatureStream {
|
||||
|
||||
public:
|
||||
ResolvingSignatureStream(Symbol* signature, Klass* load_origin, bool is_method = true);
|
||||
ResolvingSignatureStream(Symbol* signature, Handle class_loader, Handle protection_domain, bool is_method = true);
|
||||
ResolvingSignatureStream(Symbol* signature, Handle class_loader, bool is_method = true);
|
||||
ResolvingSignatureStream(const Method* method);
|
||||
|
||||
Klass* as_klass(FailureMode failure_mode, TRAPS) {
|
||||
need_handles();
|
||||
return SignatureStream::as_klass(_class_loader, _protection_domain,
|
||||
failure_mode, THREAD);
|
||||
return SignatureStream::as_klass(_class_loader, failure_mode, THREAD);
|
||||
}
|
||||
oop as_java_mirror(FailureMode failure_mode, TRAPS) {
|
||||
if (is_reference()) {
|
||||
need_handles();
|
||||
}
|
||||
return SignatureStream::as_java_mirror(_class_loader, _protection_domain,
|
||||
failure_mode, THREAD);
|
||||
return SignatureStream::as_java_mirror(_class_loader, failure_mode, THREAD);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -385,7 +385,7 @@ void Threads::initialize_java_lang_classes(JavaThread* main_thread, TRAPS) {
|
||||
// Some values are actually configure-time constants but some can be set via the jlink tool and
|
||||
// so must be read dynamically. We treat them all the same.
|
||||
InstanceKlass* ik = SystemDictionary::find_instance_klass(THREAD, vmSymbols::java_lang_VersionProps(),
|
||||
Handle(), Handle());
|
||||
Handle());
|
||||
{
|
||||
ResourceMark rm(main_thread);
|
||||
JDK_Version::set_java_version(get_java_version_info(ik, vmSymbols::java_version_name()));
|
||||
|
@ -532,8 +532,7 @@ vframeStream::vframeStream(oop continuation, Handle continuation_scope)
|
||||
|
||||
|
||||
// Step back n frames, skip any pseudo frames in between.
|
||||
// This function is used in Class.forName, Class.newInstance, Method.Invoke,
|
||||
// AccessController.doPrivileged.
|
||||
// This function is used in Class.forName, Class.newInstance, and Method.Invoke.
|
||||
void vframeStreamCommon::security_get_caller_frame(int depth) {
|
||||
assert(depth >= 0, "invalid depth: %d", depth);
|
||||
for (int n = 0; !at_end(); security_next()) {
|
||||
|
@ -695,7 +695,7 @@ void JMXStartRemoteDCmd::execute(DCmdSource source, TRAPS) {
|
||||
|
||||
loadAgentModule(CHECK);
|
||||
Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
|
||||
Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK);
|
||||
Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, true, CHECK);
|
||||
|
||||
JavaValue result(T_VOID);
|
||||
|
||||
@ -768,7 +768,7 @@ void JMXStartLocalDCmd::execute(DCmdSource source, TRAPS) {
|
||||
|
||||
loadAgentModule(CHECK);
|
||||
Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
|
||||
Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK);
|
||||
Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, true, CHECK);
|
||||
|
||||
JavaValue result(T_VOID);
|
||||
JavaCalls::call_static(&result, k, vmSymbols::startLocalAgent_name(), vmSymbols::void_method_signature(), CHECK);
|
||||
@ -785,7 +785,7 @@ void JMXStopRemoteDCmd::execute(DCmdSource source, TRAPS) {
|
||||
|
||||
loadAgentModule(CHECK);
|
||||
Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
|
||||
Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK);
|
||||
Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, true, CHECK);
|
||||
|
||||
JavaValue result(T_VOID);
|
||||
JavaCalls::call_static(&result, k, vmSymbols::stopRemoteAgent_name(), vmSymbols::void_method_signature(), CHECK);
|
||||
@ -806,7 +806,7 @@ void JMXStatusDCmd::execute(DCmdSource source, TRAPS) {
|
||||
|
||||
loadAgentModule(CHECK);
|
||||
Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
|
||||
Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, Handle(), true, CHECK);
|
||||
Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_agent_Agent(), loader, true, CHECK);
|
||||
|
||||
JavaValue result(T_OBJECT);
|
||||
JavaCalls::call_static(&result, k, vmSymbols::getAgentStatus_name(), vmSymbols::void_string_signature(), CHECK);
|
||||
|
@ -160,7 +160,6 @@ void Management::initialize(TRAPS) {
|
||||
Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
|
||||
Klass* k = SystemDictionary::resolve_or_null(vmSymbols::jdk_internal_agent_Agent(),
|
||||
loader,
|
||||
Handle(),
|
||||
THREAD);
|
||||
if (k == nullptr) {
|
||||
vm_exit_during_initialization("Management agent initialization failure: "
|
||||
|
@ -188,30 +188,30 @@ void Exceptions::_throw(JavaThread* thread, const char* file, int line, Handle h
|
||||
|
||||
|
||||
void Exceptions::_throw_msg(JavaThread* thread, const char* file, int line, Symbol* name, const char* message,
|
||||
Handle h_loader, Handle h_protection_domain) {
|
||||
Handle h_loader) {
|
||||
// Check for special boot-strapping/compiler-thread handling
|
||||
if (special_exception(thread, file, line, Handle(), name, message)) return;
|
||||
// Create and throw exception
|
||||
Handle h_cause(thread, nullptr);
|
||||
Handle h_exception = new_exception(thread, name, message, h_cause, h_loader, h_protection_domain);
|
||||
Handle h_exception = new_exception(thread, name, message, h_cause, h_loader);
|
||||
_throw(thread, file, line, h_exception, message);
|
||||
}
|
||||
|
||||
void Exceptions::_throw_msg_cause(JavaThread* thread, const char* file, int line, Symbol* name, const char* message, Handle h_cause,
|
||||
Handle h_loader, Handle h_protection_domain) {
|
||||
Handle h_loader) {
|
||||
// Check for special boot-strapping/compiler-thread handling
|
||||
if (special_exception(thread, file, line, Handle(), name, message)) return;
|
||||
// Create and throw exception and init cause
|
||||
Handle h_exception = new_exception(thread, name, message, h_cause, h_loader, h_protection_domain);
|
||||
Handle h_exception = new_exception(thread, name, message, h_cause, h_loader);
|
||||
_throw(thread, file, line, h_exception, message);
|
||||
}
|
||||
|
||||
void Exceptions::_throw_cause(JavaThread* thread, const char* file, int line, Symbol* name, Handle h_cause,
|
||||
Handle h_loader, Handle h_protection_domain) {
|
||||
Handle h_loader) {
|
||||
// Check for special boot-strapping/compiler-thread handling
|
||||
if (special_exception(thread, file, line, Handle(), name)) return;
|
||||
// Create and throw exception
|
||||
Handle h_exception = new_exception(thread, name, h_cause, h_loader, h_protection_domain);
|
||||
Handle h_exception = new_exception(thread, name, h_cause, h_loader);
|
||||
_throw(thread, file, line, h_exception, nullptr);
|
||||
}
|
||||
|
||||
@ -229,13 +229,13 @@ void Exceptions::_throw_args(JavaThread* thread, const char* file, int line, Sym
|
||||
// Methods for default parameters.
|
||||
// NOTE: These must be here (and not in the header file) because of include circularities.
|
||||
void Exceptions::_throw_msg_cause(JavaThread* thread, const char* file, int line, Symbol* name, const char* message, Handle h_cause) {
|
||||
_throw_msg_cause(thread, file, line, name, message, h_cause, Handle(thread, nullptr), Handle(thread, nullptr));
|
||||
_throw_msg_cause(thread, file, line, name, message, h_cause, Handle());
|
||||
}
|
||||
void Exceptions::_throw_msg(JavaThread* thread, const char* file, int line, Symbol* name, const char* message) {
|
||||
_throw_msg(thread, file, line, name, message, Handle(thread, nullptr), Handle(thread, nullptr));
|
||||
_throw_msg(thread, file, line, name, message, Handle());
|
||||
}
|
||||
void Exceptions::_throw_cause(JavaThread* thread, const char* file, int line, Symbol* name, Handle h_cause) {
|
||||
_throw_cause(thread, file, line, name, h_cause, Handle(thread, nullptr), Handle(thread, nullptr));
|
||||
_throw_cause(thread, file, line, name, h_cause, Handle());
|
||||
}
|
||||
|
||||
|
||||
@ -297,7 +297,7 @@ void Exceptions::fthrow(JavaThread* thread, const char* file, int line, Symbol*
|
||||
// and returns a Handle
|
||||
Handle Exceptions::new_exception(JavaThread* thread, Symbol* name,
|
||||
Symbol* signature, JavaCallArguments *args,
|
||||
Handle h_loader, Handle h_protection_domain) {
|
||||
Handle h_loader) {
|
||||
assert(Universe::is_fully_initialized(),
|
||||
"cannot be called during initialization");
|
||||
assert(!thread->has_pending_exception(), "already has exception");
|
||||
@ -305,7 +305,7 @@ Handle Exceptions::new_exception(JavaThread* thread, Symbol* name,
|
||||
Handle h_exception;
|
||||
|
||||
// Resolve exception klass, and check for pending exception below.
|
||||
Klass* klass = SystemDictionary::resolve_or_fail(name, h_loader, h_protection_domain, true, thread);
|
||||
Klass* klass = SystemDictionary::resolve_or_fail(name, h_loader, true, thread);
|
||||
|
||||
if (!thread->has_pending_exception()) {
|
||||
assert(klass != nullptr, "klass must exist");
|
||||
@ -329,8 +329,8 @@ Handle Exceptions::new_exception(JavaThread* thread, Symbol* name,
|
||||
Handle Exceptions::new_exception(JavaThread* thread, Symbol* name,
|
||||
Symbol* signature, JavaCallArguments *args,
|
||||
Handle h_cause,
|
||||
Handle h_loader, Handle h_protection_domain) {
|
||||
Handle h_exception = new_exception(thread, name, signature, args, h_loader, h_protection_domain);
|
||||
Handle h_loader) {
|
||||
Handle h_exception = new_exception(thread, name, signature, args, h_loader);
|
||||
|
||||
// Future: object initializer should take a cause argument
|
||||
if (h_cause.not_null()) {
|
||||
@ -359,7 +359,7 @@ Handle Exceptions::new_exception(JavaThread* thread, Symbol* name,
|
||||
// creating a new exception
|
||||
Handle Exceptions::new_exception(JavaThread* thread, Symbol* name,
|
||||
Handle h_cause,
|
||||
Handle h_loader, Handle h_protection_domain,
|
||||
Handle h_loader,
|
||||
ExceptionMsgToUtf8Mode to_utf8_safe) {
|
||||
JavaCallArguments args;
|
||||
Symbol* signature = nullptr;
|
||||
@ -369,14 +369,14 @@ Handle Exceptions::new_exception(JavaThread* thread, Symbol* name,
|
||||
signature = vmSymbols::throwable_void_signature();
|
||||
args.push_oop(h_cause);
|
||||
}
|
||||
return new_exception(thread, name, signature, &args, h_loader, h_protection_domain);
|
||||
return new_exception(thread, name, signature, &args, h_loader);
|
||||
}
|
||||
|
||||
// Convenience method. Calls either the <init>() or <init>(String) method when
|
||||
// creating a new exception
|
||||
Handle Exceptions::new_exception(JavaThread* thread, Symbol* name,
|
||||
const char* message, Handle h_cause,
|
||||
Handle h_loader, Handle h_protection_domain,
|
||||
Handle h_loader,
|
||||
ExceptionMsgToUtf8Mode to_utf8_safe) {
|
||||
JavaCallArguments args;
|
||||
Symbol* signature = nullptr;
|
||||
@ -413,11 +413,10 @@ Handle Exceptions::new_exception(JavaThread* thread, Symbol* name,
|
||||
args.push_oop(msg);
|
||||
signature = vmSymbols::string_void_signature();
|
||||
}
|
||||
return new_exception(thread, name, signature, &args, h_cause, h_loader, h_protection_domain);
|
||||
return new_exception(thread, name, signature, &args, h_cause, h_loader);
|
||||
}
|
||||
|
||||
// Another convenience method that creates handles for null class loaders and
|
||||
// protection domains and null causes.
|
||||
// Another convenience method that creates handles for null class loaders and null causes.
|
||||
// If the last parameter 'to_utf8_mode' is safe_to_utf8,
|
||||
// it means we can safely ignore the encoding scheme of the message string and
|
||||
// convert it directly to a java UTF8 string. Otherwise, we need to take the
|
||||
@ -428,11 +427,10 @@ Handle Exceptions::new_exception(JavaThread* thread, Symbol* name,
|
||||
const char* message,
|
||||
ExceptionMsgToUtf8Mode to_utf8_safe) {
|
||||
|
||||
Handle h_loader(thread, nullptr);
|
||||
Handle h_prot(thread, nullptr);
|
||||
Handle h_cause(thread, nullptr);
|
||||
Handle h_loader;
|
||||
Handle h_cause;
|
||||
return Exceptions::new_exception(thread, name, message, h_cause, h_loader,
|
||||
h_prot, to_utf8_safe);
|
||||
to_utf8_safe);
|
||||
}
|
||||
|
||||
// invokedynamic uses wrap_dynamic_exception for:
|
||||
|
@ -128,15 +128,15 @@ class Exceptions {
|
||||
|
||||
static void _throw_msg(JavaThread* thread, const char* file, int line, Symbol* name, const char* message);
|
||||
static void _throw_msg(JavaThread* thread, const char* file, int line, Symbol* name, const char* message,
|
||||
Handle loader, Handle protection_domain);
|
||||
Handle loader);
|
||||
|
||||
static void _throw_msg_cause(JavaThread* thread, const char* file, int line, Symbol* name, const char* message, Handle h_cause);
|
||||
static void _throw_msg_cause(JavaThread* thread, const char* file, int line, Symbol* name, const char* message, Handle h_cause,
|
||||
Handle h_loader, Handle h_protection_domain);
|
||||
Handle h_loader);
|
||||
|
||||
static void _throw_cause(JavaThread* thread, const char* file, int line, Symbol* name, Handle h_cause);
|
||||
static void _throw_cause(JavaThread* thread, const char* file, int line, Symbol* name, Handle h_cause,
|
||||
Handle h_loader, Handle h_protection_domain);
|
||||
Handle h_loader);
|
||||
|
||||
static void _throw_args(JavaThread* thread, const char* file, int line,
|
||||
Symbol* name, Symbol* signature,
|
||||
@ -150,21 +150,21 @@ class Exceptions {
|
||||
// Create and initialize a new exception
|
||||
static Handle new_exception(JavaThread* thread, Symbol* name,
|
||||
Symbol* signature, JavaCallArguments* args,
|
||||
Handle loader, Handle protection_domain);
|
||||
Handle loader);
|
||||
|
||||
static Handle new_exception(JavaThread* thread, Symbol* name,
|
||||
Symbol* signature, JavaCallArguments* args,
|
||||
Handle cause,
|
||||
Handle loader, Handle protection_domain);
|
||||
Handle loader);
|
||||
|
||||
static Handle new_exception(JavaThread* thread, Symbol* name,
|
||||
Handle cause,
|
||||
Handle loader, Handle protection_domain,
|
||||
Handle loader,
|
||||
ExceptionMsgToUtf8Mode to_utf8_safe = safe_to_utf8);
|
||||
|
||||
static Handle new_exception(JavaThread* thread, Symbol* name,
|
||||
const char* message, Handle cause,
|
||||
Handle loader, Handle protection_domain,
|
||||
Handle loader,
|
||||
ExceptionMsgToUtf8Mode to_utf8_safe = safe_to_utf8);
|
||||
|
||||
static Handle new_exception(JavaThread* thread, Symbol* name,
|
||||
@ -268,8 +268,8 @@ class Exceptions {
|
||||
#define THROW_CAUSE(name, cause) \
|
||||
{ Exceptions::_throw_cause(THREAD_AND_LOCATION, name, cause); return; }
|
||||
|
||||
#define THROW_MSG_LOADER(name, message, loader, protection_domain) \
|
||||
{ Exceptions::_throw_msg(THREAD_AND_LOCATION, name, message, loader, protection_domain); return; }
|
||||
#define THROW_MSG_LOADER(name, message, loader) \
|
||||
{ Exceptions::_throw_msg(THREAD_AND_LOCATION, name, message, loader); return; }
|
||||
|
||||
#define THROW_ARG(name, signature, args) \
|
||||
{ Exceptions::_throw_args(THREAD_AND_LOCATION, name, signature, args); return; }
|
||||
@ -286,8 +286,8 @@ class Exceptions {
|
||||
#define THROW_MSG_(name, message, result) \
|
||||
{ Exceptions::_throw_msg(THREAD_AND_LOCATION, name, message); return result; }
|
||||
|
||||
#define THROW_MSG_LOADER_(name, message, loader, protection_domain, result) \
|
||||
{ Exceptions::_throw_msg(THREAD_AND_LOCATION, name, message, loader, protection_domain); return result; }
|
||||
#define THROW_MSG_LOADER_(name, message, loader, result) \
|
||||
{ Exceptions::_throw_msg(THREAD_AND_LOCATION, name, message, loader); return result; }
|
||||
|
||||
#define THROW_ARG_(name, signature, args, result) \
|
||||
{ Exceptions::_throw_args(THREAD_AND_LOCATION, name, signature, args); return result; }
|
||||
|
@ -113,9 +113,6 @@ runtime/ErrorHandling/CreateCoredumpOnCrash.java 8267433 macosx-x64
|
||||
runtime/StackGuardPages/TestStackGuardPagesNative.java 8303612 linux-all
|
||||
runtime/ErrorHandling/MachCodeFramesInErrorFile.java 8313315 linux-ppc64le
|
||||
runtime/cds/appcds/customLoader/HelloCustom_JFR.java 8241075 linux-all,windows-x64
|
||||
runtime/Dictionary/CleanProtectionDomain.java 8341916 generic-all
|
||||
runtime/Dictionary/ProtectionDomainCacheTest.java 8341916 generic-all
|
||||
runtime/logging/ProtectionDomainVerificationTest.java 8341916 generic-all
|
||||
runtime/NMT/VirtualAllocCommitMerge.java 8309698 linux-s390x
|
||||
|
||||
# Fails with +UseCompactObjectHeaders on aarch64
|
||||
|
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Verifies the creation and cleaup of entries in the Protection Domain Table
|
||||
* @requires vm.flagless
|
||||
* @library /test/lib
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @build jdk.test.whitebox.WhiteBox
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
|
||||
* @run driver CleanProtectionDomain
|
||||
*/
|
||||
|
||||
import java.security.ProtectionDomain;
|
||||
import jdk.test.lib.compiler.InMemoryJavaCompiler;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
import static jdk.test.lib.Asserts.*;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.whitebox.WhiteBox;
|
||||
|
||||
public class CleanProtectionDomain {
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(
|
||||
"-Xlog:protectiondomain+table=debug",
|
||||
"--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED",
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:+WhiteBoxAPI",
|
||||
"-Xbootclasspath/a:.",
|
||||
"-Djava.security.manager=allow",
|
||||
Test.class.getName());
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
output.shouldContain("protection domain added");
|
||||
output.shouldContain("protection domain unlinked");
|
||||
output.shouldHaveExitValue(0);
|
||||
}
|
||||
|
||||
static class Test {
|
||||
public static void test() throws Exception {
|
||||
TestClassLoader classloader = new TestClassLoader();
|
||||
ProtectionDomain pd = new ProtectionDomain(null, null);
|
||||
byte klassbuf[] = InMemoryJavaCompiler.compile("TestClass", "class TestClass { }");
|
||||
Class<?> klass = classloader.defineClass("TestClass", klassbuf, pd);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
WhiteBox wb = WhiteBox.getWhiteBox();
|
||||
int removedCountOrig = wb.protectionDomainRemovedCount();
|
||||
int removedCount;
|
||||
|
||||
test();
|
||||
|
||||
// Wait until ServiceThread cleans ProtectionDomain table.
|
||||
// When the TestClassLoader is unloaded by GC, at least one
|
||||
// ProtectionDomainCacheEntry will be eligible for removal.
|
||||
int cnt = 0;
|
||||
while (true) {
|
||||
if (cnt++ % 30 == 0) {
|
||||
System.gc();
|
||||
}
|
||||
removedCount = wb.protectionDomainRemovedCount();
|
||||
if (removedCountOrig != removedCount) {
|
||||
break;
|
||||
}
|
||||
Thread.sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
private static class TestClassLoader extends ClassLoader {
|
||||
public TestClassLoader() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Class<?> defineClass(String name, byte[] bytes, ProtectionDomain pd) {
|
||||
return defineClass(name, bytes, 0, bytes.length, pd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8151486 8218266
|
||||
* @summary Call Class.forName() on the system classloader from a class loaded
|
||||
* from a custom classloader, using the current class's protection domain.
|
||||
* @requires vm.flagless
|
||||
* @library /test/lib
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @build jdk.test.lib.Utils
|
||||
* jdk.test.lib.util.JarUtils
|
||||
* @build ClassForName ProtectionDomainCacheTest
|
||||
* @run driver ProtectionDomainCacheTest
|
||||
*/
|
||||
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import jdk.test.lib.Utils;
|
||||
import jdk.test.lib.util.JarUtils;
|
||||
import java.io.File;
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
/*
|
||||
* Create .jar, load ClassForName from .jar using a URLClassLoader
|
||||
*/
|
||||
public class ProtectionDomainCacheTest {
|
||||
static class Test {
|
||||
private static final long TIMEOUT = (long)(5000.0 * Utils.TIMEOUT_FACTOR);
|
||||
private static final String TESTCLASSES = System.getProperty("test.classes", ".");
|
||||
private static final String CLASSFILENAME = "ClassForName.class";
|
||||
|
||||
// Use a new classloader to load the ClassForName class.
|
||||
public static void loadAndRun(Path jarFilePath)
|
||||
throws Exception {
|
||||
ClassLoader classLoader = new URLClassLoader(
|
||||
new URL[]{jarFilePath.toUri().toURL()}) {
|
||||
@Override public String toString() { return "LeakedClassLoader"; }
|
||||
};
|
||||
|
||||
Class<?> loadClass = Class.forName("ClassForName", true, classLoader);
|
||||
loadClass.newInstance();
|
||||
|
||||
System.out.println("returning : " + classLoader);
|
||||
}
|
||||
|
||||
public static void main(final String[] args) throws Exception {
|
||||
// Create a temporary .jar file containing ClassForName.class
|
||||
Path testClassesDir = Paths.get(TESTCLASSES);
|
||||
Path jarFilePath = Files.createTempFile("cfn", ".jar");
|
||||
JarUtils.createJarFile(jarFilePath, testClassesDir, CLASSFILENAME);
|
||||
jarFilePath.toFile().deleteOnExit();
|
||||
|
||||
// Remove the ClassForName.class file that jtreg built, to make sure
|
||||
// we're loading from the tmp .jar
|
||||
Path classFile = FileSystems.getDefault().getPath(TESTCLASSES,
|
||||
CLASSFILENAME);
|
||||
Files.delete(classFile);
|
||||
|
||||
for (int i = 0; i < 20; i++) {
|
||||
loadAndRun(jarFilePath);
|
||||
}
|
||||
|
||||
// Give the GC a chance to unload protection domains
|
||||
for (int i = 0; i < 100; i++) {
|
||||
System.gc();
|
||||
}
|
||||
System.out.println("All Classloaders and protection domain cache entries successfully unloaded");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(
|
||||
"-Djava.security.policy==" + System.getProperty("test.src") + File.separator + "test.policy",
|
||||
"-Dtest.classes=" + System.getProperty("test.classes", "."),
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:VerifySubSet=dictionary",
|
||||
"-XX:+VerifyAfterGC",
|
||||
"-Xlog:gc+verify,protectiondomain=trace",
|
||||
"-Djava.security.manager",
|
||||
Test.class.getName());
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
output.shouldContain("PD in set is not alive");
|
||||
output.shouldContain("HandshakeForPD::do_thread");
|
||||
output.shouldHaveExitValue(0);
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test ProtectionDomainVerificationTest
|
||||
* @bug 8149064
|
||||
* @requires vm.flagless
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @library /test/lib
|
||||
* @run driver ProtectionDomainVerificationTest
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.Platform;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
public class ProtectionDomainVerificationTest {
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
|
||||
// -Xlog:protectiondomain=trace
|
||||
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:protectiondomain=trace",
|
||||
"-Xmx128m",
|
||||
"-Djava.security.manager=allow",
|
||||
Hello.class.getName(), "security_manager");
|
||||
new OutputAnalyzer(pb.start())
|
||||
.shouldHaveExitValue(0)
|
||||
.shouldContain("[protectiondomain] Checking package access")
|
||||
.shouldContain("[protectiondomain] adding protection domain that can access class");
|
||||
|
||||
// -Xlog:protectiondomain=debug
|
||||
pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:protectiondomain=debug",
|
||||
"-Xmx128m",
|
||||
"-Djava.security.manager=allow",
|
||||
Hello.class.getName(), "security_manager");
|
||||
new OutputAnalyzer(pb.start())
|
||||
.shouldHaveExitValue(0)
|
||||
.shouldContain("[protectiondomain] Checking package access")
|
||||
.shouldNotContain("[protectiondomain] adding protection domain that can access class");
|
||||
|
||||
// -Xlog:protectiondomain=debug
|
||||
pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:protectiondomain=trace",
|
||||
"-Xmx128m",
|
||||
"-Djava.security.manager=disallow",
|
||||
Hello.class.getName());
|
||||
new OutputAnalyzer(pb.start())
|
||||
.shouldHaveExitValue(0)
|
||||
.shouldNotContain("[protectiondomain] Checking package access")
|
||||
.shouldNotContain("pd set count = #");
|
||||
}
|
||||
|
||||
public static class Hello {
|
||||
public static void main(String[] args) {
|
||||
if (args.length == 1) {
|
||||
// Need a security manager to trigger logging.
|
||||
System.setSecurityManager(new SecurityManager());
|
||||
}
|
||||
System.out.print("Hello!");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. 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
|
||||
@ -67,14 +67,6 @@ public class DictionaryStatsTest {
|
||||
// Variance of bucket size : 0.281
|
||||
// Std. dev. of bucket size: 0.530
|
||||
// Maximum bucket size : 2
|
||||
// ProtectionDomainCacheTable statistics:
|
||||
// Number of buckets : 1009 = 8072 bytes, each 8
|
||||
// Number of entries : 0 = 0 bytes, each 0
|
||||
// Total footprint : = 8072 bytes
|
||||
// Average bucket size : 0.000
|
||||
// Variance of bucket size : 0.000
|
||||
// Std. dev. of bucket size: 0.000
|
||||
// Maximum bucket size : 0
|
||||
|
||||
|
||||
public void run(CommandExecutor executor) throws ClassNotFoundException {
|
||||
@ -99,10 +91,6 @@ public class DictionaryStatsTest {
|
||||
output.shouldContain("Std. dev. of bucket size");
|
||||
output.shouldContain("Maximum bucket size");
|
||||
output.shouldMatch("LoaderConstraintTable statistics:");
|
||||
// Would be nice to run this with "-Djava.security.manager=allow"
|
||||
// so the numbers aren't 0 (running make with VM_OPTIONS allowing
|
||||
// security manager does get 12 entries in this table.)
|
||||
output.shouldMatch("ProtectionDomainCacheTable statistics:");
|
||||
|
||||
// what is this?
|
||||
Reference.reachabilityFence(named_cl);
|
||||
|
@ -776,9 +776,6 @@ public class WhiteBox {
|
||||
// Resolved Method Table
|
||||
public native long resolvedMethodItemsCount();
|
||||
|
||||
// Protection Domain Table
|
||||
public native int protectionDomainRemovedCount();
|
||||
|
||||
public native int getKlassMetadataSize(Class<?> c);
|
||||
|
||||
// ThreadSMR GC safety check for threadObj
|
||||
|
Loading…
Reference in New Issue
Block a user