--- old/make/excludeSrc.make 2015-10-29 21:53:00.461399152 -0700 +++ new/make/excludeSrc.make 2015-10-29 21:53:00.353395073 -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) --- old/src/share/vm/classfile/classLoaderData.cpp 2015-10-29 21:53:01.085422717 -0700 +++ new/src/share/vm/classfile/classLoaderData.cpp 2015-10-29 21:53:00.981418789 -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 --- old/src/share/vm/classfile/classLoaderData.hpp 2015-10-29 21:53:01.713446432 -0700 +++ new/src/share/vm/classfile/classLoaderData.hpp 2015-10-29 21:53:01.605442353 -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. --- old/src/share/vm/classfile/classLoaderExt.hpp 2015-10-29 21:53:02.353470600 -0700 +++ new/src/share/vm/classfile/classLoaderExt.hpp 2015-10-29 21:53:02.237466220 -0700 @@ -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 --- old/src/share/vm/classfile/dictionary.cpp 2015-10-29 21:53:02.993494769 -0700 +++ new/src/share/vm/classfile/dictionary.cpp 2015-10-29 21:53:02.877490389 -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(table_size, sizeof(DictionaryEntry)) { + : TwoOopHashtable(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* t, int number_of_entries) - : TwoOopHashtable(table_size, sizeof(DictionaryEntry), t, number_of_entries) { + : TwoOopHashtable(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; } --- old/src/share/vm/classfile/dictionary.hpp 2015-10-29 21:53:03.665520146 -0700 +++ new/src/share/vm/classfile/dictionary.hpp 2015-10-29 21:53:03.553515917 -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::bucket(i); } @@ -66,6 +67,7 @@ Hashtable::add_entry(index, (HashtableEntry*)new_entry); } + static size_t entry_size(); public: Dictionary(int table_size); Dictionary(int table_size, HashtableBucket* t, int number_of_entries); --- old/src/share/vm/classfile/sharedPathsMiscInfo.hpp 2015-10-29 21:53:04.337545524 -0700 +++ new/src/share/vm/classfile/sharedPathsMiscInfo.hpp 2015-10-29 21:53:04.225541294 -0700 @@ -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 files/dirs void add_boot_classpath(const char* path) { add_path(path, BOOT); --- old/src/share/vm/classfile/systemDictionary.cpp 2015-10-29 21:53:04.993570297 -0700 +++ new/src/share/vm/classfile/systemDictionary.cpp 2015-10-29 21:53:04.885566218 -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 + // 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. @@ -1071,6 +1082,35 @@ check_loader_lock_contention(lockObject, THREAD); ObjectLocker ol(lockObject, THREAD, DoObjectLock); +#if INCLUDE_CDS + instanceKlassHandle sk = + SystemDictionaryShared::resolve_from_shared_space(class_name, + class_loader, + protection_domain, + st, + verify, + CHECK_NULL); + if (sk.not_null()) { + assert(MetaspaceShared::is_in_shared_space(sk()), "must be"); + + // Make sure we have an entry in the SystemDictionary on success + debug_only( { + Symbol* h_name = sk->name(); + ClassLoaderData *defining_loader_data = sk->class_loader_data(); + + MutexLocker mu(SystemDictionary_lock, THREAD); + + Klass* check = find_class(h_name, loader_data); + assert(check == sk(), "should be present in the dictionary"); + + Klass* check2 = find_class(h_name, defining_loader_data); + assert(check == check2, "name inconsistancy in SystemDictionary"); + } ); + + return sk(); + } +#endif + TempNewSymbol parsed_name = NULL; // Parse the stream. Note that we do this even though this klass might @@ -1201,8 +1241,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* interfaces = ik->local_interfaces(); @@ -1215,7 +1260,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 --- old/src/share/vm/classfile/systemDictionary.hpp 2015-10-29 21:53:05.701597033 -0700 +++ new/src/share/vm/classfile/systemDictionary.hpp 2015-10-29 21:53:05.593592955 -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, --- old/src/share/vm/classfile/systemDictionaryShared.hpp 2015-10-29 21:53:06.369622259 -0700 +++ new/src/share/vm/classfile/systemDictionaryShared.hpp 2015-10-29 21:53:06.253617879 -0700 @@ -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 Klass* resolve_from_shared_space(Symbol* class_name, + Handle class_loader, + Handle protection_domain, + ClassFileStream* cfs, + bool verify, + TRAPS) { + return NULL; + } }; #endif // SHARE_VM_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP --- old/src/share/vm/classfile/vmSymbols.hpp 2015-10-29 21:53:07.025647032 -0700 +++ new/src/share/vm/classfile/vmSymbols.hpp 2015-10-29 21:53:06.913642803 -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" @@ -611,6 +612,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. --- old/src/share/vm/memory/metaspaceShared.cpp 2015-10-29 21:53:07.713673014 -0700 +++ new/src/share/vm/memory/metaspaceShared.cpp 2015-10-29 21:53:07.597668633 -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; @@ -96,6 +99,10 @@ ik->array_klasses_do(collect_classes); } } + +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++) { @@ -422,12 +429,15 @@ VirtualSpace _mc_vs; CompactHashtableWriter* _string_cht; GrowableArray *_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 *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(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* 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. --- old/src/share/vm/memory/metaspaceShared.hpp 2015-10-29 21:53:08.397698844 -0700 +++ new/src/share/vm/memory/metaspaceShared.hpp 2015-10-29 21:53:08.293694917 -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 --- old/src/share/vm/prims/whitebox.cpp 2015-10-29 21:53:09.057723768 -0700 +++ new/src/share/vm/prims/whitebox.cpp 2015-10-29 21:53:08.937719236 -0700 @@ -1218,6 +1218,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(); @@ -1418,6 +1422,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 }, --- /dev/null 2015-04-28 03:38:03.853934809 -0700 +++ new/src/share/vm/classfile/classListParser.cpp 2015-10-29 21:53:09.625745218 -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 2015-04-28 03:38:03.853934809 -0700 +++ new/src/share/vm/classfile/classListParser.hpp 2015-10-29 21:53:10.217767574 -0700 @@ -0,0 +1,58 @@ +/* + * 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 Klass; + +class ClassListParser VALUE_OBJ_CLASS_SPEC { + 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 --- /dev/null 2015-04-28 03:38:03.853934809 -0700 +++ new/src/share/vm/classfile/classLoaderExt.cpp 2015-10-29 21:53:10.821790383 -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_permanent_symbol(parser->current_class_name(), THREAD); + guarantee(!HAS_PENDING_EXCEPTION, "Exception creating a symbol."); + return SystemDictionary::resolve_or_null(class_name_symbol, THREAD); +} --- /dev/null 2015-04-28 03:38:03.853934809 -0700 +++ new/src/share/vm/classfile/systemDictionary_ext.hpp 2015-10-29 21:53:11.425813193 -0700 @@ -0,0 +1,6 @@ +#ifndef SHARE_VM_CLASSFILE_SYSTEMDICTIONARY_EXT_HPP +#define SHARE_VM_CLASSFILE_SYSTEMDICTIONARY_EXT_HPP + +#define WK_KLASSES_DO_EXT(do_klass) + +#endif --- /dev/null 2015-04-28 03:38:03.853934809 -0700 +++ new/src/share/vm/classfile/vmSymbols_ext.hpp 2015-10-29 21:53:12.037836304 -0700 @@ -0,0 +1,6 @@ +#ifndef SHARE_VM_CLASSFILE_VMSYMBOLS_EXT_HPP +#define SHARE_VM_CLASSFILE_VMSYMBOLS_EXT_HPP + +#define VM_SYMBOLS_DO_EXT(template, do_alias) + +#endif