8140802: Clean up and refactor of class loading code for CDS
Reviewed-by: jiangli, acorn, coleenp
--- a/hotspot/make/excludeSrc.make Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/make/excludeSrc.make Tue Aug 18 11:27:23 2015 -0700
@@ -73,8 +73,9 @@
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)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/classfile/classListParser.cpp Tue Aug 18 11:27:23 2015 -0700
@@ -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;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/classfile/classListParser.hpp Tue Aug 18 11:27:23 2015 -0700
@@ -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
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp Tue Aug 18 11:27:23 2015 -0700
@@ -82,7 +82,7 @@
_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
--- a/hotspot/src/share/vm/classfile/classLoaderData.hpp Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp Tue Aug 18 11:27:23 2015 -0700
@@ -187,6 +187,9 @@
// 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 @@
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.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/classfile/classLoaderExt.cpp Tue Aug 18 11:27:23 2015 -0700
@@ -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);
+}
--- a/hotspot/src/share/vm/classfile/classLoaderExt.hpp Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/classfile/classLoaderExt.hpp Tue Aug 18 11:27:23 2015 -0700
@@ -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 @@
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
--- a/hotspot/src/share/vm/classfile/dictionary.cpp Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/classfile/dictionary.cpp Tue Aug 18 11:27:23 2015 -0700
@@ -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, 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 @@
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;
}
--- a/hotspot/src/share/vm/classfile/dictionary.hpp Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/classfile/dictionary.hpp Tue Aug 18 11:27:23 2015 -0700
@@ -53,6 +53,7 @@
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 @@
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);
--- a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp Tue Aug 18 11:27:23 2015 -0700
@@ -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 @@
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);
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Tue Aug 18 11:27:23 2015 -0700
@@ -322,6 +322,17 @@
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 @@
//
// 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 @@
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 @@
// 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
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Tue Aug 18 11:27:23 2015 -0700
@@ -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"
@@ -194,15 +195,18 @@
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 {
@@ -667,11 +671,6 @@
// 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,
--- a/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp Tue Aug 18 11:27:23 2015 -0700
@@ -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 @@
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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/classfile/systemDictionary_ext.hpp Tue Aug 18 11:27:23 2015 -0700
@@ -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
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Tue Aug 18 11:27:23 2015 -0700
@@ -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"
@@ -617,6 +618,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.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/classfile/vmSymbols_ext.hpp Tue Aug 18 11:27:23 2015 -0700
@@ -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
+
--- a/hotspot/src/share/vm/memory/metaspaceShared.cpp Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp Tue Aug 18 11:27:23 2015 -0700
@@ -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_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 @@
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 @@
_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 @@
}
}; // class VM_PopulateDumpSharedSpace
+VM_PopulateDumpSharedSpace* VM_PopulateDumpSharedSpace::_instance;
void VM_PopulateDumpSharedSpace::doit() {
Thread* THREAD = VMThread::vm_thread();
@@ -475,7 +518,11 @@
// 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 @@
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::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 @@
// 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 @@
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 @@
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 @@
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 @@
}
}
+// 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 @@
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.
--- a/hotspot/src/share/vm/memory/metaspaceShared.hpp Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/memory/metaspaceShared.hpp Tue Aug 18 11:27:23 2015 -0700
@@ -160,5 +160,8 @@
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
--- a/hotspot/src/share/vm/prims/whitebox.cpp Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/prims/whitebox.cpp Tue Aug 18 11:27:23 2015 -0700
@@ -1271,6 +1271,10 @@
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 @@
{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 },
--- a/hotspot/src/share/vm/utilities/hashtable.cpp Thu Nov 12 14:03:14 2015 +0100
+++ b/hotspot/src/share/vm/utilities/hashtable.cpp Tue Aug 18 11:27:23 2015 -0700
@@ -365,6 +365,7 @@
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 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>;