8194759: Support caching class mirror objects
Support archiving mirror objects for shared classes in 'open' archive java heap region. Reviewed-by: coleenp, iklam, mseledtsov, tschatzl
This commit is contained in:
parent
979d5b7986
commit
f987dec395
src/hotspot/share
classfile
logging
memory
oops
test/hotspot/jtreg/runtime/appcds/cacheObject
@ -481,6 +481,7 @@ static bool is_jfr_event_class(Klass *k) {
|
||||
void Dictionary::reorder_dictionary_for_sharing() {
|
||||
|
||||
// Copy all the dictionary entries into a single master list.
|
||||
assert(DumpSharedSpaces, "Should only be used at dump time");
|
||||
|
||||
DictionaryEntry* master_list = NULL;
|
||||
for (int i = 0; i < table_size(); ++i) {
|
||||
@ -488,7 +489,7 @@ void Dictionary::reorder_dictionary_for_sharing() {
|
||||
while (p != NULL) {
|
||||
DictionaryEntry* next = p->next();
|
||||
InstanceKlass*ik = p->instance_klass();
|
||||
if (ik->signers() != NULL) {
|
||||
if (ik->has_signer_and_not_archived()) {
|
||||
// We cannot include signed classes in the archive because the certificates
|
||||
// used during dump time may be different than those used during
|
||||
// runtime (due to expiration, etc).
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -71,6 +71,7 @@ class java_lang_String : AllStatic {
|
||||
};
|
||||
|
||||
static void compute_offsets();
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
||||
// Instance creation
|
||||
static Handle create_from_unicode(jchar* unicode, int len, TRAPS);
|
||||
@ -222,6 +223,15 @@ class java_lang_Class : AllStatic {
|
||||
static void fixup_mirror(Klass* k, TRAPS);
|
||||
static oop create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS);
|
||||
|
||||
// Archiving
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
static void archive_basic_type_mirrors(TRAPS) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
static oop archive_mirror(Klass* k, TRAPS) NOT_CDS_JAVA_HEAP_RETURN_(NULL);
|
||||
static oop process_archived_mirror(Klass* k, oop mirror, oop archived_mirror, Thread *THREAD)
|
||||
NOT_CDS_JAVA_HEAP_RETURN_(NULL);
|
||||
static void restore_archived_mirror(Klass *k, Handle mirror, Handle class_loader, Handle module,
|
||||
Handle protection_domain, TRAPS) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
|
||||
static void fixup_module_field(Klass* k, Handle module);
|
||||
|
||||
// Conversion
|
||||
@ -306,6 +316,8 @@ class java_lang_Thread : AllStatic {
|
||||
static void compute_offsets();
|
||||
|
||||
public:
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
||||
// Instance creation
|
||||
static oop create();
|
||||
// Returns the JavaThread associated with the thread obj
|
||||
@ -406,6 +418,8 @@ class java_lang_ThreadGroup : AllStatic {
|
||||
static void compute_offsets();
|
||||
|
||||
public:
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
||||
// parent ThreadGroup
|
||||
static oop parent(oop java_thread_group);
|
||||
// name
|
||||
@ -485,6 +499,7 @@ class java_lang_Throwable: AllStatic {
|
||||
static void print_stack_usage(Handle stream);
|
||||
|
||||
static void compute_offsets();
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
||||
// Allocate space for backtrace (created but stack trace not filled in)
|
||||
static void allocate_backtrace(Handle throwable, TRAPS);
|
||||
@ -515,6 +530,8 @@ class java_lang_reflect_AccessibleObject: AllStatic {
|
||||
static void compute_offsets();
|
||||
|
||||
public:
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
||||
// Accessors
|
||||
static jboolean override(oop reflect);
|
||||
static void set_override(oop reflect, jboolean value);
|
||||
@ -546,6 +563,8 @@ class java_lang_reflect_Method : public java_lang_reflect_AccessibleObject {
|
||||
static void compute_offsets();
|
||||
|
||||
public:
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
||||
// Allocation
|
||||
static Handle create(TRAPS);
|
||||
|
||||
@ -615,6 +634,8 @@ class java_lang_reflect_Constructor : public java_lang_reflect_AccessibleObject
|
||||
static void compute_offsets();
|
||||
|
||||
public:
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
||||
// Allocation
|
||||
static Handle create(TRAPS);
|
||||
|
||||
@ -673,6 +694,8 @@ class java_lang_reflect_Field : public java_lang_reflect_AccessibleObject {
|
||||
static void compute_offsets();
|
||||
|
||||
public:
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
||||
// Allocation
|
||||
static Handle create(TRAPS);
|
||||
|
||||
@ -728,6 +751,8 @@ class java_lang_reflect_Parameter {
|
||||
static void compute_offsets();
|
||||
|
||||
public:
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
||||
// Allocation
|
||||
static Handle create(TRAPS);
|
||||
|
||||
@ -758,6 +783,8 @@ class java_lang_Module {
|
||||
static void compute_offsets();
|
||||
|
||||
public:
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
||||
// Allocation
|
||||
static Handle create(Handle loader, Handle module_name, TRAPS);
|
||||
|
||||
@ -787,6 +814,8 @@ class reflect_ConstantPool {
|
||||
static void compute_offsets();
|
||||
|
||||
public:
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
||||
// Allocation
|
||||
static Handle create(TRAPS);
|
||||
|
||||
@ -809,6 +838,8 @@ class reflect_UnsafeStaticFieldAccessorImpl {
|
||||
static void compute_offsets();
|
||||
|
||||
public:
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
||||
static int base_offset() {
|
||||
return _base_offset;
|
||||
}
|
||||
@ -910,6 +941,7 @@ class java_lang_ref_SoftReference: public java_lang_ref_Reference {
|
||||
static void set_clock(jlong value);
|
||||
|
||||
static void compute_offsets();
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
};
|
||||
|
||||
// Interface to java.lang.invoke.MethodHandle objects
|
||||
@ -926,6 +958,8 @@ class java_lang_invoke_MethodHandle: AllStatic {
|
||||
static void compute_offsets();
|
||||
|
||||
public:
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
||||
// Accessors
|
||||
static oop type(oop mh);
|
||||
static void set_type(oop mh, oop mtype);
|
||||
@ -955,6 +989,8 @@ class java_lang_invoke_DirectMethodHandle: AllStatic {
|
||||
static void compute_offsets();
|
||||
|
||||
public:
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
||||
// Accessors
|
||||
static oop member(oop mh);
|
||||
|
||||
@ -980,6 +1016,8 @@ class java_lang_invoke_LambdaForm: AllStatic {
|
||||
static void compute_offsets();
|
||||
|
||||
public:
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
||||
// Accessors
|
||||
static oop vmentry(oop lform);
|
||||
static void set_vmentry(oop lform, oop invoker);
|
||||
@ -1011,6 +1049,8 @@ class java_lang_invoke_ResolvedMethodName : AllStatic {
|
||||
|
||||
static void compute_offsets();
|
||||
public:
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
||||
static int vmtarget_offset_in_bytes() { return _vmtarget_offset; }
|
||||
|
||||
static Method* vmtarget(oop resolved_method);
|
||||
@ -1048,6 +1088,7 @@ class java_lang_invoke_MemberName: AllStatic {
|
||||
static void compute_offsets();
|
||||
|
||||
public:
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
// Accessors
|
||||
static oop clazz(oop mname);
|
||||
static void set_clazz(oop mname, oop clazz);
|
||||
@ -1112,6 +1153,7 @@ class java_lang_invoke_MethodType: AllStatic {
|
||||
static void compute_offsets();
|
||||
|
||||
public:
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
// Accessors
|
||||
static oop rtype(oop mt);
|
||||
static objArrayOop ptypes(oop mt);
|
||||
@ -1147,6 +1189,7 @@ private:
|
||||
static void compute_offsets();
|
||||
|
||||
public:
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
// Accessors
|
||||
static oop target( oop site);
|
||||
static void set_target( oop site, oop target);
|
||||
@ -1180,6 +1223,7 @@ private:
|
||||
static void compute_offsets();
|
||||
|
||||
public:
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
// Accessors
|
||||
static DependencyContext vmdependencies(oop context);
|
||||
|
||||
@ -1203,6 +1247,7 @@ class java_security_AccessControlContext: AllStatic {
|
||||
|
||||
static void compute_offsets();
|
||||
public:
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
static oop create(objArrayHandle context, bool isPrivileged, Handle privileged_context, TRAPS);
|
||||
|
||||
static bool is_authorized(Handle context);
|
||||
@ -1228,6 +1273,7 @@ class java_lang_ClassLoader : AllStatic {
|
||||
|
||||
public:
|
||||
static void compute_offsets();
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
||||
static ClassLoaderData* loader_data(oop loader);
|
||||
static ClassLoaderData* cmpxchg_loader_data(ClassLoaderData* new_data, oop loader, ClassLoaderData* expected_data);
|
||||
@ -1279,6 +1325,7 @@ class java_lang_System : AllStatic {
|
||||
static bool has_security_manager();
|
||||
|
||||
static void compute_offsets();
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
||||
// Debugging
|
||||
friend class JavaClasses;
|
||||
@ -1316,6 +1363,7 @@ class java_lang_StackTraceElement: AllStatic {
|
||||
int version, int bci, Symbol* name, TRAPS);
|
||||
|
||||
static void compute_offsets();
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
||||
// Debugging
|
||||
friend class JavaClasses;
|
||||
@ -1359,6 +1407,7 @@ public:
|
||||
static void set_version(oop info, short value);
|
||||
|
||||
static void compute_offsets();
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
||||
static void to_stack_trace_element(Handle stackFrame, Handle stack_trace_element, TRAPS);
|
||||
|
||||
@ -1380,6 +1429,7 @@ class java_lang_LiveStackFrameInfo: AllStatic {
|
||||
static void set_mode(oop info, int value);
|
||||
|
||||
static void compute_offsets();
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
||||
// Debugging
|
||||
friend class JavaClasses;
|
||||
@ -1404,6 +1454,7 @@ class java_lang_AssertionStatusDirectives: AllStatic {
|
||||
static void set_deflt(oop obj, bool val);
|
||||
|
||||
static void compute_offsets();
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
||||
// Debugging
|
||||
friend class JavaClasses;
|
||||
@ -1417,6 +1468,7 @@ class java_nio_Buffer: AllStatic {
|
||||
public:
|
||||
static int limit_offset();
|
||||
static void compute_offsets();
|
||||
static void serialize(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
};
|
||||
|
||||
class java_util_concurrent_locks_AbstractOwnableSynchronizer : AllStatic {
|
||||
|
@ -703,7 +703,6 @@ bool StringTable::copy_shared_string(GrowableArray<MemRegion> *string_space,
|
||||
assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
|
||||
|
||||
Thread* THREAD = Thread::current();
|
||||
G1CollectedHeap::heap()->begin_archive_alloc_range();
|
||||
for (int i = 0; i < the_table()->table_size(); ++i) {
|
||||
HashtableEntry<oop, mtSymbol>* bucket = the_table()->bucket(i);
|
||||
for ( ; bucket != NULL; bucket = bucket->next()) {
|
||||
@ -727,7 +726,6 @@ bool StringTable::copy_shared_string(GrowableArray<MemRegion> *string_space,
|
||||
}
|
||||
}
|
||||
|
||||
G1CollectedHeap::heap()->end_archive_alloc_range(string_space, os::vm_allocation_granularity());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -148,6 +148,7 @@
|
||||
LOG_TAG(update) \
|
||||
LOG_TAG(unload) /* Trace unloading of classes */ \
|
||||
LOG_TAG(unshareable) \
|
||||
LOG_TAG(mirror) \
|
||||
LOG_TAG(verification) \
|
||||
LOG_TAG(verify) \
|
||||
LOG_TAG(vmoperation) \
|
||||
|
@ -125,14 +125,13 @@ public:
|
||||
size_t _cds_i2i_entry_code_buffers_size;
|
||||
size_t _core_spaces_size; // number of bytes allocated by the core spaces
|
||||
// (mc, md, ro, rw and od).
|
||||
|
||||
struct space_info {
|
||||
int _crc; // crc checksum of the current space
|
||||
size_t _file_offset; // sizeof(this) rounded to vm page size
|
||||
union {
|
||||
char* _base; // copy-on-write base address
|
||||
intx _offset; // offset from the compressed oop encoding base, only used
|
||||
// by string space
|
||||
// by archive heap space
|
||||
} _addr;
|
||||
size_t _used; // for setting space top on read
|
||||
bool _read_only; // read only space?
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2018, 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
|
||||
@ -344,6 +344,9 @@ public:
|
||||
// correct length.
|
||||
virtual void do_tag(int tag) = 0;
|
||||
|
||||
// Read/write the oop
|
||||
virtual void do_oop(oop* o) = 0;
|
||||
|
||||
bool writing() {
|
||||
return !reading();
|
||||
}
|
||||
|
@ -375,9 +375,45 @@ void MetaspaceShared::serialize(SerializeClosure* soc) {
|
||||
StringTable::serialize(soc);
|
||||
soc->do_tag(--tag);
|
||||
|
||||
serialize_well_known_classes(soc);
|
||||
soc->do_tag(--tag);
|
||||
|
||||
soc->do_tag(666);
|
||||
}
|
||||
|
||||
void MetaspaceShared::serialize_well_known_classes(SerializeClosure* soc) {
|
||||
java_lang_Class::serialize(soc);
|
||||
java_lang_String::serialize(soc);
|
||||
java_lang_System::serialize(soc);
|
||||
java_lang_ClassLoader::serialize(soc);
|
||||
java_lang_Throwable::serialize(soc);
|
||||
java_lang_Thread::serialize(soc);
|
||||
java_lang_ThreadGroup::serialize(soc);
|
||||
java_lang_AssertionStatusDirectives::serialize(soc);
|
||||
java_lang_ref_SoftReference::serialize(soc);
|
||||
java_lang_invoke_MethodHandle::serialize(soc);
|
||||
java_lang_invoke_DirectMethodHandle::serialize(soc);
|
||||
java_lang_invoke_MemberName::serialize(soc);
|
||||
java_lang_invoke_ResolvedMethodName::serialize(soc);
|
||||
java_lang_invoke_LambdaForm::serialize(soc);
|
||||
java_lang_invoke_MethodType::serialize(soc);
|
||||
java_lang_invoke_CallSite::serialize(soc);
|
||||
java_lang_invoke_MethodHandleNatives_CallSiteContext::serialize(soc);
|
||||
java_security_AccessControlContext::serialize(soc);
|
||||
java_lang_reflect_AccessibleObject::serialize(soc);
|
||||
java_lang_reflect_Method::serialize(soc);
|
||||
java_lang_reflect_Constructor::serialize(soc);
|
||||
java_lang_reflect_Field::serialize(soc);
|
||||
java_nio_Buffer::serialize(soc);
|
||||
reflect_ConstantPool::serialize(soc);
|
||||
reflect_UnsafeStaticFieldAccessorImpl::serialize(soc);
|
||||
java_lang_reflect_Parameter::serialize(soc);
|
||||
java_lang_Module::serialize(soc);
|
||||
java_lang_StackTraceElement::serialize(soc);
|
||||
java_lang_StackFrameInfo::serialize(soc);
|
||||
java_lang_LiveStackFrameInfo::serialize(soc);
|
||||
}
|
||||
|
||||
address MetaspaceShared::cds_i2i_entry_code_buffers(size_t total_size) {
|
||||
if (DumpSharedSpaces) {
|
||||
if (_cds_i2i_entry_code_buffers == NULL) {
|
||||
@ -415,7 +451,12 @@ static void collect_array_classes(Klass* k) {
|
||||
class CollectClassesClosure : public KlassClosure {
|
||||
void do_klass(Klass* k) {
|
||||
if (!(k->is_instance_klass() && InstanceKlass::cast(k)->is_in_error_state())) {
|
||||
_global_klass_objects->append_if_missing(k);
|
||||
if (k->is_instance_klass() && InstanceKlass::cast(k)->signers() != NULL) {
|
||||
// Mark any class with signers and don't add to the _global_klass_objects
|
||||
k->set_has_signer_and_not_archived();
|
||||
} else {
|
||||
_global_klass_objects->append_if_missing(k);
|
||||
}
|
||||
}
|
||||
if (k->is_array_klass()) {
|
||||
// Add in the array classes too
|
||||
@ -452,6 +493,19 @@ static void remove_java_mirror_in_classes() {
|
||||
}
|
||||
}
|
||||
|
||||
static void clear_basic_type_mirrors() {
|
||||
assert(!MetaspaceShared::is_heap_object_archiving_allowed(), "Sanity");
|
||||
Universe::set_int_mirror(NULL);
|
||||
Universe::set_float_mirror(NULL);
|
||||
Universe::set_double_mirror(NULL);
|
||||
Universe::set_byte_mirror(NULL);
|
||||
Universe::set_bool_mirror(NULL);
|
||||
Universe::set_char_mirror(NULL);
|
||||
Universe::set_long_mirror(NULL);
|
||||
Universe::set_short_mirror(NULL);
|
||||
Universe::set_void_mirror(NULL);
|
||||
}
|
||||
|
||||
static void rewrite_nofast_bytecode(Method* method) {
|
||||
BytecodeStream bcs(method);
|
||||
while (!bcs.is_last_bytecode()) {
|
||||
@ -775,6 +829,17 @@ public:
|
||||
_dump_region->append_intptr_t((intptr_t)tag);
|
||||
}
|
||||
|
||||
void do_oop(oop* o) {
|
||||
if (*o == NULL) {
|
||||
_dump_region->append_intptr_t(0);
|
||||
} else {
|
||||
assert(MetaspaceShared::is_heap_object_archiving_allowed(),
|
||||
"Archiving heap object is not allowed");
|
||||
_dump_region->append_intptr_t(
|
||||
(intptr_t)oopDesc::encode_heap_oop_not_null(*o));
|
||||
}
|
||||
}
|
||||
|
||||
void do_region(u_char* start, size_t size) {
|
||||
assert((intptr_t)start % sizeof(intptr_t) == 0, "bad alignment");
|
||||
assert(size % sizeof(intptr_t) == 0, "bad size");
|
||||
@ -935,7 +1000,7 @@ void DumpAllocStats::print_stats(int ro_all, int rw_all, int mc_all, int md_all)
|
||||
|
||||
class VM_PopulateDumpSharedSpace: public VM_Operation {
|
||||
private:
|
||||
GrowableArray<MemRegion> *_string_regions;
|
||||
GrowableArray<MemRegion> *_closed_archive_heap_regions;
|
||||
GrowableArray<MemRegion> *_open_archive_heap_regions;
|
||||
|
||||
void dump_java_heap_objects() NOT_CDS_JAVA_HEAP_RETURN;
|
||||
@ -1193,6 +1258,7 @@ public:
|
||||
}
|
||||
|
||||
static Klass* get_relocated_klass(Klass* orig_klass) {
|
||||
assert(DumpSharedSpaces, "dump time only");
|
||||
address* pp = _new_loc_table->get((address)orig_klass);
|
||||
assert(pp != NULL, "must be");
|
||||
Klass* klass = (Klass*)(*pp);
|
||||
@ -1222,7 +1288,11 @@ char* VM_PopulateDumpSharedSpace::dump_read_only_tables() {
|
||||
// Reorder the system dictionary. Moving the symbols affects
|
||||
// how the hash table indices are calculated.
|
||||
SystemDictionary::reorder_dictionary_for_sharing();
|
||||
|
||||
tty->print("Removing java_mirror ... ");
|
||||
if (!MetaspaceShared::is_heap_object_archiving_allowed()) {
|
||||
clear_basic_type_mirrors();
|
||||
}
|
||||
remove_java_mirror_in_classes();
|
||||
tty->print_cr("done. ");
|
||||
NOT_PRODUCT(SystemDictionary::verify();)
|
||||
@ -1312,7 +1382,7 @@ void VM_PopulateDumpSharedSpace::doit() {
|
||||
dump_symbols();
|
||||
|
||||
// Dump supported java heap objects
|
||||
_string_regions = NULL;
|
||||
_closed_archive_heap_regions = NULL;
|
||||
_open_archive_heap_regions = NULL;
|
||||
dump_java_heap_objects();
|
||||
|
||||
@ -1375,7 +1445,7 @@ void VM_PopulateDumpSharedSpace::doit() {
|
||||
write_region(mapinfo, MetaspaceShared::od, &_od_region, /*read_only=*/true, /*allow_exec=*/false);
|
||||
|
||||
_total_string_region_size = mapinfo->write_archive_heap_regions(
|
||||
_string_regions,
|
||||
_closed_archive_heap_regions,
|
||||
MetaspaceShared::first_string,
|
||||
MetaspaceShared::max_strings);
|
||||
_total_open_archive_region_size = mapinfo->write_archive_heap_regions(
|
||||
@ -1424,7 +1494,7 @@ void VM_PopulateDumpSharedSpace::print_region_stats() {
|
||||
_ro_region.print(total_reserved);
|
||||
_md_region.print(total_reserved);
|
||||
_od_region.print(total_reserved);
|
||||
print_heap_region_stats(_string_regions, "st", total_reserved);
|
||||
print_heap_region_stats(_closed_archive_heap_regions, "st", total_reserved);
|
||||
print_heap_region_stats(_open_archive_heap_regions, "oa", total_reserved);
|
||||
|
||||
tty->print_cr("total : " SIZE_FORMAT_W(9) " [100.0%% of total] out of " SIZE_FORMAT_W(9) " bytes [%5.1f%% used]",
|
||||
@ -1452,6 +1522,11 @@ void MetaspaceShared::relocate_klass_ptr(oop o) {
|
||||
o->set_klass(k);
|
||||
}
|
||||
|
||||
Klass* MetaspaceShared::get_relocated_klass(Klass *k) {
|
||||
assert(DumpSharedSpaces, "sanity");
|
||||
return ArchiveCompactor::get_relocated_klass(k);
|
||||
}
|
||||
|
||||
class LinkSharedClassesClosure : public KlassClosure {
|
||||
Thread* THREAD;
|
||||
bool _made_progress;
|
||||
@ -1693,11 +1768,11 @@ void VM_PopulateDumpSharedSpace::dump_java_heap_objects() {
|
||||
// Cache for recording where the archived objects are copied to
|
||||
MetaspaceShared::create_archive_object_cache();
|
||||
|
||||
tty->print_cr("Dumping String objects to closed archive heap region ...");
|
||||
tty->print_cr("Dumping objects to closed archive heap region ...");
|
||||
NOT_PRODUCT(StringTable::verify());
|
||||
// The string space has maximum two regions. See FileMapInfo::write_archive_heap_regions() for details.
|
||||
_string_regions = new GrowableArray<MemRegion>(2);
|
||||
StringTable::write_to_archive(_string_regions);
|
||||
// The closed space has maximum two regions. See FileMapInfo::write_archive_heap_regions() for details.
|
||||
_closed_archive_heap_regions = new GrowableArray<MemRegion>(2);
|
||||
MetaspaceShared::dump_closed_archive_heap_objects(_closed_archive_heap_regions);
|
||||
|
||||
tty->print_cr("Dumping objects to open archive heap region ...");
|
||||
_open_archive_heap_regions = new GrowableArray<MemRegion>(2);
|
||||
@ -1709,6 +1784,20 @@ void VM_PopulateDumpSharedSpace::dump_java_heap_objects() {
|
||||
G1HeapVerifier::verify_archive_regions();
|
||||
}
|
||||
|
||||
void MetaspaceShared::dump_closed_archive_heap_objects(
|
||||
GrowableArray<MemRegion> * closed_archive) {
|
||||
assert(is_heap_object_archiving_allowed(), "Cannot dump java heap objects");
|
||||
|
||||
Thread* THREAD = Thread::current();
|
||||
G1CollectedHeap::heap()->begin_archive_alloc_range();
|
||||
|
||||
// Archive interned string objects
|
||||
StringTable::write_to_archive(closed_archive);
|
||||
|
||||
G1CollectedHeap::heap()->end_archive_alloc_range(closed_archive,
|
||||
os::vm_allocation_granularity());
|
||||
}
|
||||
|
||||
void MetaspaceShared::dump_open_archive_heap_objects(
|
||||
GrowableArray<MemRegion> * open_archive) {
|
||||
assert(UseG1GC, "Only support G1 GC");
|
||||
@ -1718,21 +1807,33 @@ void MetaspaceShared::dump_open_archive_heap_objects(
|
||||
Thread* THREAD = Thread::current();
|
||||
G1CollectedHeap::heap()->begin_archive_alloc_range(true /* open */);
|
||||
|
||||
MetaspaceShared::archive_resolved_constants(THREAD);
|
||||
java_lang_Class::archive_basic_type_mirrors(THREAD);
|
||||
|
||||
MetaspaceShared::archive_klass_objects(THREAD);
|
||||
|
||||
G1CollectedHeap::heap()->end_archive_alloc_range(open_archive,
|
||||
os::vm_allocation_granularity());
|
||||
}
|
||||
|
||||
MetaspaceShared::ArchivedObjectCache* MetaspaceShared::_archive_object_cache = NULL;
|
||||
oop MetaspaceShared::archive_heap_object(oop obj, Thread* THREAD) {
|
||||
oop MetaspaceShared::find_archived_heap_object(oop obj) {
|
||||
assert(DumpSharedSpaces, "dump-time only");
|
||||
|
||||
ArchivedObjectCache* cache = MetaspaceShared::archive_object_cache();
|
||||
oop* p = cache->get(obj);
|
||||
if (p != NULL) {
|
||||
// already archived
|
||||
return *p;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
oop MetaspaceShared::archive_heap_object(oop obj, Thread* THREAD) {
|
||||
assert(DumpSharedSpaces, "dump-time only");
|
||||
|
||||
oop ao = find_archived_heap_object(obj);
|
||||
if (ao != NULL) {
|
||||
// already archived
|
||||
return ao;
|
||||
}
|
||||
|
||||
int len = obj->size();
|
||||
@ -1745,15 +1846,23 @@ oop MetaspaceShared::archive_heap_object(oop obj, Thread* THREAD) {
|
||||
if (archived_oop != NULL) {
|
||||
Copy::aligned_disjoint_words((HeapWord*)obj, (HeapWord*)archived_oop, len);
|
||||
relocate_klass_ptr(archived_oop);
|
||||
ArchivedObjectCache* cache = MetaspaceShared::archive_object_cache();
|
||||
cache->put(obj, archived_oop);
|
||||
}
|
||||
log_debug(cds)("Archived heap object " PTR_FORMAT " ==> " PTR_FORMAT,
|
||||
p2i(obj), p2i(archived_oop));
|
||||
return archived_oop;
|
||||
}
|
||||
|
||||
void MetaspaceShared::archive_resolved_constants(Thread* THREAD) {
|
||||
void MetaspaceShared::archive_klass_objects(Thread* THREAD) {
|
||||
int i;
|
||||
for (i = 0; i < _global_klass_objects->length(); i++) {
|
||||
Klass* k = _global_klass_objects->at(i);
|
||||
|
||||
// archive mirror object
|
||||
java_lang_Class::archive_mirror(k, CHECK);
|
||||
|
||||
// archive the resolved_referenes array
|
||||
if (k->is_instance_klass()) {
|
||||
InstanceKlass* ik = InstanceKlass::cast(k);
|
||||
ik->constants()->archive_resolved_references(THREAD);
|
||||
@ -1802,6 +1911,19 @@ public:
|
||||
FileMapInfo::assert_mark(tag == old_tag);
|
||||
}
|
||||
|
||||
void do_oop(oop *p) {
|
||||
narrowOop o = (narrowOop)nextPtr();
|
||||
if (o == 0 || !MetaspaceShared::open_archive_heap_region_mapped()) {
|
||||
p = NULL;
|
||||
} else {
|
||||
assert(MetaspaceShared::is_heap_object_archiving_allowed(),
|
||||
"Archived heap object is not allowed");
|
||||
assert(MetaspaceShared::open_archive_heap_region_mapped(),
|
||||
"Open archive heap region is not mapped");
|
||||
RootAccess<IN_ARCHIVE_ROOT>::oop_store(p, oopDesc::decode_heap_oop_not_null(o));
|
||||
}
|
||||
}
|
||||
|
||||
void do_region(u_char* start, size_t size) {
|
||||
assert((intptr_t)start % sizeof(intptr_t) == 0, "bad alignment");
|
||||
assert(size % sizeof(intptr_t) == 0, "bad size");
|
||||
|
@ -113,8 +113,9 @@ class MetaspaceShared : AllStatic {
|
||||
static ArchivedObjectCache* archive_object_cache() {
|
||||
return _archive_object_cache;
|
||||
}
|
||||
static oop find_archived_heap_object(oop obj);
|
||||
static oop archive_heap_object(oop obj, Thread* THREAD);
|
||||
static void archive_resolved_constants(Thread* THREAD);
|
||||
static void archive_klass_objects(Thread* THREAD);
|
||||
#endif
|
||||
static bool is_heap_object_archiving_allowed() {
|
||||
CDS_JAVA_HEAP_ONLY(return (UseG1GC && UseCompressedOops && UseCompressedClassPointers);)
|
||||
@ -128,6 +129,8 @@ class MetaspaceShared : AllStatic {
|
||||
}
|
||||
static void fixup_mapped_heap_regions() NOT_CDS_JAVA_HEAP_RETURN;
|
||||
|
||||
static void dump_closed_archive_heap_objects(GrowableArray<MemRegion> * closed_archive) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
|
||||
static void dump_open_archive_heap_objects(GrowableArray<MemRegion> * open_archive) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
static void set_open_archive_heap_region_mapped() {
|
||||
CDS_JAVA_HEAP_ONLY(_open_archive_heap_region_mapped = true);
|
||||
@ -199,7 +202,8 @@ class MetaspaceShared : AllStatic {
|
||||
static void zero_cpp_vtable_clones_for_writing();
|
||||
static void patch_cpp_vtable_pointers();
|
||||
static bool is_valid_shared_method(const Method* m) NOT_CDS_RETURN_(false);
|
||||
static void serialize(SerializeClosure* sc);
|
||||
static void serialize(SerializeClosure* sc) NOT_CDS_RETURN;
|
||||
static void serialize_well_known_classes(SerializeClosure* soc) NOT_CDS_RETURN;
|
||||
|
||||
static MetaspaceSharedStats* stats() {
|
||||
return &_stats;
|
||||
@ -248,5 +252,7 @@ class MetaspaceShared : AllStatic {
|
||||
return _cds_i2i_entry_code_buffers_size;
|
||||
}
|
||||
static void relocate_klass_ptr(oop o);
|
||||
|
||||
static Klass* get_relocated_klass(Klass *k);
|
||||
};
|
||||
#endif // SHARE_VM_MEMORY_METASPACESHARED_HPP
|
||||
|
@ -247,7 +247,7 @@ void Universe::metaspace_pointers_do(MetaspaceClosure* it) {
|
||||
_do_stack_walk_cache->metaspace_pointers_do(it);
|
||||
}
|
||||
|
||||
// Serialize metadata in and out of CDS archive, not oops.
|
||||
// Serialize metadata and pointers to primitive type mirrors in and out of CDS archive
|
||||
void Universe::serialize(SerializeClosure* f, bool do_all) {
|
||||
|
||||
f->do_ptr((void**)&_boolArrayKlassObj);
|
||||
@ -271,6 +271,20 @@ void Universe::serialize(SerializeClosure* f, bool do_all) {
|
||||
}
|
||||
}
|
||||
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
// The mirrors are NULL if MetaspaceShared::is_heap_object_archiving_allowed
|
||||
// is false.
|
||||
f->do_oop(&_int_mirror);
|
||||
f->do_oop(&_float_mirror);
|
||||
f->do_oop(&_double_mirror);
|
||||
f->do_oop(&_byte_mirror);
|
||||
f->do_oop(&_bool_mirror);
|
||||
f->do_oop(&_char_mirror);
|
||||
f->do_oop(&_long_mirror);
|
||||
f->do_oop(&_short_mirror);
|
||||
f->do_oop(&_void_mirror);
|
||||
#endif
|
||||
|
||||
f->do_ptr((void**)&_the_array_interfaces_array);
|
||||
f->do_ptr((void**)&_the_empty_int_array);
|
||||
f->do_ptr((void**)&_the_empty_short_array);
|
||||
@ -453,25 +467,38 @@ void Universe::genesis(TRAPS) {
|
||||
}
|
||||
|
||||
void Universe::initialize_basic_type_mirrors(TRAPS) {
|
||||
assert(_int_mirror==NULL, "basic type mirrors already initialized");
|
||||
_int_mirror =
|
||||
java_lang_Class::create_basic_type_mirror("int", T_INT, CHECK);
|
||||
_float_mirror =
|
||||
java_lang_Class::create_basic_type_mirror("float", T_FLOAT, CHECK);
|
||||
_double_mirror =
|
||||
java_lang_Class::create_basic_type_mirror("double", T_DOUBLE, CHECK);
|
||||
_byte_mirror =
|
||||
java_lang_Class::create_basic_type_mirror("byte", T_BYTE, CHECK);
|
||||
_bool_mirror =
|
||||
java_lang_Class::create_basic_type_mirror("boolean",T_BOOLEAN, CHECK);
|
||||
_char_mirror =
|
||||
java_lang_Class::create_basic_type_mirror("char", T_CHAR, CHECK);
|
||||
_long_mirror =
|
||||
java_lang_Class::create_basic_type_mirror("long", T_LONG, CHECK);
|
||||
_short_mirror =
|
||||
java_lang_Class::create_basic_type_mirror("short", T_SHORT, CHECK);
|
||||
_void_mirror =
|
||||
java_lang_Class::create_basic_type_mirror("void", T_VOID, CHECK);
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
if (UseSharedSpaces &&
|
||||
MetaspaceShared::open_archive_heap_region_mapped() &&
|
||||
_int_mirror != NULL) {
|
||||
assert(MetaspaceShared::is_heap_object_archiving_allowed(), "Sanity");
|
||||
assert(_float_mirror != NULL && _double_mirror != NULL &&
|
||||
_byte_mirror != NULL && _byte_mirror != NULL &&
|
||||
_bool_mirror != NULL && _char_mirror != NULL &&
|
||||
_long_mirror != NULL && _short_mirror != NULL &&
|
||||
_void_mirror != NULL, "Sanity");
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
_int_mirror =
|
||||
java_lang_Class::create_basic_type_mirror("int", T_INT, CHECK);
|
||||
_float_mirror =
|
||||
java_lang_Class::create_basic_type_mirror("float", T_FLOAT, CHECK);
|
||||
_double_mirror =
|
||||
java_lang_Class::create_basic_type_mirror("double", T_DOUBLE, CHECK);
|
||||
_byte_mirror =
|
||||
java_lang_Class::create_basic_type_mirror("byte", T_BYTE, CHECK);
|
||||
_bool_mirror =
|
||||
java_lang_Class::create_basic_type_mirror("boolean",T_BOOLEAN, CHECK);
|
||||
_char_mirror =
|
||||
java_lang_Class::create_basic_type_mirror("char", T_CHAR, CHECK);
|
||||
_long_mirror =
|
||||
java_lang_Class::create_basic_type_mirror("long", T_LONG, CHECK);
|
||||
_short_mirror =
|
||||
java_lang_Class::create_basic_type_mirror("short", T_SHORT, CHECK);
|
||||
_void_mirror =
|
||||
java_lang_Class::create_basic_type_mirror("void", T_VOID, CHECK);
|
||||
}
|
||||
|
||||
_mirrors[T_INT] = _int_mirror;
|
||||
_mirrors[T_FLOAT] = _float_mirror;
|
||||
|
@ -294,6 +294,16 @@ class Universe: AllStatic {
|
||||
static oop short_mirror() { return check_mirror(_short_mirror); }
|
||||
static oop void_mirror() { return check_mirror(_void_mirror); }
|
||||
|
||||
static void set_int_mirror(oop m) { _int_mirror = m; }
|
||||
static void set_float_mirror(oop m) { _float_mirror = m; }
|
||||
static void set_double_mirror(oop m) { _double_mirror = m; }
|
||||
static void set_byte_mirror(oop m) { _byte_mirror = m; }
|
||||
static void set_bool_mirror(oop m) { _bool_mirror = m; }
|
||||
static void set_char_mirror(oop m) { _char_mirror = m; }
|
||||
static void set_long_mirror(oop m) { _long_mirror = m; }
|
||||
static void set_short_mirror(oop m) { _short_mirror = m; }
|
||||
static void set_void_mirror(oop m) { _void_mirror = m; }
|
||||
|
||||
// table of same
|
||||
static oop _mirrors[T_VOID+1];
|
||||
|
||||
|
@ -183,7 +183,8 @@ void* Klass::operator new(size_t size, ClassLoaderData* loader_data, size_t word
|
||||
Klass::Klass() : _prototype_header(markOopDesc::prototype()),
|
||||
_shared_class_path_index(-1),
|
||||
_java_mirror(NULL) {
|
||||
|
||||
CDS_ONLY(_shared_class_flags = 0;)
|
||||
CDS_JAVA_HEAP_ONLY(_archived_mirror = 0;)
|
||||
_primary_supers[0] = this;
|
||||
set_super_check_offset(in_bytes(primary_supers_offset()));
|
||||
}
|
||||
@ -519,29 +520,71 @@ void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protec
|
||||
loader_data->add_class(this);
|
||||
}
|
||||
|
||||
// Recreate the class mirror.
|
||||
Handle loader(THREAD, loader_data->class_loader());
|
||||
ModuleEntry* module_entry = NULL;
|
||||
Klass* k = this;
|
||||
if (k->is_objArray_klass()) {
|
||||
k = ObjArrayKlass::cast(k)->bottom_klass();
|
||||
}
|
||||
// Obtain klass' module.
|
||||
if (k->is_instance_klass()) {
|
||||
InstanceKlass* ik = (InstanceKlass*) k;
|
||||
module_entry = ik->module();
|
||||
} else {
|
||||
module_entry = ModuleEntryTable::javabase_moduleEntry();
|
||||
}
|
||||
// Obtain java.lang.Module, if available
|
||||
Handle module_handle(THREAD, ((module_entry != NULL) ? module_entry->module() : (oop)NULL));
|
||||
|
||||
if (this->has_raw_archived_mirror()) {
|
||||
log_debug(cds, mirror)("%s has raw archived mirror", external_name());
|
||||
if (MetaspaceShared::open_archive_heap_region_mapped()) {
|
||||
oop m = archived_java_mirror();
|
||||
log_debug(cds, mirror)("Archived mirror is: " PTR_FORMAT, p2i(m));
|
||||
if (m != NULL) {
|
||||
// mirror is archived, restore
|
||||
assert(oopDesc::is_archive_object(m), "must be archived mirror object");
|
||||
Handle m_h(THREAD, m);
|
||||
java_lang_Class::restore_archived_mirror(this, m_h, loader, module_handle, protection_domain, CHECK);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// No archived mirror data
|
||||
_java_mirror = NULL;
|
||||
this->clear_has_raw_archived_mirror();
|
||||
}
|
||||
|
||||
// Only recreate it if not present. A previous attempt to restore may have
|
||||
// gotten an OOM later but keep the mirror if it was created.
|
||||
if (java_mirror() == NULL) {
|
||||
Handle loader(THREAD, loader_data->class_loader());
|
||||
ModuleEntry* module_entry = NULL;
|
||||
Klass* k = this;
|
||||
if (k->is_objArray_klass()) {
|
||||
k = ObjArrayKlass::cast(k)->bottom_klass();
|
||||
}
|
||||
// Obtain klass' module.
|
||||
if (k->is_instance_klass()) {
|
||||
InstanceKlass* ik = (InstanceKlass*) k;
|
||||
module_entry = ik->module();
|
||||
} else {
|
||||
module_entry = ModuleEntryTable::javabase_moduleEntry();
|
||||
}
|
||||
// Obtain java.lang.Module, if available
|
||||
Handle module_handle(THREAD, ((module_entry != NULL) ? module_entry->module() : (oop)NULL));
|
||||
log_trace(cds, mirror)("Recreate mirror for %s", external_name());
|
||||
java_lang_Class::create_mirror(this, loader, module_handle, protection_domain, CHECK);
|
||||
}
|
||||
}
|
||||
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
// Used at CDS dump time to access the archived mirror. No GC barrier.
|
||||
oop Klass::archived_java_mirror_raw() {
|
||||
assert(DumpSharedSpaces, "called only during runtime");
|
||||
assert(has_raw_archived_mirror(), "must have raw archived mirror");
|
||||
return oopDesc::decode_heap_oop(_archived_mirror);
|
||||
}
|
||||
|
||||
// Used at CDS runtime to get the archived mirror from shared class. Uses GC barrier.
|
||||
oop Klass::archived_java_mirror() {
|
||||
assert(UseSharedSpaces, "UseSharedSpaces expected.");
|
||||
assert(has_raw_archived_mirror(), "must have raw archived mirror");
|
||||
return RootAccess<IN_ARCHIVE_ROOT>::oop_load(&_archived_mirror);
|
||||
}
|
||||
|
||||
// No GC barrier
|
||||
void Klass::set_archived_java_mirror_raw(oop m) {
|
||||
assert(DumpSharedSpaces, "called only during runtime");
|
||||
_archived_mirror = oopDesc::encode_heap_oop(m);
|
||||
}
|
||||
#endif // INCLUDE_CDS_JAVA_HEAP
|
||||
|
||||
Klass* Klass::array_klass_or_null(int rank) {
|
||||
EXCEPTION_MARK;
|
||||
// No exception can be thrown by array_klass_impl when called with or_null == true.
|
||||
|
@ -156,6 +156,18 @@ private:
|
||||
// -1.
|
||||
jshort _shared_class_path_index;
|
||||
|
||||
#if INCLUDE_CDS
|
||||
// Flags of the current shared class.
|
||||
u2 _shared_class_flags;
|
||||
enum {
|
||||
_has_raw_archived_mirror = 1,
|
||||
_has_signer_and_not_archived = 1 << 2
|
||||
};
|
||||
#endif
|
||||
// The _archived_mirror is set at CDS dump time pointing to the cached mirror
|
||||
// in the open archive heap region when archiving java object is supported.
|
||||
CDS_JAVA_HEAP_ONLY(narrowOop _archived_mirror);
|
||||
|
||||
friend class SharedClassUtil;
|
||||
protected:
|
||||
|
||||
@ -229,11 +241,17 @@ protected:
|
||||
oop java_mirror() const;
|
||||
void set_java_mirror(Handle m);
|
||||
|
||||
oop archived_java_mirror_raw() NOT_CDS_JAVA_HEAP_RETURN_(NULL); // no GC barrier
|
||||
oop archived_java_mirror() NOT_CDS_JAVA_HEAP_RETURN_(NULL); // accessor with GC barrier
|
||||
void set_archived_java_mirror_raw(oop m) NOT_CDS_JAVA_HEAP_RETURN; // no GC barrier
|
||||
|
||||
// Temporary mirror switch used by RedefineClasses
|
||||
// Both mirrors are on the ClassLoaderData::_handles list already so no
|
||||
// barriers are needed.
|
||||
void set_java_mirror_handle(OopHandle mirror) { _java_mirror = mirror; }
|
||||
OopHandle java_mirror_handle() const { return _java_mirror; }
|
||||
OopHandle java_mirror_handle() const {
|
||||
return _java_mirror;
|
||||
}
|
||||
|
||||
// modifier flags
|
||||
jint modifier_flags() const { return _modifier_flags; }
|
||||
@ -267,6 +285,26 @@ protected:
|
||||
_shared_class_path_index = index;
|
||||
};
|
||||
|
||||
void set_has_raw_archived_mirror() {
|
||||
CDS_ONLY(_shared_class_flags |= _has_raw_archived_mirror;)
|
||||
}
|
||||
void clear_has_raw_archived_mirror() {
|
||||
CDS_ONLY(_shared_class_flags &= ~_has_raw_archived_mirror;)
|
||||
}
|
||||
bool has_raw_archived_mirror() const {
|
||||
CDS_ONLY(return (_shared_class_flags & _has_raw_archived_mirror) != 0;)
|
||||
NOT_CDS(return false;)
|
||||
}
|
||||
#if INCLUDE_CDS
|
||||
void set_has_signer_and_not_archived() {
|
||||
_shared_class_flags |= _has_signer_and_not_archived;
|
||||
}
|
||||
bool has_signer_and_not_archived() const {
|
||||
assert(DumpSharedSpaces, "dump time only");
|
||||
return (_shared_class_flags & _has_signer_and_not_archived) != 0;
|
||||
}
|
||||
#endif // INCLUDE_CDS
|
||||
|
||||
// Obtain the module or package for this class
|
||||
virtual ModuleEntry* module() const = 0;
|
||||
virtual PackageEntry* package() const = 0;
|
||||
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import sun.hotspot.WhiteBox;
|
||||
|
||||
//
|
||||
// Test class mirror objects are cached when open archive heap objects are mapped:
|
||||
// - Well-known shared library classes:
|
||||
// java.lang.Object
|
||||
// java.lang.String
|
||||
// - Shared application class loaded by the system class loader
|
||||
// - Shared application class loaded user defined class loader
|
||||
//
|
||||
public class CheckCachedMirrorApp {
|
||||
static WhiteBox wb;
|
||||
public static void main(String args[]) throws Exception {
|
||||
String path = args[0];
|
||||
URL url = new File(path).toURI().toURL();
|
||||
URL[] urls = new URL[] {url};
|
||||
|
||||
URLClassLoader loader = new URLClassLoader(urls);
|
||||
Class hello = loader.loadClass("Hello");
|
||||
System.out.println("Loaded " + hello + " from " + url + " using loader " + loader);
|
||||
|
||||
wb = WhiteBox.getWhiteBox();
|
||||
|
||||
if (!wb.areOpenArchiveHeapObjectsMapped()) {
|
||||
System.out.println("Archived open_archive_heap objects are not mapped.");
|
||||
System.out.println("This may happen during normal operation. Test Skipped.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Well-known shared library classes
|
||||
Class object_class = Object.class;
|
||||
checkMirror(object_class, true);
|
||||
Class string_class = String.class;
|
||||
checkMirror(string_class, true);
|
||||
|
||||
// Shared app class
|
||||
Class app_class = CheckCachedMirrorApp.class;
|
||||
checkMirror(app_class, true);
|
||||
|
||||
// Hello is shared class and loaded by the 'loader' defined in current app.
|
||||
// It should not have cached resolved_references.
|
||||
Class class_with_user_defined_loader = hello;
|
||||
checkMirror(class_with_user_defined_loader, false);
|
||||
}
|
||||
|
||||
static void checkMirror(Class c, boolean mirrorShouldBeArchived) {
|
||||
System.out.print("Check cached mirror for " + c);
|
||||
if (wb.isSharedClass(c)) {
|
||||
// Check if the Class object is cached
|
||||
if (mirrorShouldBeArchived && wb.isShared(c)) {
|
||||
System.out.println(c + " mirror is cached. Expected.");
|
||||
} else if (!mirrorShouldBeArchived && !wb.isShared(c)) {
|
||||
System.out.println(c + " mirror is not cached. Expected.");
|
||||
} else if (mirrorShouldBeArchived && !wb.isShared(c)) {
|
||||
throw new RuntimeException(
|
||||
"FAILED. " + c + " mirror is not cached.");
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
"FAILED. " + c + " mirror should not be cached.");
|
||||
}
|
||||
} else {
|
||||
System.out.println("Class " + c + "is not shared, skipping the check for mirror");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Test archived mirror
|
||||
* @requires vm.cds.archived.java.heap
|
||||
* @requires vm.cds.custom.loaders
|
||||
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @modules java.management
|
||||
* jdk.jartool/sun.tools.jar
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* @compile CheckCachedMirrorApp.java
|
||||
* @compile ../test-classes/Hello.java
|
||||
* @run driver ClassFileInstaller -jar app.jar CheckCachedMirrorApp
|
||||
* @run driver ClassFileInstaller -jar hello.jar Hello
|
||||
* @run driver ClassFileInstaller -jar WhiteBox.jar sun.hotspot.WhiteBox
|
||||
* @run main CheckCachedMirrorTest
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import sun.hotspot.WhiteBox;
|
||||
|
||||
public class CheckCachedMirrorTest {
|
||||
public static void main(String[] args) throws Exception {
|
||||
String wbJar = ClassFileInstaller.getJarPath("WhiteBox.jar");
|
||||
String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar;
|
||||
String appJar = ClassFileInstaller.getJarPath("app.jar");
|
||||
String helloJarPath = ClassFileInstaller.getJarPath("hello.jar");
|
||||
|
||||
String classlist[] = new String[] {
|
||||
"CheckCachedMirrorApp", // built-in app loader
|
||||
"java/lang/Object id: 1", // boot loader
|
||||
"Hello id: 2 super: 1 source: " + helloJarPath // custom loader
|
||||
};
|
||||
|
||||
TestCommon.testDump(appJar, classlist, use_whitebox_jar);
|
||||
OutputAnalyzer output = TestCommon.exec(appJar, use_whitebox_jar,
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:+WhiteBoxAPI",
|
||||
"-Xlog:cds=debug",
|
||||
"CheckCachedMirrorApp",
|
||||
helloJarPath);
|
||||
TestCommon.checkExec(output);
|
||||
}
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import sun.hotspot.WhiteBox;
|
||||
|
||||
//
|
||||
// - Test static final String field with initial value in cached mirror should be also archived.
|
||||
// - GC should not crash when reference fields in cached mirror are updated at runtime
|
||||
// - Reference fields are updated to point to runtime created objects
|
||||
// - Reference fields are nullified
|
||||
//
|
||||
public class MirrorWithReferenceFieldsApp {
|
||||
|
||||
// Static String field with initial value
|
||||
static final String archived_field = "abc";
|
||||
|
||||
// Static object field
|
||||
static Object non_archived_field_1;
|
||||
|
||||
// Instance field
|
||||
Integer non_archived_field_2;
|
||||
|
||||
public MirrorWithReferenceFieldsApp() {
|
||||
non_archived_field_1 = new Object();
|
||||
non_archived_field_2 = new Integer(1);
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
WhiteBox wb = WhiteBox.getWhiteBox();
|
||||
|
||||
if (!wb.areOpenArchiveHeapObjectsMapped()) {
|
||||
System.out.println("Archived open_archive_heap objects are not mapped.");
|
||||
System.out.println("This may happen during normal operation. Test Skipped.");
|
||||
return;
|
||||
}
|
||||
|
||||
MirrorWithReferenceFieldsApp m = new MirrorWithReferenceFieldsApp();
|
||||
m.test(wb);
|
||||
}
|
||||
|
||||
public void test(WhiteBox wb) {
|
||||
Class c = MirrorWithReferenceFieldsApp.class;
|
||||
if (wb.isSharedClass(c)) {
|
||||
// Check if the Class object is cached
|
||||
if (wb.isShared(c)) {
|
||||
System.out.println(c + " mirror is cached. Expected.");
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
"FAILED. " + c + " mirror should be cached.");
|
||||
}
|
||||
|
||||
// Check fields
|
||||
|
||||
if (wb.isShared(archived_field)) {
|
||||
System.out.println("archived_field is archived as excepted");
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
"FAILED. archived_field is not archived.");
|
||||
}
|
||||
|
||||
// GC should not crash
|
||||
System.gc();
|
||||
System.gc();
|
||||
System.gc();
|
||||
|
||||
non_archived_field_1 = null;
|
||||
non_archived_field_2 = null;
|
||||
|
||||
System.gc();
|
||||
System.gc();
|
||||
System.gc();
|
||||
|
||||
System.out.println("Done.");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Test archived mirror with reference fields
|
||||
* @requires vm.cds.archived.java.heap
|
||||
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @modules java.management
|
||||
* jdk.jartool/sun.tools.jar
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* @compile MirrorWithReferenceFieldsApp.java
|
||||
* @run driver ClassFileInstaller -jar app.jar MirrorWithReferenceFieldsApp
|
||||
* @run driver ClassFileInstaller -jar WhiteBox.jar sun.hotspot.WhiteBox
|
||||
* @run main MirrorWithReferenceFieldsTest
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import sun.hotspot.WhiteBox;
|
||||
|
||||
public class MirrorWithReferenceFieldsTest {
|
||||
public static void main(String[] args) throws Exception {
|
||||
String wbJar = ClassFileInstaller.getJarPath("WhiteBox.jar");
|
||||
String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar;
|
||||
String appJar = ClassFileInstaller.getJarPath("app.jar");
|
||||
|
||||
String classlist[] = new String[] {
|
||||
"MirrorWithReferenceFieldsApp",
|
||||
};
|
||||
|
||||
TestCommon.testDump(appJar, classlist, use_whitebox_jar);
|
||||
OutputAnalyzer output = TestCommon.exec(appJar, use_whitebox_jar,
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:+WhiteBoxAPI",
|
||||
"-XX:+VerifyAfterGC",
|
||||
"MirrorWithReferenceFieldsApp");
|
||||
try {
|
||||
TestCommon.checkExec(output, "Done");
|
||||
} catch (Exception e) {
|
||||
output.shouldContain("Archived open_archive_heap objects are not mapped");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,205 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import sun.hotspot.WhiteBox;
|
||||
|
||||
//
|
||||
// Test primitive type class mirror objects are cached when open archive heap
|
||||
// objects are mapped.
|
||||
//
|
||||
public class PrimitiveTypesApp {
|
||||
public static void main(String[] args) {
|
||||
WhiteBox wb = WhiteBox.getWhiteBox();
|
||||
if (!wb.areOpenArchiveHeapObjectsMapped()) {
|
||||
System.out.println("Archived open_archive_heap objects are not mapped.");
|
||||
System.out.println("This may happen during normal operation. Test Skipped.");
|
||||
return;
|
||||
}
|
||||
|
||||
FieldsTest ft = new FieldsTest();
|
||||
ft.testBoolean(wb);
|
||||
ft.testByte(wb);
|
||||
ft.testChar(wb);
|
||||
ft.testInt(wb);
|
||||
ft.testShort(wb);
|
||||
ft.testLong(wb);
|
||||
ft.testFloat(wb);
|
||||
ft.testDouble(wb);
|
||||
}
|
||||
}
|
||||
|
||||
class FieldsTest {
|
||||
public boolean f_boolean;
|
||||
public byte f_byte;
|
||||
public char f_char;
|
||||
public int f_int;
|
||||
public short f_short;
|
||||
public long f_long;
|
||||
public float f_float;
|
||||
public double f_double;
|
||||
|
||||
FieldsTest() {
|
||||
f_byte = 1;
|
||||
f_boolean = false;
|
||||
f_char = 'a';
|
||||
f_int = 1;
|
||||
f_short = 100;
|
||||
f_long = 2018L;
|
||||
f_float = 1.0f;
|
||||
f_double = 2.5;
|
||||
}
|
||||
|
||||
void testBoolean(WhiteBox wb) {
|
||||
try {
|
||||
Field f = this.getClass().getDeclaredField("f_boolean");
|
||||
f.setBoolean(this, true);
|
||||
if (!f_boolean) {
|
||||
throw new RuntimeException("FAILED. Field f_boolean has unexpected value: " + f_boolean);
|
||||
}
|
||||
checkPrimitiveType(wb, f, Boolean.TYPE);
|
||||
} catch (NoSuchFieldException nsfe) {
|
||||
throw new RuntimeException(nsfe);
|
||||
} catch (IllegalAccessException iae) {
|
||||
throw new RuntimeException(iae);
|
||||
}
|
||||
}
|
||||
|
||||
void testByte(WhiteBox wb) {
|
||||
try {
|
||||
Field f = this.getClass().getDeclaredField("f_byte");
|
||||
f.setByte(this, (byte)9);
|
||||
if (f_byte != (byte)9) {
|
||||
throw new RuntimeException("FAILED. Field f_byte has unexpected value: " + f_byte);
|
||||
}
|
||||
checkPrimitiveType(wb, f, Byte.TYPE);
|
||||
} catch (NoSuchFieldException nsfe) {
|
||||
throw new RuntimeException(nsfe);
|
||||
} catch (IllegalAccessException iae) {
|
||||
throw new RuntimeException(iae);
|
||||
}
|
||||
}
|
||||
|
||||
void testChar(WhiteBox wb) {
|
||||
try {
|
||||
Field f = this.getClass().getDeclaredField("f_char");
|
||||
f.setChar(this, 'b');
|
||||
if (f_char != 'b') {
|
||||
throw new RuntimeException("FAILED. Field f_char has unexpected value: " + f_char);
|
||||
}
|
||||
checkPrimitiveType(wb, f, Character.TYPE);
|
||||
} catch (NoSuchFieldException nsfe) {
|
||||
throw new RuntimeException(nsfe);
|
||||
} catch (IllegalAccessException iae) {
|
||||
throw new RuntimeException(iae);
|
||||
}
|
||||
}
|
||||
|
||||
void testInt(WhiteBox wb) {
|
||||
try {
|
||||
Field f = this.getClass().getDeclaredField("f_int");
|
||||
f.setInt(this, 9999);
|
||||
if (f_int != 9999) {
|
||||
throw new RuntimeException("FAILED. Field f_int has unexpected value: " + f_int);
|
||||
}
|
||||
checkPrimitiveType(wb, f, Integer.TYPE);
|
||||
} catch (NoSuchFieldException nsfe) {
|
||||
throw new RuntimeException(nsfe);
|
||||
} catch (IllegalAccessException iae) {
|
||||
throw new RuntimeException(iae);
|
||||
}
|
||||
}
|
||||
|
||||
void testShort(WhiteBox wb) {
|
||||
try {
|
||||
Field f = this.getClass().getDeclaredField("f_short");
|
||||
f.setShort(this, (short)99);
|
||||
if (f_short != 99) {
|
||||
throw new RuntimeException("FAILED. Field f_short has unexpected value: " + f_short);
|
||||
}
|
||||
checkPrimitiveType(wb, f, Short.TYPE);
|
||||
} catch (NoSuchFieldException nsfe) {
|
||||
throw new RuntimeException(nsfe);
|
||||
} catch (IllegalAccessException iae) {
|
||||
throw new RuntimeException(iae);
|
||||
}
|
||||
}
|
||||
|
||||
void testLong(WhiteBox wb) {
|
||||
try {
|
||||
Field f = this.getClass().getDeclaredField("f_long");
|
||||
f.setLong(this, 99L);
|
||||
if (f_long != 99L) {
|
||||
throw new RuntimeException("FAILED. Field f_long has unexpected value: " + f_long);
|
||||
}
|
||||
checkPrimitiveType(wb, f, Long.TYPE);
|
||||
} catch (NoSuchFieldException nsfe) {
|
||||
throw new RuntimeException(nsfe);
|
||||
} catch (IllegalAccessException iae) {
|
||||
throw new RuntimeException(iae);
|
||||
}
|
||||
}
|
||||
|
||||
void testFloat(WhiteBox wb) {
|
||||
try {
|
||||
Field f = this.getClass().getDeclaredField("f_float");
|
||||
f.setFloat(this, 9.9f);
|
||||
if (f_float != 9.9f) {
|
||||
throw new RuntimeException("FAILED. Field f_float has unexpected value: " + f_float);
|
||||
}
|
||||
checkPrimitiveType(wb, f, Float.TYPE);
|
||||
} catch (NoSuchFieldException nsfe) {
|
||||
throw new RuntimeException(nsfe);
|
||||
} catch (IllegalAccessException iae) {
|
||||
throw new RuntimeException(iae);
|
||||
}
|
||||
}
|
||||
|
||||
void testDouble(WhiteBox wb) {
|
||||
try {
|
||||
Field f = this.getClass().getDeclaredField("f_double");
|
||||
f.setDouble(this, 9.9);
|
||||
if (f_double != 9.9) {
|
||||
throw new RuntimeException("FAILED. Field f_double has unexpected value: " + f_double);
|
||||
}
|
||||
checkPrimitiveType(wb, f, Double.TYPE);
|
||||
} catch (NoSuchFieldException nsfe) {
|
||||
throw new RuntimeException(nsfe);
|
||||
} catch (IllegalAccessException iae) {
|
||||
throw new RuntimeException(iae);
|
||||
}
|
||||
}
|
||||
|
||||
void checkPrimitiveType(WhiteBox wb, Field f, Class t) {
|
||||
Class c = f.getType();
|
||||
if (!(c.isPrimitive() && c == t)) {
|
||||
throw new RuntimeException("FAILED. " + c + " is not primitive type " + t);
|
||||
}
|
||||
if (wb.isShared(c)) {
|
||||
System.out.println(c + " is cached, expected");
|
||||
} else {
|
||||
throw new RuntimeException("FAILED. " + c + " is not cached.");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Test archived primitive type mirrors
|
||||
* @requires vm.cds.archived.java.heap
|
||||
* @library /test/lib /test/hotspot/jtreg/runtime/appcds
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @modules java.management
|
||||
* jdk.jartool/sun.tools.jar
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* @compile PrimitiveTypesApp.java
|
||||
* @run driver ClassFileInstaller -jar app.jar PrimitiveTypesApp FieldsTest
|
||||
* @run driver ClassFileInstaller -jar WhiteBox.jar sun.hotspot.WhiteBox
|
||||
* @run main PrimitiveTypesTest
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import sun.hotspot.WhiteBox;
|
||||
|
||||
public class PrimitiveTypesTest {
|
||||
public static void main(String[] args) throws Exception {
|
||||
String wbJar = ClassFileInstaller.getJarPath("WhiteBox.jar");
|
||||
String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar;
|
||||
String appJar = ClassFileInstaller.getJarPath("app.jar");
|
||||
|
||||
String classlist[] = new String[] {
|
||||
"PrimitiveTypesApp",
|
||||
"FieldsTest"
|
||||
};
|
||||
|
||||
TestCommon.testDump(appJar, classlist, use_whitebox_jar);
|
||||
OutputAnalyzer output = TestCommon.exec(appJar, use_whitebox_jar,
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:+WhiteBoxAPI",
|
||||
"-XX:+VerifyAfterGC",
|
||||
"PrimitiveTypesApp");
|
||||
TestCommon.checkExec(output);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2018, 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
|
||||
@ -89,6 +89,16 @@ public class RedefineClassApp {
|
||||
doTest(group, new Foo(), jar);
|
||||
}
|
||||
|
||||
static void checkArchivedMirrorObject(Class klass) {
|
||||
if (wb.areOpenArchiveHeapObjectsMapped()) {
|
||||
if (!wb.isShared(klass)) {
|
||||
failed ++;
|
||||
System.out.println("FAILED. " + klass + " mirror object is not archived");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void doTest(String group, Intf object, File jar) throws Throwable {
|
||||
numTests ++;
|
||||
|
||||
@ -101,6 +111,9 @@ public class RedefineClassApp {
|
||||
System.out.println("Test is shared = " + wb.isSharedClass(klass));
|
||||
System.out.println("++++++++++++++++++++++++++");
|
||||
|
||||
// Check archived mirror object before redefine
|
||||
checkArchivedMirrorObject(klass);
|
||||
|
||||
// Call get() before redefine. All strings in archived classes are shared.
|
||||
String res = object.get();
|
||||
System.out.println("get() returns " + res);
|
||||
@ -144,6 +157,9 @@ public class RedefineClassApp {
|
||||
System.gc();
|
||||
System.gc();
|
||||
|
||||
// Check archived mirror object after redefine and GC
|
||||
checkArchivedMirrorObject(klass);
|
||||
|
||||
System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++ (done)\n\n");
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user