8259067: bootclasspath append takes out object lock
Reviewed-by: lfoltan, sspitsyn, iklam, dholmes
This commit is contained in:
parent
0e6de4eb57
commit
1c33847b8b
src/hotspot/share
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -141,8 +141,9 @@ PerfCounter* ClassLoader::_unsafe_defineClassCallCounter = NULL;
|
|||||||
GrowableArray<ModuleClassPathList*>* ClassLoader::_patch_mod_entries = NULL;
|
GrowableArray<ModuleClassPathList*>* ClassLoader::_patch_mod_entries = NULL;
|
||||||
GrowableArray<ModuleClassPathList*>* ClassLoader::_exploded_entries = NULL;
|
GrowableArray<ModuleClassPathList*>* ClassLoader::_exploded_entries = NULL;
|
||||||
ClassPathEntry* ClassLoader::_jrt_entry = NULL;
|
ClassPathEntry* ClassLoader::_jrt_entry = NULL;
|
||||||
ClassPathEntry* ClassLoader::_first_append_entry = NULL;
|
|
||||||
ClassPathEntry* ClassLoader::_last_append_entry = NULL;
|
ClassPathEntry* volatile ClassLoader::_first_append_entry_list = NULL;
|
||||||
|
ClassPathEntry* volatile ClassLoader::_last_append_entry = NULL;
|
||||||
#if INCLUDE_CDS
|
#if INCLUDE_CDS
|
||||||
ClassPathEntry* ClassLoader::_app_classpath_entries = NULL;
|
ClassPathEntry* ClassLoader::_app_classpath_entries = NULL;
|
||||||
ClassPathEntry* ClassLoader::_last_app_classpath_entry = NULL;
|
ClassPathEntry* ClassLoader::_last_app_classpath_entry = NULL;
|
||||||
@ -815,7 +816,7 @@ ClassPathZipEntry* ClassLoader::create_class_path_zip_entry(const char *path, bo
|
|||||||
|
|
||||||
// returns true if entry already on class path
|
// returns true if entry already on class path
|
||||||
bool ClassLoader::contains_append_entry(const char* name) {
|
bool ClassLoader::contains_append_entry(const char* name) {
|
||||||
ClassPathEntry* e = _first_append_entry;
|
ClassPathEntry* e = first_append_entry();
|
||||||
while (e != NULL) {
|
while (e != NULL) {
|
||||||
// assume zip entries have been canonicalized
|
// assume zip entries have been canonicalized
|
||||||
if (strcmp(name, e->name()) == 0) {
|
if (strcmp(name, e->name()) == 0) {
|
||||||
@ -826,11 +827,14 @@ bool ClassLoader::contains_append_entry(const char* name) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The boot append entries are added with a lock, and read lock free.
|
||||||
void ClassLoader::add_to_boot_append_entries(ClassPathEntry *new_entry) {
|
void ClassLoader::add_to_boot_append_entries(ClassPathEntry *new_entry) {
|
||||||
if (new_entry != NULL) {
|
if (new_entry != NULL) {
|
||||||
|
MutexLocker ml(Bootclasspath_lock, Mutex::_no_safepoint_check_flag);
|
||||||
if (_last_append_entry == NULL) {
|
if (_last_append_entry == NULL) {
|
||||||
assert(_first_append_entry == NULL, "boot loader's append class path entry list not empty");
|
_last_append_entry = new_entry;
|
||||||
_first_append_entry = _last_append_entry = new_entry;
|
assert(first_append_entry() == NULL, "boot loader's append class path entry list not empty");
|
||||||
|
Atomic::release_store(&_first_append_entry_list, new_entry);
|
||||||
} else {
|
} else {
|
||||||
_last_append_entry->set_next(new_entry);
|
_last_append_entry->set_next(new_entry);
|
||||||
_last_append_entry = new_entry;
|
_last_append_entry = new_entry;
|
||||||
@ -944,7 +948,7 @@ void ClassLoader::print_bootclasspath() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// appended entries
|
// appended entries
|
||||||
e = _first_append_entry;
|
e = first_append_entry();
|
||||||
while (e != NULL) {
|
while (e != NULL) {
|
||||||
tty->print("%s ;", e->name());
|
tty->print("%s ;", e->name());
|
||||||
e = e->next();
|
e = e->next();
|
||||||
@ -1252,7 +1256,7 @@ InstanceKlass* ClassLoader::load_class(Symbol* name, bool search_append_only, TR
|
|||||||
assert(classpath_index == 0, "The classpath_index has been incremented incorrectly");
|
assert(classpath_index == 0, "The classpath_index has been incremented incorrectly");
|
||||||
classpath_index = 1;
|
classpath_index = 1;
|
||||||
|
|
||||||
e = _first_append_entry;
|
e = first_append_entry();
|
||||||
while (e != NULL) {
|
while (e != NULL) {
|
||||||
stream = e->open_stream(file_name, CHECK_NULL);
|
stream = e->open_stream(file_name, CHECK_NULL);
|
||||||
if (NULL != stream) {
|
if (NULL != stream) {
|
||||||
@ -1427,7 +1431,7 @@ void ClassLoader::record_result(InstanceKlass* ik, const ClassFileStream* stream
|
|||||||
// Initialize the class loader's access to methods in libzip. Parse and
|
// Initialize the class loader's access to methods in libzip. Parse and
|
||||||
// process the boot classpath into a list ClassPathEntry objects. Once
|
// process the boot classpath into a list ClassPathEntry objects. Once
|
||||||
// this list has been created, it must not change order (see class PackageInfo)
|
// this list has been created, it must not change order (see class PackageInfo)
|
||||||
// it can be appended to and is by jvmti and the kernel vm.
|
// it can be appended to and is by jvmti.
|
||||||
|
|
||||||
void ClassLoader::initialize() {
|
void ClassLoader::initialize() {
|
||||||
EXCEPTION_MARK;
|
EXCEPTION_MARK;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -53,6 +53,7 @@ public:
|
|||||||
ClassPathEntry* next() const;
|
ClassPathEntry* next() const;
|
||||||
virtual ~ClassPathEntry() {}
|
virtual ~ClassPathEntry() {}
|
||||||
void set_next(ClassPathEntry* next);
|
void set_next(ClassPathEntry* next);
|
||||||
|
|
||||||
virtual bool is_modules_image() const { return false; }
|
virtual bool is_modules_image() const { return false; }
|
||||||
virtual bool is_jar_file() const { return false; }
|
virtual bool is_jar_file() const { return false; }
|
||||||
// Is this entry created from the "Class-path" attribute from a JAR Manifest?
|
// Is this entry created from the "Class-path" attribute from a JAR Manifest?
|
||||||
@ -214,9 +215,13 @@ class ClassLoader: AllStatic {
|
|||||||
// 3. the boot loader's append path
|
// 3. the boot loader's append path
|
||||||
// [-Xbootclasspath/a]; [jvmti appended entries]
|
// [-Xbootclasspath/a]; [jvmti appended entries]
|
||||||
// Note: boot loader append path does not support named modules.
|
// Note: boot loader append path does not support named modules.
|
||||||
static ClassPathEntry* _first_append_entry;
|
static ClassPathEntry* volatile _first_append_entry_list;
|
||||||
|
static ClassPathEntry* first_append_entry() {
|
||||||
|
return Atomic::load_acquire(&_first_append_entry_list);
|
||||||
|
}
|
||||||
|
|
||||||
// Last entry in linked list of appended ClassPathEntry instances
|
// Last entry in linked list of appended ClassPathEntry instances
|
||||||
static ClassPathEntry* _last_append_entry;
|
static ClassPathEntry* volatile _last_append_entry;
|
||||||
|
|
||||||
// Info used by CDS
|
// Info used by CDS
|
||||||
CDS_ONLY(static ClassPathEntry* _app_classpath_entries;)
|
CDS_ONLY(static ClassPathEntry* _app_classpath_entries;)
|
||||||
@ -234,7 +239,7 @@ class ClassLoader: AllStatic {
|
|||||||
CDS_ONLY(static ClassPathEntry* app_classpath_entries() {return _app_classpath_entries;})
|
CDS_ONLY(static ClassPathEntry* app_classpath_entries() {return _app_classpath_entries;})
|
||||||
CDS_ONLY(static ClassPathEntry* module_path_entries() {return _module_path_entries;})
|
CDS_ONLY(static ClassPathEntry* module_path_entries() {return _module_path_entries;})
|
||||||
|
|
||||||
static bool has_bootclasspath_append() { return _first_append_entry != NULL; }
|
static bool has_bootclasspath_append() { return first_append_entry() != NULL; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Initialization:
|
// Initialization:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -48,7 +48,7 @@ inline ClassPathEntry* ClassLoader::classpath_entry(int n) {
|
|||||||
// the _jrt_entry is not included in the _first_append_entry
|
// the _jrt_entry is not included in the _first_append_entry
|
||||||
// linked list, it must be accounted for when comparing the
|
// linked list, it must be accounted for when comparing the
|
||||||
// class path vs. the shared archive class path.
|
// class path vs. the shared archive class path.
|
||||||
ClassPathEntry* e = ClassLoader::_first_append_entry;
|
ClassPathEntry* e = first_append_entry();
|
||||||
while (--n >= 1) {
|
while (--n >= 1) {
|
||||||
assert(e != NULL, "Not that many classpath entries.");
|
assert(e != NULL, "Not that many classpath entries.");
|
||||||
e = e->next();
|
e = e->next();
|
||||||
@ -72,7 +72,7 @@ inline int ClassLoader::num_boot_classpath_entries() {
|
|||||||
Arguments::assert_is_dumping_archive();
|
Arguments::assert_is_dumping_archive();
|
||||||
assert(has_jrt_entry(), "must have a java runtime image");
|
assert(has_jrt_entry(), "must have a java runtime image");
|
||||||
int num_entries = 1; // count the runtime image
|
int num_entries = 1; // count the runtime image
|
||||||
ClassPathEntry* e = ClassLoader::_first_append_entry;
|
ClassPathEntry* e = first_append_entry();
|
||||||
while (e != NULL) {
|
while (e != NULL) {
|
||||||
num_entries ++;
|
num_entries ++;
|
||||||
e = e->next();
|
e = e->next();
|
||||||
@ -82,7 +82,7 @@ inline int ClassLoader::num_boot_classpath_entries() {
|
|||||||
|
|
||||||
inline ClassPathEntry* ClassLoader::get_next_boot_classpath_entry(ClassPathEntry* e) {
|
inline ClassPathEntry* ClassLoader::get_next_boot_classpath_entry(ClassPathEntry* e) {
|
||||||
if (e == ClassLoader::_jrt_entry) {
|
if (e == ClassLoader::_jrt_entry) {
|
||||||
return ClassLoader::_first_append_entry;
|
return first_append_entry();
|
||||||
} else {
|
} else {
|
||||||
return e->next();
|
return e->next();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -659,13 +659,6 @@ JvmtiEnv::AddToBootstrapClassLoaderSearch(const char* segment) {
|
|||||||
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
|
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// lock the loader
|
|
||||||
Thread* thread = Thread::current();
|
|
||||||
HandleMark hm(thread);
|
|
||||||
Handle loader_lock = Handle(thread, SystemDictionary::system_loader_lock());
|
|
||||||
|
|
||||||
ObjectLocker ol(loader_lock, thread);
|
|
||||||
|
|
||||||
// add the jar file to the bootclasspath
|
// add the jar file to the bootclasspath
|
||||||
log_info(class, load)("opened: %s", zip_entry->name());
|
log_info(class, load)("opened: %s", zip_entry->name());
|
||||||
#if INCLUDE_CDS
|
#if INCLUDE_CDS
|
||||||
|
@ -157,6 +157,7 @@ Mutex* CDSLambda_lock = NULL;
|
|||||||
Mutex* DumpRegion_lock = NULL;
|
Mutex* DumpRegion_lock = NULL;
|
||||||
Mutex* ClassListFile_lock = NULL;
|
Mutex* ClassListFile_lock = NULL;
|
||||||
#endif // INCLUDE_CDS
|
#endif // INCLUDE_CDS
|
||||||
|
Mutex* Bootclasspath_lock = NULL;
|
||||||
|
|
||||||
#if INCLUDE_JVMCI
|
#if INCLUDE_JVMCI
|
||||||
Monitor* JVMCI_lock = NULL;
|
Monitor* JVMCI_lock = NULL;
|
||||||
@ -353,6 +354,7 @@ void mutex_init() {
|
|||||||
def(DumpRegion_lock , PaddedMutex , leaf, true, _safepoint_check_never);
|
def(DumpRegion_lock , PaddedMutex , leaf, true, _safepoint_check_never);
|
||||||
def(ClassListFile_lock , PaddedMutex , leaf, true, _safepoint_check_never);
|
def(ClassListFile_lock , PaddedMutex , leaf, true, _safepoint_check_never);
|
||||||
#endif // INCLUDE_CDS
|
#endif // INCLUDE_CDS
|
||||||
|
def(Bootclasspath_lock , PaddedMutex , leaf, false, _safepoint_check_never);
|
||||||
|
|
||||||
#if INCLUDE_JVMCI
|
#if INCLUDE_JVMCI
|
||||||
def(JVMCI_lock , PaddedMonitor, nonleaf+2, true, _safepoint_check_always);
|
def(JVMCI_lock , PaddedMonitor, nonleaf+2, true, _safepoint_check_always);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -158,6 +158,8 @@ extern Mutex* CodeHeapStateAnalytics_lock; // lock print functions against
|
|||||||
extern Monitor* JVMCI_lock; // Monitor to control initialization of JVMCI
|
extern Monitor* JVMCI_lock; // Monitor to control initialization of JVMCI
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern Mutex* Bootclasspath_lock;
|
||||||
|
|
||||||
extern Mutex* tty_lock; // lock to synchronize output.
|
extern Mutex* tty_lock; // lock to synchronize output.
|
||||||
|
|
||||||
// A MutexLocker provides mutual exclusion with respect to a given mutex
|
// A MutexLocker provides mutual exclusion with respect to a given mutex
|
||||||
|
Loading…
x
Reference in New Issue
Block a user