8341916: Remove ProtectionDomain related hotspot code and tests

Reviewed-by: dholmes, iklam, jrose
This commit is contained in:
Coleen Phillimore 2024-11-18 12:48:40 +00:00
parent 5eb0733f5f
commit dfddbcaab8
48 changed files with 169 additions and 1415 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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) {

View File

@ -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 {

View File

@ -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++) {

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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

View File

@ -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) \

View File

@ -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;

View File

@ -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();
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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)) {

View File

@ -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 ) \

View File

@ -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;") \

View File

@ -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
*/

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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.

View File

@ -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;

View File

@ -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) \

View File

@ -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()) {

View File

@ -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;
}

View File

@ -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)));

View File

@ -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()) {

View File

@ -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);

View File

@ -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},

View File

@ -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);

View File

@ -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();
}

View File

@ -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

View File

@ -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);
}
};

View File

@ -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()));

View File

@ -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()) {

View File

@ -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);

View File

@ -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: "

View File

@ -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:

View File

@ -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; }

View File

@ -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

View File

@ -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);
}
}
}
}

View File

@ -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);
}
}

View File

@ -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!");
}
}
}

View File

@ -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);

View File

@ -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