8261921: ClassListParser::current should be used only by main thread

Reviewed-by: dholmes, ccheung, coleenp
This commit is contained in:
Ioi Lam 2021-02-23 03:11:47 +00:00
parent 991f7c1303
commit 8cfea7c523
5 changed files with 35 additions and 17 deletions

View file

@ -43,6 +43,7 @@
#include "memory/metaspaceShared.hpp" #include "memory/metaspaceShared.hpp"
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"
#include "oops/constantPool.hpp" #include "oops/constantPool.hpp"
#include "runtime/atomic.hpp"
#include "runtime/handles.inline.hpp" #include "runtime/handles.inline.hpp"
#include "runtime/java.hpp" #include "runtime/java.hpp"
#include "runtime/javaCalls.hpp" #include "runtime/javaCalls.hpp"
@ -50,11 +51,10 @@
#include "utilities/hashtable.inline.hpp" #include "utilities/hashtable.inline.hpp"
#include "utilities/macros.hpp" #include "utilities/macros.hpp"
volatile Thread* ClassListParser::_parsing_thread = NULL;
ClassListParser* ClassListParser::_instance = NULL; ClassListParser* ClassListParser::_instance = NULL;
ClassListParser::ClassListParser(const char* file) { ClassListParser::ClassListParser(const char* file) {
assert(_instance == NULL, "must be singleton");
_instance = this;
_classlist_file = file; _classlist_file = file;
_file = NULL; _file = NULL;
// Use os::open() because neither fopen() nor os::fopen() // Use os::open() because neither fopen() nor os::fopen()
@ -73,12 +73,22 @@ ClassListParser::ClassListParser(const char* file) {
_line_no = 0; _line_no = 0;
_interfaces = new (ResourceObj::C_HEAP, mtClass) GrowableArray<int>(10, mtClass); _interfaces = new (ResourceObj::C_HEAP, mtClass) GrowableArray<int>(10, mtClass);
_indy_items = new (ResourceObj::C_HEAP, mtClass) GrowableArray<const char*>(9, mtClass); _indy_items = new (ResourceObj::C_HEAP, mtClass) GrowableArray<const char*>(9, mtClass);
// _instance should only be accessed by the thread that created _instance.
assert(_instance == NULL, "must be singleton");
_instance = this;
Atomic::store(&_parsing_thread, Thread::current());
}
bool ClassListParser::is_parsing_thread() {
return Atomic::load(&_parsing_thread) == Thread::current();
} }
ClassListParser::~ClassListParser() { ClassListParser::~ClassListParser() {
if (_file) { if (_file) {
fclose(_file); fclose(_file);
} }
Atomic::store(&_parsing_thread, (Thread*)NULL);
_instance = NULL; _instance = NULL;
} }

View file

@ -33,6 +33,8 @@
#define LAMBDA_PROXY_TAG "@lambda-proxy" #define LAMBDA_PROXY_TAG "@lambda-proxy"
#define LAMBDA_FORM_TAG "@lambda-form-invoker" #define LAMBDA_FORM_TAG "@lambda-form-invoker"
class Thread;
class ID2KlassTable : public KVHashtable<int, InstanceKlass*, mtInternal> { class ID2KlassTable : public KVHashtable<int, InstanceKlass*, mtInternal> {
public: public:
ID2KlassTable() : KVHashtable<int, InstanceKlass*, mtInternal>(1987) {} ID2KlassTable() : KVHashtable<int, InstanceKlass*, mtInternal>(1987) {}
@ -81,6 +83,7 @@ class ClassListParser : public StackObj {
_line_buf_size = _max_allowed_line_len + _line_buf_extra _line_buf_size = _max_allowed_line_len + _line_buf_extra
}; };
static volatile Thread* _parsing_thread; // the thread that created _instance
static ClassListParser* _instance; // the singleton. static ClassListParser* _instance; // the singleton.
const char* _classlist_file; const char* _classlist_file;
FILE* _file; FILE* _file;
@ -119,9 +122,13 @@ public:
ClassListParser(const char* file); ClassListParser(const char* file);
~ClassListParser(); ~ClassListParser();
static bool is_parsing_thread();
static ClassListParser* instance() { static ClassListParser* instance() {
assert(is_parsing_thread(), "call this only in the thread that created ClassListParsing::_instance");
assert(_instance != NULL, "must be");
return _instance; return _instance;
} }
bool parse_one_line(); bool parse_one_line();
void split_tokens_by_whitespace(int offset); void split_tokens_by_whitespace(int offset);
int split_at_tag_from_line(); int split_at_tag_from_line();

View file

@ -369,8 +369,8 @@ InstanceKlass* SystemDictionary::resolve_super_or_fail(Symbol* class_name,
#if INCLUDE_CDS #if INCLUDE_CDS
if (DumpSharedSpaces) { if (DumpSharedSpaces) {
// Special processing for handling UNREGISTERED shared classes. // Special processing for handling UNREGISTERED shared classes.
InstanceKlass* k = SystemDictionaryShared::dump_time_resolve_super_or_fail(class_name, InstanceKlass* k = SystemDictionaryShared::lookup_super_for_unregistered_class(class_name,
super_name, class_loader, protection_domain, is_superclass, CHECK_NULL); super_name, is_superclass);
if (k) { if (k) {
return k; return k;
} }

View file

@ -1196,18 +1196,23 @@ bool SystemDictionaryShared::add_unregistered_class(InstanceKlass* k, TRAPS) {
return created; return created;
} }
// This function is called to resolve the super/interfaces of shared classes for // This function is called to lookup the super/interfaces of shared classes for
// non-built-in loaders. E.g., SharedClass in the below example // unregistered loaders. E.g., SharedClass in the below example
// where "super:" (and optionally "interface:") have been specified. // where "super:" (and optionally "interface:") have been specified.
// //
// java/lang/Object id: 0 // java/lang/Object id: 0
// Interface id: 2 super: 0 source: cust.jar // Interface id: 2 super: 0 source: cust.jar
// SharedClass id: 4 super: 0 interfaces: 2 source: cust.jar // SharedClass id: 4 super: 0 interfaces: 2 source: cust.jar
InstanceKlass* SystemDictionaryShared::dump_time_resolve_super_or_fail( InstanceKlass* SystemDictionaryShared::lookup_super_for_unregistered_class(
Symbol* class_name, Symbol* super_name, Handle class_loader, Symbol* class_name, Symbol* super_name, bool is_superclass) {
Handle protection_domain, bool is_superclass, TRAPS) {
assert(DumpSharedSpaces, "only when dumping"); assert(DumpSharedSpaces, "only when static dumping");
if (!ClassListParser::is_parsing_thread()) {
// Unregistered classes can be created only by ClassListParser::_parsing_thread.
return NULL;
}
ClassListParser* parser = ClassListParser::instance(); ClassListParser* parser = ClassListParser::instance();
if (parser == NULL) { if (parser == NULL) {

View file

@ -247,12 +247,8 @@ public:
static bool is_sharing_possible(ClassLoaderData* loader_data); static bool is_sharing_possible(ClassLoaderData* loader_data);
static bool add_unregistered_class(InstanceKlass* k, TRAPS); static bool add_unregistered_class(InstanceKlass* k, TRAPS);
static InstanceKlass* dump_time_resolve_super_or_fail(Symbol* class_name, static InstanceKlass* lookup_super_for_unregistered_class(Symbol* class_name,
Symbol* super_name, Symbol* super_name, bool is_superclass);
Handle class_loader,
Handle protection_domain,
bool is_superclass,
TRAPS);
static void init_dumptime_info(InstanceKlass* k) NOT_CDS_RETURN; static void init_dumptime_info(InstanceKlass* k) NOT_CDS_RETURN;
static void remove_dumptime_info(InstanceKlass* k) NOT_CDS_RETURN; static void remove_dumptime_info(InstanceKlass* k) NOT_CDS_RETURN;