mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8261921
: ClassListParser::current should be used only by main thread
Reviewed-by: dholmes, ccheung, coleenp
This commit is contained in:
parent
991f7c1303
commit
8cfea7c523
5 changed files with 35 additions and 17 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue