This commit is contained in:
Jiangli Zhou 2015-11-23 23:42:46 +01:00
commit 9a9314db0c
20 changed files with 426 additions and 74 deletions

View File

@ -73,8 +73,9 @@ ifeq ($(INCLUDE_CDS), false)
CXXFLAGS += -DINCLUDE_CDS=0
CFLAGS += -DINCLUDE_CDS=0
Src_Files_EXCLUDE += filemap.cpp metaspaceShared*.cpp sharedPathsMiscInfo.cpp \
systemDictionaryShared.cpp classLoaderExt.cpp sharedClassUtil.cpp
Src_Files_EXCLUDE += classListParser.cpp classLoaderExt.cpp \
filemap.cpp metaspaceShared*.cpp sharedClassUtil.cpp sharedPathsMiscInfo.cpp \
systemDictionaryShared.cpp
endif
ifeq ($(INCLUDE_ALL_GCS), false)

View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 2015, 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/classListParser.hpp"
#include "runtime/os.hpp"
#include "runtime/java.hpp"
ClassListParser::ClassListParser(const char* file) {
_classlist_file = file;
_file = fopen(file, "r");
if (_file == NULL) {
char errmsg[JVM_MAXPATHLEN];
os::lasterror(errmsg, JVM_MAXPATHLEN);
vm_exit_during_initialization("Loading classlist failed", errmsg);
}
}
ClassListParser::~ClassListParser() {
if (_file) {
fclose(_file);
}
}
bool ClassListParser::parse_one_line() {
for (;;) {
if (fgets(_line, sizeof(_line), _file) == NULL) {
return false;
}
int line_len = (int)strlen(_line);
if (line_len > _max_allowed_line_len) {
tty->print_cr("input line too long (must be no longer than %d chars)", _max_allowed_line_len);
vm_exit_during_initialization("Loading classlist failed");
}
if (*_line == '#') { // comment
continue;
}
break;
}
// Remove trailing \r\n
_line[strcspn(_line, "\r\n")] = 0;
return true;
}

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2015, 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_VM_MEMORY_CLASSLISTPARSER_HPP
#define SHARE_VM_MEMORY_CLASSLISTPARSER_HPP
#include "utilities/exceptions.hpp"
#include "utilities/globalDefinitions.hpp"
class ClassListParser : public StackObj {
enum {
// Max number of bytes allowed per line in the classlist.
// Theoretically Java class names could be 65535 bytes in length. In reality,
// 4K bytes is more than enough.
_max_allowed_line_len = 4096,
_line_buf_extra = 10, // for detecting input too long
_line_buf_size = _max_allowed_line_len + _line_buf_extra
};
const char* _classlist_file;
FILE* _file;
char _line[_line_buf_size]; // The buffer that holds the current line.
public:
ClassListParser(const char* file);
~ClassListParser();
bool parse_one_line();
const char* current_class_name() {
return _line;
}
};
#endif // SHARE_VM_MEMORY_CLASSLISTPARSER_HPP

View File

@ -82,7 +82,7 @@ ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous, Depen
_keep_alive(is_anonymous || h_class_loader.is_null()),
_metaspace(NULL), _unloading(false), _klasses(NULL),
_claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL),
_next(NULL), _dependencies(dependencies),
_next(NULL), _dependencies(dependencies), _shared_class_loader_id(-1),
_metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true,
Monitor::_safepoint_check_never)) {
// empty

View File

@ -187,6 +187,9 @@ class ClassLoaderData : public CHeapObj<mtClass> {
// Support for walking class loader data objects
ClassLoaderData* _next; /// Next loader_datas created
// CDS
int _shared_class_loader_id;
// ReadOnly and ReadWrite metaspaces (static because only on the null
// class loader for now).
static Metaspace* _ro_metaspace;
@ -308,6 +311,15 @@ class ClassLoaderData : public CHeapObj<mtClass> {
Metaspace* ro_metaspace();
Metaspace* rw_metaspace();
void initialize_shared_metaspaces();
int shared_class_loader_id() {
return _shared_class_loader_id;
}
void set_shared_class_loader_id(int id) {
assert(id >= 0, "sanity");
assert(_shared_class_loader_id <0, "cannot be assigned more than once");
_shared_class_loader_id = id;
}
};
// An iterator that distributes Klasses to parallel worker threads.

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2015, 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/classListParser.hpp"
#include "classfile/classLoaderExt.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
Klass* ClassLoaderExt::load_one_class(ClassListParser* parser, TRAPS) {
TempNewSymbol class_name_symbol = SymbolTable::new_symbol(parser->current_class_name(), THREAD);
guarantee(!HAS_PENDING_EXCEPTION, "Exception creating a symbol.");
return SystemDictionary::resolve_or_null(class_name_symbol, THREAD);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2015, 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
@ -29,6 +29,8 @@
#include "oops/instanceKlass.hpp"
#include "runtime/handles.hpp"
class ClassListParser;
class ClassLoaderExt: public ClassLoader { // AllStatic
public:
@ -69,6 +71,7 @@ public:
ClassLoader::add_to_list(new_entry);
}
static void setup_search_paths() {}
static Klass* load_one_class(ClassListParser* parser, TRAPS);
};
#endif // SHARE_VM_CLASSFILE_CLASSLOADEREXT_HPP

View File

@ -23,8 +23,10 @@
*/
#include "precompiled.hpp"
#include "classfile/sharedClassUtil.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/systemDictionaryShared.hpp"
#include "memory/iterator.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiRedefineClassesTrace.hpp"
@ -34,9 +36,16 @@
DictionaryEntry* Dictionary::_current_class_entry = NULL;
int Dictionary::_current_class_index = 0;
size_t Dictionary::entry_size() {
if (DumpSharedSpaces) {
return SystemDictionaryShared::dictionary_entry_size();
} else {
return sizeof(DictionaryEntry);
}
}
Dictionary::Dictionary(int table_size)
: TwoOopHashtable<Klass*, mtClass>(table_size, sizeof(DictionaryEntry)) {
: TwoOopHashtable<Klass*, mtClass>(table_size, (int)entry_size()) {
_current_class_index = 0;
_current_class_entry = NULL;
_pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize);
@ -45,7 +54,7 @@ Dictionary::Dictionary(int table_size)
Dictionary::Dictionary(int table_size, HashtableBucket<mtClass>* t,
int number_of_entries)
: TwoOopHashtable<Klass*, mtClass>(table_size, sizeof(DictionaryEntry), t, number_of_entries) {
: TwoOopHashtable<Klass*, mtClass>(table_size, (int)entry_size(), t, number_of_entries) {
_current_class_index = 0;
_current_class_entry = NULL;
_pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize);
@ -61,6 +70,9 @@ DictionaryEntry* Dictionary::new_entry(unsigned int hash, Klass* klass,
entry->set_loader_data(loader_data);
entry->set_pd_set(NULL);
assert(klass->is_instance_klass(), "Must be");
if (DumpSharedSpaces) {
SystemDictionaryShared::init_shared_dictionary_entry(klass, entry);
}
return entry;
}

View File

@ -53,6 +53,7 @@ private:
DictionaryEntry* get_entry(int index, unsigned int hash,
Symbol* name, ClassLoaderData* loader_data);
protected:
DictionaryEntry* bucket(int i) {
return (DictionaryEntry*)Hashtable<Klass*, mtClass>::bucket(i);
}
@ -66,6 +67,7 @@ private:
Hashtable<Klass*, mtClass>::add_entry(index, (HashtableEntry<Klass*, mtClass>*)new_entry);
}
static size_t entry_size();
public:
Dictionary(int table_size);
Dictionary(int table_size, HashtableBucket<mtClass>* t, int number_of_entries);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2015, 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
@ -25,6 +25,7 @@
#ifndef SHARE_VM_CLASSFILE_SHAREDPATHSMISCINFO_HPP
#define SHARE_VM_CLASSFILE_SHAREDPATHSMISCINFO_HPP
#include "classfile/classLoader.hpp"
#include "runtime/os.hpp"
// During dumping time, when processing class paths, we build up the dump-time
@ -106,19 +107,6 @@ public:
add_path(path, NON_EXIST);
}
// The path must exist and have required size and modification time
void add_required_file(const char* path) {
add_path(path, REQUIRED);
struct stat st;
if (os::stat(path, &st) != 0) {
assert(0, "sanity");
ClassLoader::exit_with_path_failure("failed to os::stat(%s)", path); // should not happen
}
write_time(st.st_mtime);
write_long(st.st_size);
}
// The path must exist, and must contain exactly <num_entries> files/dirs
void add_boot_classpath(const char* path) {
add_path(path, BOOT);

View File

@ -322,6 +322,17 @@ Klass* SystemDictionary::resolve_super_or_fail(Symbol* child_name,
Handle protection_domain,
bool is_superclass,
TRAPS) {
#if INCLUDE_CDS
if (DumpSharedSpaces) {
// Special processing for CDS dump time.
Klass* k = SystemDictionaryShared::dump_time_resolve_super_or_fail(child_name,
class_name, class_loader, protection_domain, is_superclass, CHECK_NULL);
if (k) {
return k;
}
}
#endif // INCLUDE_CDS
// Double-check, if child class is already loaded, just return super-class,interface
// Don't add a placedholder if already loaded, i.e. already in system dictionary
// Make sure there's a placeholder for the *child* before resolving.
@ -1079,12 +1090,30 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name,
//
// Note: "name" is updated.
instanceKlassHandle k = ClassFileParser(st).parseClassFile(class_name,
loader_data,
protection_domain,
parsed_name,
verify,
THREAD);
instanceKlassHandle k;
#if INCLUDE_CDS
k = SystemDictionaryShared::lookup_from_stream(class_name,
class_loader,
protection_domain,
st,
verify,
CHECK_NULL);
#endif
if (k.not_null()) {
parsed_name = k->name();
} else {
if (st->buffer() == NULL) {
return NULL;
}
k = ClassFileParser(st).parseClassFile(class_name,
loader_data,
protection_domain,
parsed_name,
verify,
THREAD);
}
const char* pkg = "java/";
if (!HAS_PENDING_EXCEPTION &&
@ -1201,8 +1230,13 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik,
if (ik->super() != NULL) {
Symbol* cn = ik->super()->name();
resolve_super_or_fail(class_name, cn,
class_loader, protection_domain, true, CHECK_(nh));
Klass *s = resolve_super_or_fail(class_name, cn,
class_loader, protection_domain, true, CHECK_(nh));
if (s != ik->super()) {
// The dynamically resolved super class is not the same as the one we used during dump time,
// so we cannot use ik.
return nh;
}
}
Array<Klass*>* interfaces = ik->local_interfaces();
@ -1215,7 +1249,12 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik,
// reinitialized yet (they will be once the interface classes
// are loaded)
Symbol* name = k->name();
resolve_super_or_fail(class_name, name, class_loader, protection_domain, false, CHECK_(nh));
Klass* i = resolve_super_or_fail(class_name, name, class_loader, protection_domain, false, CHECK_(nh));
if (k != i) {
// The dynamically resolved interface class is not the same as the one we used during dump time,
// so we cannot use ik.
return nh;
}
}
// Adjust methods to recover missing data. They need addresses for

View File

@ -27,6 +27,7 @@
#include "classfile/classFileStream.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary_ext.hpp"
#include "oops/objArrayOop.hpp"
#include "oops/symbol.hpp"
#include "runtime/java.hpp"
@ -200,15 +201,18 @@ class Ticks;
do_klass(Integer_klass, java_lang_Integer, Pre ) \
do_klass(Long_klass, java_lang_Long, Pre ) \
\
/* Extensions */ \
WK_KLASSES_DO_EXT(do_klass) \
/* JVMCI classes. These are loaded on-demand. */ \
JVMCI_WK_KLASSES_DO(do_klass) \
JVMCI_WK_KLASSES_DO(do_klass) \
\
/*end*/
class SystemDictionary : AllStatic {
friend class VMStructs;
friend class SystemDictionaryHandles;
friend class SharedClassUtil;
public:
enum WKID {
@ -673,11 +677,6 @@ protected:
// Basic find on classes in the midst of being loaded
static Symbol* find_placeholder(Symbol* name, ClassLoaderData* loader_data);
// Updating entry in dictionary
// Add a completely loaded class
static void add_klass(int index, Symbol* class_name,
ClassLoaderData* loader_data, KlassHandle obj);
// Add a placeholder for a class being loaded
static void add_placeholder(int index,
Symbol* class_name,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2015, 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
@ -22,11 +22,13 @@
*
*/
#ifndef SHARE_VM_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP
#define SHARE_VM_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP
#include "classfile/systemDictionary.hpp"
#include "classfile/dictionary.hpp"
class ClassFileStream;
class SystemDictionaryShared: public SystemDictionary {
public:
@ -42,6 +44,30 @@ public:
oop class_loader = loader_data->class_loader();
return (class_loader == NULL);
}
static Klass* dump_time_resolve_super_or_fail(Symbol* child_name,
Symbol* class_name,
Handle class_loader,
Handle protection_domain,
bool is_superclass,
TRAPS) {
return NULL;
}
static size_t dictionary_entry_size() {
return sizeof(DictionaryEntry);
}
static void init_shared_dictionary_entry(Klass* k, DictionaryEntry* entry) {}
static InstanceKlass* lookup_from_stream(Symbol* class_name,
Handle class_loader,
Handle protection_domain,
ClassFileStream* st,
bool verify,
TRAPS) {
return NULL;
}
};
#endif // SHARE_VM_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2015, 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_VM_CLASSFILE_SYSTEMDICTIONARY_EXT_HPP
#define SHARE_VM_CLASSFILE_SYSTEMDICTIONARY_EXT_HPP
#define WK_KLASSES_DO_EXT(do_klass)
#endif // SHARE_VM_CLASSFILE_SYSTEMDICTIONARY_EXT_HPP

View File

@ -25,6 +25,7 @@
#ifndef SHARE_VM_CLASSFILE_VMSYMBOLS_HPP
#define SHARE_VM_CLASSFILE_VMSYMBOLS_HPP
#include "classfile/vmSymbols_ext.hpp"
#include "oops/symbol.hpp"
#include "memory/iterator.hpp"
#include "trace/traceMacros.hpp"
@ -646,6 +647,9 @@
/* trace signatures */ \
TRACE_TEMPLATES(template) \
\
/* extensions */ \
VM_SYMBOLS_DO_EXT(template, do_alias) \
\
/*end*/
// Here are all the intrinsics known to the runtime and the CI.

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2015, 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_VM_CLASSFILE_VMSYMBOLS_EXT_HPP
#define SHARE_VM_CLASSFILE_VMSYMBOLS_EXT_HPP
#define VM_SYMBOLS_DO_EXT(template, do_alias)
#endif // SHARE_VM_CLASSFILE_VMSYMBOLS_EXT_HPP

View File

@ -23,6 +23,8 @@
*/
#include "precompiled.hpp"
#include "classfile/classListParser.hpp"
#include "classfile/classLoaderExt.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/loaderConstraints.hpp"
#include "classfile/placeholders.hpp"
@ -42,6 +44,7 @@
#include "runtime/signature.hpp"
#include "runtime/vmThread.hpp"
#include "runtime/vm_operations.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/hashtable.inline.hpp"
int MetaspaceShared::_max_alignment = 0;
@ -97,6 +100,10 @@ static void collect_classes(Klass* k) {
}
}
static void collect_classes2(Klass* k, ClassLoaderData* class_data) {
collect_classes(k);
}
static void remove_unshareable_in_classes() {
for (int i = 0; i < _global_klass_objects->length(); i++) {
Klass* k = _global_klass_objects->at(i);
@ -422,12 +429,15 @@ private:
VirtualSpace _mc_vs;
CompactHashtableWriter* _string_cht;
GrowableArray<MemRegion> *_string_regions;
char* _md_alloc_low;
char* _md_alloc_top;
char* _md_alloc_max;
static VM_PopulateDumpSharedSpace* _instance;
public:
VM_PopulateDumpSharedSpace(ClassLoaderData* loader_data,
GrowableArray<Klass*> *class_promote_order) :
_loader_data(loader_data) {
// Split up and initialize the misc code and data spaces
ReservedSpace* shared_rs = MetaspaceShared::shared_rs();
size_t metadata_size = SharedReadOnlySize + SharedReadWriteSize;
@ -440,11 +450,43 @@ public:
_md_vs.initialize(md_rs, SharedMiscDataSize);
_mc_vs.initialize(mc_rs, SharedMiscCodeSize);
_class_promote_order = class_promote_order;
_md_alloc_low = _md_vs.low();
_md_alloc_top = _md_alloc_low + sizeof(char*);
_md_alloc_max = _md_vs.low() + SharedMiscDataSize;
assert(_instance == NULL, "must be singleton");
_instance = this;
}
~VM_PopulateDumpSharedSpace() {
assert(_instance == this, "must be singleton");
_instance = NULL;
}
static VM_PopulateDumpSharedSpace* instance() {
assert(_instance != NULL, "sanity");
return _instance;
}
VMOp_Type type() const { return VMOp_PopulateDumpSharedSpace; }
void doit(); // outline because gdb sucks
char* misc_data_space_alloc(size_t num_bytes) {
size_t alignment = sizeof(char*);
num_bytes = align_size_up(num_bytes, alignment);
_md_alloc_top = (char*)align_ptr_up(_md_alloc_top, alignment);
if (_md_alloc_top + num_bytes > _md_alloc_max) {
report_out_of_shared_space(SharedMiscData);
}
char* p = _md_alloc_top;
_md_alloc_top += num_bytes;
memset(p, 0, num_bytes);
return p;
}
private:
void handle_misc_data_space_failure(bool success) {
if (!success) {
@ -453,6 +495,7 @@ private:
}
}; // class VM_PopulateDumpSharedSpace
VM_PopulateDumpSharedSpace* VM_PopulateDumpSharedSpace::_instance;
void VM_PopulateDumpSharedSpace::doit() {
Thread* THREAD = VMThread::vm_thread();
@ -475,7 +518,11 @@ void VM_PopulateDumpSharedSpace::doit() {
// that so we don't have to walk the SystemDictionary again.
_global_klass_objects = new GrowableArray<Klass*>(1000);
Universe::basic_type_classes_do(collect_classes);
SystemDictionary::classes_do(collect_classes);
// Need to call SystemDictionary::classes_do(void f(Klass*, ClassLoaderData*))
// as we may have some classes with NULL ClassLoaderData* in the dictionary. Other
// variants of SystemDictionary::classes_do will skip those classes.
SystemDictionary::classes_do(collect_classes2);
tty->print_cr("Number of classes %d", _global_klass_objects->length());
{
@ -515,6 +562,10 @@ void VM_PopulateDumpSharedSpace::doit() {
char* mc_top = mc_low;
char* mc_end = _mc_vs.high();
assert(_md_alloc_top != NULL, "sanity");
*(char**)_md_alloc_low = _md_alloc_top;
md_top = _md_alloc_top;
// Reserve space for the list of Klass*s whose vtables are used
// for patching others as needed.
@ -735,6 +786,7 @@ void MetaspaceShared::prepare_for_dumping() {
void MetaspaceShared::preload_and_dump(TRAPS) {
TraceTime timer("Dump Shared Spaces", TraceStartupTime);
ResourceMark rm;
char class_list_path_str[JVM_MAXPATHLEN];
tty->print_cr("Allocated shared space: " SIZE_FORMAT " bytes at " PTR_FORMAT,
MetaspaceShared::shared_rs()->size(),
@ -747,7 +799,6 @@ void MetaspaceShared::preload_and_dump(TRAPS) {
// Construct the path to the class list (in jre/lib)
// Walk up two directories from the location of the VM and
// optionally tack on "lib" (depending on platform)
char class_list_path_str[JVM_MAXPATHLEN];
os::jvm_path(class_list_path_str, sizeof(class_list_path_str));
for (int i = 0; i < 3; i++) {
char *end = strrchr(class_list_path_str, *os::file_separator());
@ -785,6 +836,11 @@ void MetaspaceShared::preload_and_dump(TRAPS) {
static const char map_entry_array_sig[] = "[Ljava/util/Map$Entry;";
SymbolTable::new_permanent_symbol(map_entry_array_sig, THREAD);
// Need to allocate the op here:
// op.misc_data_space_alloc() will be called during preload_and_dump().
ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
VM_PopulateDumpSharedSpace op(loader_data, class_promote_order);
tty->print_cr("Loading classes to share ...");
_has_error_classes = false;
class_count += preload_and_dump(class_list_path, class_promote_order,
@ -809,44 +865,27 @@ void MetaspaceShared::preload_and_dump(TRAPS) {
link_and_cleanup_shared_classes(CATCH);
tty->print_cr("Rewriting and linking classes: done");
// Create and dump the shared spaces. Everything so far is loaded
// with the null class loader.
ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
VM_PopulateDumpSharedSpace op(loader_data, class_promote_order);
VMThread::execute(&op);
// Since various initialization steps have been undone by this process,
// it is not reasonable to continue running a java process.
exit(0);
}
int MetaspaceShared::preload_and_dump(const char * class_list_path,
int MetaspaceShared::preload_and_dump(const char* class_list_path,
GrowableArray<Klass*>* class_promote_order,
TRAPS) {
FILE* file = fopen(class_list_path, "r");
char class_name[256];
ClassListParser parser(class_list_path);
int class_count = 0;
if (file != NULL) {
while ((fgets(class_name, sizeof class_name, file)) != NULL) {
if (*class_name == '#') { // comment
continue;
}
// Remove trailing newline
size_t name_len = strlen(class_name);
if (class_name[name_len-1] == '\n') {
class_name[name_len-1] = '\0';
}
while (parser.parse_one_line()) {
Klass* klass = ClassLoaderExt::load_one_class(&parser, THREAD);
// Got a class name - load it.
TempNewSymbol class_name_symbol = SymbolTable::new_permanent_symbol(class_name, THREAD);
guarantee(!HAS_PENDING_EXCEPTION, "Exception creating a symbol.");
Klass* klass = SystemDictionary::resolve_or_null(class_name_symbol,
THREAD);
CLEAR_PENDING_EXCEPTION;
if (klass != NULL) {
if (PrintSharedSpaces && Verbose && WizardMode) {
tty->print_cr("Shared spaces preloaded: %s", class_name);
ResourceMark rm;
tty->print_cr("Shared spaces preloaded: %s", klass->external_name());
}
InstanceKlass* ik = InstanceKlass::cast(klass);
@ -862,17 +901,8 @@ int MetaspaceShared::preload_and_dump(const char * class_list_path,
guarantee(!HAS_PENDING_EXCEPTION, "exception in link_class");
class_count++;
} else {
//tty->print_cr("Preload failed: %s", class_name);
}
}
fclose(file);
} else {
char errmsg[JVM_MAXPATHLEN];
os::lasterror(errmsg, JVM_MAXPATHLEN);
tty->print_cr("Loading classlist failed: %s", errmsg);
exit(1);
}
return class_count;
}
@ -908,6 +938,11 @@ bool MetaspaceShared::try_link_class(InstanceKlass* ik, TRAPS) {
}
}
// Allocate misc data blocks during dumping.
char* MetaspaceShared::misc_data_space_alloc(size_t num_bytes) {
return VM_PopulateDumpSharedSpace::instance()->misc_data_space_alloc(num_bytes);
}
// Closure for serializing initialization data in from a data area
// (ptr_array) read from the shared file.
@ -1033,6 +1068,8 @@ void MetaspaceShared::initialize_shared_spaces() {
char* buffer = mapinfo->header()->region_addr(md);
buffer = *((char**)buffer); // skip over the md_alloc'ed blocks
// Skip over (reserve space for) a list of addresses of C++ vtables
// for Klass objects. They get filled in later.

View File

@ -190,5 +190,8 @@ class MetaspaceShared : AllStatic {
static int count_class(const char* classlist_file);
static void estimate_regions_size() NOT_CDS_RETURN;
// Allocate a block of memory from the "md" region.
static char* misc_data_space_alloc(size_t num_bytes);
};
#endif // SHARE_VM_MEMORY_METASPACESHARED_HPP

View File

@ -1271,6 +1271,10 @@ WB_ENTRY(void, WB_AssertMatchingSafepointCalls(JNIEnv* env, jobject o, jboolean
attemptedNoSafepointValue == JNI_TRUE);
WB_END
WB_ENTRY(jboolean, WB_IsSharedClass(JNIEnv* env, jobject wb, jclass clazz))
return (jboolean)MetaspaceShared::is_in_shared_space(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
WB_END
WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj))
oop obj_oop = JNIHandles::resolve(obj);
return (jboolean) obj_oop->mark()->has_monitor();
@ -1471,6 +1475,7 @@ static JNINativeMethod methods[] = {
{CC"runMemoryUnitTests", CC"()V", (void*)&WB_RunMemoryUnitTests},
{CC"readFromNoaccessArea",CC"()V", (void*)&WB_ReadFromNoaccessArea},
{CC"stressVirtualSpaceResize",CC"(JJJ)I", (void*)&WB_StressVirtualSpaceResize},
{CC"isSharedClass", CC"(Ljava/lang/Class;)Z", (void*)&WB_IsSharedClass },
#if INCLUDE_ALL_GCS
{CC"g1InConcurrentMark", CC"()Z", (void*)&WB_G1InConcurrentMark},
{CC"g1IsHumongous0", CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous },

View File

@ -365,6 +365,7 @@ template class RehashableHashtable<Symbol*, mtSymbol>;
template class RehashableHashtable<oopDesc*, mtSymbol>;
template class Hashtable<Symbol*, mtSymbol>;
template class Hashtable<Klass*, mtClass>;
template class Hashtable<InstanceKlass*, mtClass>;
template class Hashtable<oop, mtClass>;
#if defined(SOLARIS) || defined(CHECK_UNHANDLED_OOPS)
template class Hashtable<oop, mtSymbol>;
@ -378,6 +379,7 @@ template class HashtableEntry<oop, mtSymbol>;
template class BasicHashtableEntry<mtSymbol>;
template class BasicHashtableEntry<mtCode>;
template class BasicHashtable<mtClass>;
template class BasicHashtable<mtClassShared>;
template class BasicHashtable<mtSymbol>;
template class BasicHashtable<mtCode>;
template class BasicHashtable<mtInternal>;