Merge
This commit is contained in:
commit
9a9314db0c
@ -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)
|
||||
|
66
hotspot/src/share/vm/classfile/classListParser.cpp
Normal file
66
hotspot/src/share/vm/classfile/classListParser.cpp
Normal 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;
|
||||
}
|
||||
|
56
hotspot/src/share/vm/classfile/classListParser.hpp
Normal file
56
hotspot/src/share/vm/classfile/classListParser.hpp
Normal 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
|
@ -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
|
||||
|
@ -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.
|
||||
|
36
hotspot/src/share/vm/classfile/classLoaderExt.cpp
Normal file
36
hotspot/src/share/vm/classfile/classLoaderExt.cpp
Normal 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);
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
30
hotspot/src/share/vm/classfile/systemDictionary_ext.hpp
Normal file
30
hotspot/src/share/vm/classfile/systemDictionary_ext.hpp
Normal 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
|
@ -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.
|
||||
|
31
hotspot/src/share/vm/classfile/vmSymbols_ext.hpp
Normal file
31
hotspot/src/share/vm/classfile/vmSymbols_ext.hpp
Normal 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
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 },
|
||||
|
@ -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>;
|
||||
|
Loading…
Reference in New Issue
Block a user