8059340: ConstantPool::_resolved_references is missing in heap dump
Reviewed-by: sspitsyn, stefank, twisti
--- a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp Fri May 15 19:23:11 2015 +0300
+++ b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp Thu May 21 18:22:33 2015 +0300
@@ -229,16 +229,21 @@
Register tmp = index; // reuse
lslw(tmp, tmp, LogBytesPerHeapOop);
- get_constant_pool(result);
// load pointer for resolved_references[] objArray
- ldr(result, Address(result, ConstantPool::resolved_references_offset_in_bytes()));
- // JNIHandles::resolve(obj);
- ldr(result, Address(result, 0));
+ get_resolved_references(result);
// Add in the index
add(result, result, tmp);
load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
}
+void InterpreterMacroAssembler::get_resolved_references(Register reg) {
+ get_constant_pool(reg);
+ ldr(reg, Address(reg, ConstantPool::pool_holder_offset_in_bytes()));
+ ldr(reg, Address(reg, Klass::java_mirror_offset()));
+ assert(java_lang_Class::resolved_references_offset_in_bytes() > 0, "");
+ load_heap_oop(reg, Address(reg, java_lang_Class::resolved_references_offset_in_bytes()));
+}
+
// Generate a subtype check: branch to ok_is_subtype if sub_klass is a
// subtype of super_klass.
//
--- a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp Fri May 15 19:23:11 2015 +0300
+++ b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp Thu May 21 18:22:33 2015 +0300
@@ -121,6 +121,8 @@
ldr(tags, Address(cpool, ConstantPool::tags_offset_in_bytes()));
}
+ void get_resolved_references(Register reg);
+
void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset);
void get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset, size_t index_size = sizeof(u2));
void get_cache_and_index_and_bytecode_at_bcp(Register cache, Register index, Register bytecode, int byte_no, int bcp_offset, size_t index_size = sizeof(u2));
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Fri May 15 19:23:11 2015 +0300
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Thu May 21 18:22:33 2015 +0300
@@ -798,11 +798,8 @@
// word index to byte offset. Since this is a java object, it can be compressed
Register tmp = index; // reuse
sll(index, LogBytesPerHeapOop, tmp);
- get_constant_pool(result);
// load pointer for resolved_references[] objArray
- ld_ptr(result, ConstantPool::resolved_references_offset_in_bytes(), result);
- // JNIHandles::resolve(result)
- ld_ptr(result, 0, result);
+ get_resolved_references(result);
// Add in the index
add(result, tmp, result);
load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result);
@@ -973,6 +970,13 @@
ld_ptr(Rcpool, ConstantPool::tags_offset_in_bytes(), Rtags);
}
+void InterpreterMacroAssembler::get_resolved_references(Register Rdst) {
+ get_constant_pool(Rdst);
+ ld_ptr(Rdst, ConstantPool::pool_holder_offset_in_bytes(), Rdst);
+ ld_ptr(Rdst, Klass::java_mirror_offset(), Rdst);
+ assert(java_lang_Class::resolved_references_offset_in_bytes() > 0, "");
+ load_heap_oop(Rdst, java_lang_Class::resolved_references_offset_in_bytes(), Rdst);
+}
// unlock if synchronized method
//
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp Fri May 15 19:23:11 2015 +0300
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp Thu May 21 18:22:33 2015 +0300
@@ -212,6 +212,7 @@
void get_constant_pool(Register Rdst);
void get_constant_pool_cache(Register Rdst);
void get_cpool_and_tags(Register Rcpool, Register Rtags);
+ void get_resolved_references(Register Rdst);
void is_a(Label& L);
// Load compiled (i2c) or interpreter entry and call from interpreted
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp Fri May 15 19:23:11 2015 +0300
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp Thu May 21 18:22:33 2015 +0300
@@ -482,6 +482,14 @@
andl(bytecode, ConstantPoolCacheEntry::bytecode_1_mask);
}
+void InterpreterMacroAssembler::get_resolved_references(Register reg) {
+ get_constant_pool(reg);
+ movptr(reg, Address(reg, ConstantPool::pool_holder_offset_in_bytes()));
+ movptr(reg, Address(reg, Klass::java_mirror_offset()));
+ assert(java_lang_Class::resolved_references_offset_in_bytes() > 0, "");
+ load_heap_oop(reg, Address(reg, java_lang_Class::resolved_references_offset_in_bytes()));
+}
+
void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache,
Register tmp,
int bcp_offset,
@@ -499,20 +507,16 @@
addptr(cache, tmp); // construct pointer to cache entry
}
-// Load object from cpool->resolved_references(index)
-void InterpreterMacroAssembler::load_resolved_reference_at_index(
- Register result, Register index) {
+// Load object from cpool->pool_holder->mirror->resolved_references(index)
+void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result, Register index) {
assert_different_registers(result, index);
// convert from field index to resolved_references() index and from
// word index to byte offset. Since this is a java object, it can be compressed
Register tmp = index; // reuse
shll(tmp, LogBytesPerHeapOop);
- get_constant_pool(result);
// load pointer for resolved_references[] objArray
- movptr(result, Address(result, ConstantPool::resolved_references_offset_in_bytes()));
- // JNIHandles::resolve(obj);
- movptr(result, Address(result, 0));
+ get_resolved_references(result);
// Add in the index
addptr(result, tmp);
load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp Fri May 15 19:23:11 2015 +0300
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp Thu May 21 18:22:33 2015 +0300
@@ -109,6 +109,8 @@
movptr(tags, Address(cpool, ConstantPool::tags_offset_in_bytes()));
}
+ void get_resolved_references(Register reg);
+
void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset);
void get_cache_and_index_at_bcp(Register cache,
Register index,
--- a/hotspot/src/share/vm/ci/ciStreams.cpp Fri May 15 19:23:11 2015 +0300
+++ b/hotspot/src/share/vm/ci/ciStreams.cpp Thu May 21 18:22:33 2015 +0300
@@ -477,10 +477,8 @@
// ------------------------------------------------------------------
// ciBytecodeStream::get_resolved_references
ciObjArray* ciBytecodeStream::get_resolved_references() {
- VM_ENTRY_MARK;
- // Get the constant pool.
- ConstantPool* cpool = _holder->get_instanceKlass()->constants();
-
+ VM_ENTRY_MARK;
+ objArrayOop resolved_references = _holder->get_instanceKlass()->resolved_references();
// Create a resolved references array and return it.
- return CURRENT_ENV->get_object(cpool->resolved_references())->as_obj_array();
- }
+ return CURRENT_ENV->get_object(resolved_references)->as_obj_array();
+}
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp Fri May 15 19:23:11 2015 +0300
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp Thu May 21 18:22:33 2015 +0300
@@ -60,7 +60,6 @@
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.inline.hpp"
-#include "runtime/jniHandles.hpp"
#include "runtime/mutex.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/synchronizer.hpp"
@@ -81,7 +80,7 @@
// The null-class-loader should always be kept alive.
_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),
+ _claimed(0), _jmethod_ids(NULL), _deallocate_list(NULL),
_next(NULL), _dependencies(dependencies),
_metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true,
Monitor::_safepoint_check_never)) {
@@ -115,7 +114,6 @@
f->do_oop(&_class_loader);
_dependencies.oops_do(f);
- _handles->oops_do(f);
if (klass_closure != NULL) {
classes_do(klass_closure);
}
@@ -356,11 +354,6 @@
_metaspace = NULL;
// release the metaspace
delete m;
- // release the handles
- if (_handles != NULL) {
- JNIHandleBlock::release_block(_handles);
- _handles = NULL;
- }
}
// Clear all the JNI handles for methods
@@ -420,17 +413,6 @@
return _metaspace;
}
-JNIHandleBlock* ClassLoaderData::handles() const { return _handles; }
-void ClassLoaderData::set_handles(JNIHandleBlock* handles) { _handles = handles; }
-
-jobject ClassLoaderData::add_handle(Handle h) {
- MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag);
- if (handles() == NULL) {
- set_handles(JNIHandleBlock::allocate_block());
- }
- return handles()->allocate_handle(h());
-}
-
// Add this metadata pointer to be freed when it's safe. This is only during
// class unloading because Handles might point to this metadata field.
void ClassLoaderData::add_to_deallocate_list(Metadata* m) {
@@ -499,7 +481,6 @@
p2i(class_loader() != NULL ? class_loader()->klass() : NULL), loader_name());
if (claimed()) out->print(" claimed ");
if (is_unloading()) out->print(" unloading ");
- out->print(" handles " INTPTR_FORMAT, p2i(handles()));
out->cr();
if (metaspace_or_null() != NULL) {
out->print_cr("metaspace: " INTPTR_FORMAT, p2i(metaspace_or_null()));
--- a/hotspot/src/share/vm/classfile/classLoaderData.hpp Fri May 15 19:23:11 2015 +0300
+++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp Thu May 21 18:22:33 2015 +0300
@@ -51,7 +51,6 @@
class ClassLoaderData;
class JNIMethodBlock;
-class JNIHandleBlock;
class Metadebug;
// GC root for walking class loader data created
@@ -173,8 +172,6 @@
// Has to be an int because we cas it.
Klass* _klasses; // The classes defined by the class loader.
- JNIHandleBlock* _handles; // Handles to constant pool arrays
-
// These method IDs are created for the class loader and set to NULL when the
// class loader is unloaded. They are rarely freed, only for redefine classes
// and if they lose a data race in InstanceKlass.
@@ -200,9 +197,6 @@
void set_metaspace(Metaspace* m) { _metaspace = m; }
- JNIHandleBlock* handles() const;
- void set_handles(JNIHandleBlock* handles);
-
// GC interface.
void clear_claimed() { _claimed = 0; }
bool claimed() const { return _claimed == 1; }
@@ -290,7 +284,6 @@
void verify();
const char* loader_name();
- jobject add_handle(Handle h);
void add_class(Klass* k);
void remove_class(Klass* k);
bool contains_klass(Klass* k);
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp Fri May 15 19:23:11 2015 +0300
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Thu May 21 18:22:33 2015 +0300
@@ -567,6 +567,12 @@
}
}
create_mirror(k, Handle(NULL), Handle(NULL), CHECK);
+
+ if (UseSharedSpaces && k->oop_is_instance()) {
+ // Create resolved_references array in the fresh mirror.
+ instanceKlassHandle ik(k());
+ ik->constants()->restore_unshareable_info(CHECK);
+ }
}
void java_lang_Class::initialize_mirror_fields(KlassHandle k,
@@ -924,6 +930,17 @@
the_class_mirror->int_field_put(classRedefinedCount_offset, value);
}
+objArrayOop java_lang_Class::resolved_references(oop java_class) {
+ assert(java_lang_Class::is_instance(java_class), "");
+ assert(resolvedReferences_offset > 0, "must be set");
+ return objArrayOop(java_class->obj_field(resolvedReferences_offset));
+}
+
+void java_lang_Class::set_resolved_references(oop java_class, objArrayOop a) {
+ assert(java_lang_Class::is_instance(java_class), "");
+ assert(resolvedReferences_offset > 0, "must be set");
+ java_class->obj_field_put(resolvedReferences_offset, a);
+}
// Note: JDK1.1 and before had a privateInfo_offset field which was used for the
// platform thread structure, and a eetop offset which was used for thread
@@ -3181,6 +3198,7 @@
}
}
+int java_lang_Class::resolvedReferences_offset;
int java_lang_Class::_klass_offset;
int java_lang_Class::_array_klass_offset;
int java_lang_Class::_oop_size_offset;
@@ -3336,6 +3354,9 @@
const int x = heapOopSize;
const int header = instanceOopDesc::base_offset_in_bytes();
+ // Class
+ java_lang_Class::resolvedReferences_offset = java_lang_Class::hc_resolvedReferences_offset * x + header;
+
// Throwable Class
java_lang_Throwable::backtrace_offset = java_lang_Throwable::hc_backtrace_offset * x + header;
java_lang_Throwable::detailMessage_offset = java_lang_Throwable::hc_detailMessage_offset * x + header;
@@ -3534,9 +3555,7 @@
// java.lang.Class
- // Fake fields
- // CHECK_OFFSET("java/lang/Class", java_lang_Class, klass); // %%% this needs to be checked
- // CHECK_OFFSET("java/lang/Class", java_lang_Class, array_klass); // %%% this needs to be checked
+ CHECK_OFFSET("java/lang/Class", java_lang_Class, resolvedReferences, "[Ljava/lang/Object;");
// java.lang.Throwable
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp Fri May 15 19:23:11 2015 +0300
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp Thu May 21 18:22:33 2015 +0300
@@ -226,6 +226,10 @@
class java_lang_Class : AllStatic {
friend class VMStructs;
+ enum {
+ hc_resolvedReferences_offset = 12
+ };
+
private:
// The fake offsets are added by the class loader when java.lang.Class is loaded
@@ -243,6 +247,7 @@
static bool offsets_computed;
static int classRedefinedCount_offset;
+ static int resolvedReferences_offset;
static GrowableArray<Klass*>* _fixup_mirror_list;
@@ -301,6 +306,10 @@
static int static_oop_field_count(oop java_class);
static void set_static_oop_field_count(oop java_class, int size);
+ static objArrayOop resolved_references(oop java_class);
+ static void set_resolved_references(oop java_class, objArrayOop a);
+ static int resolved_references_offset_in_bytes() { return resolvedReferences_offset; }
+
static GrowableArray<Klass*>* fixup_mirror_list() {
return _fixup_mirror_list;
}
--- a/hotspot/src/share/vm/oops/constantPool.cpp Fri May 15 19:23:11 2015 +0300
+++ b/hotspot/src/share/vm/oops/constantPool.cpp Thu May 21 18:22:33 2015 +0300
@@ -67,7 +67,6 @@
set_tags(NULL);
set_cache(NULL);
set_reference_map(NULL);
- set_resolved_references(NULL);
set_operands(NULL);
set_pool_holder(NULL);
set_flags(0);
@@ -104,10 +103,6 @@
unreference_symbols();
}
-objArrayOop ConstantPool::resolved_references() const {
- return (objArrayOop)JNIHandles::resolve(_resolved_references);
-}
-
// Create resolved_references array and mapping array for original cp indexes
// The ldc bytecode was rewritten to have the resolved reference array index so need a way
// to map it back for resolving and some unlikely miscellaneous uses.
@@ -136,30 +131,31 @@
// Create Java array for holding resolved strings, methodHandles,
// methodTypes, invokedynamic and invokehandle appendix objects, etc.
- objArrayOop stom = oopFactory::new_objArray(SystemDictionary::Object_klass(), map_length, CHECK);
- Handle refs_handle (THREAD, (oop)stom); // must handleize.
- set_resolved_references(loader_data->add_handle(refs_handle));
+ objArrayOop obj_arr = oopFactory::new_objArray(SystemDictionary::Object_klass(), map_length, CHECK);
+ pool_holder()->set_resolved_references(obj_arr);
}
}
+objArrayOop ConstantPool::resolved_references() const {
+ return pool_holder()->resolved_references();
+}
+
// CDS support. Create a new resolved_references array.
void ConstantPool::restore_unshareable_info(TRAPS) {
+ // restore the C++ vtable from the shared archive
+ restore_vtable();
+
+ if (pool_holder()->java_mirror() == NULL) return;
// Only create the new resolved references array if it hasn't been attempted before
- if (resolved_references() != NULL) return;
-
- // restore the C++ vtable from the shared archive
- restore_vtable();
+ if (pool_holder()->resolved_references() != NULL) return;
if (SystemDictionary::Object_klass_loaded()) {
// Recreate the object array and add to ClassLoaderData.
int map_length = resolved_reference_length();
if (map_length > 0) {
- objArrayOop stom = oopFactory::new_objArray(SystemDictionary::Object_klass(), map_length, CHECK);
- Handle refs_handle (THREAD, (oop)stom); // must handleize.
-
- ClassLoaderData* loader_data = pool_holder()->class_loader_data();
- set_resolved_references(loader_data->add_handle(refs_handle));
+ objArrayOop resolved_references = oopFactory::new_objArray(SystemDictionary::Object_klass(), map_length, CHECK);
+ pool_holder()->set_resolved_references(resolved_references);
}
}
}
@@ -168,9 +164,8 @@
// Resolved references are not in the shared archive.
// Save the length for restoration. It is not necessarily the same length
// as reference_map.length() if invokedynamic is saved.
- set_resolved_reference_length(
- resolved_references() != NULL ? resolved_references()->length() : 0);
- set_resolved_references(NULL);
+ objArrayOop resolved_references = pool_holder()->resolved_references();
+ set_resolved_reference_length(resolved_references != NULL ? resolved_references->length() : 0);
}
int ConstantPool::cp_to_object_index(int cp_index) {
@@ -1871,7 +1866,6 @@
st->print_cr(" - holder: " INTPTR_FORMAT, pool_holder());
}
st->print_cr(" - cache: " INTPTR_FORMAT, cache());
- st->print_cr(" - resolved_references: " INTPTR_FORMAT, (void *)resolved_references());
st->print_cr(" - reference_map: " INTPTR_FORMAT, reference_map());
for (int index = 1; index < length(); index++) { // Index 0 is unused
--- a/hotspot/src/share/vm/oops/constantPool.hpp Fri May 15 19:23:11 2015 +0300
+++ b/hotspot/src/share/vm/oops/constantPool.hpp Thu May 21 18:22:33 2015 +0300
@@ -84,7 +84,6 @@
// Array of resolved objects from the constant pool and map from resolved
// object index to original constant pool index
- jobject _resolved_references;
Array<u2>* _reference_map;
enum {
@@ -191,6 +190,7 @@
// resolved strings, methodHandles and callsite objects from the constant pool
objArrayOop resolved_references() const;
+
// mapping resolved object array indexes to cp indexes and back.
int object_to_cp_index(int index) { return _reference_map->at(index); }
int cp_to_object_index(int index);
@@ -222,7 +222,6 @@
static int tags_offset_in_bytes() { return offset_of(ConstantPool, _tags); }
static int cache_offset_in_bytes() { return offset_of(ConstantPool, _cache); }
static int pool_holder_offset_in_bytes() { return offset_of(ConstantPool, _pool_holder); }
- static int resolved_references_offset_in_bytes() { return offset_of(ConstantPool, _resolved_references); }
// Storing constants
@@ -771,7 +770,6 @@
private:
- void set_resolved_references(jobject s) { _resolved_references = s; }
Array<u2>* reference_map() const { return _reference_map; }
void set_reference_map(Array<u2>* o) { _reference_map = o; }
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Fri May 15 19:23:11 2015 +0300
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Thu May 21 18:22:33 2015 +0300
@@ -2032,7 +2032,6 @@
}
void InstanceKlass::remove_unshareable_info() {
- Klass::remove_unshareable_info();
// Unlink the class
if (is_linked()) {
unlink_class();
@@ -2048,6 +2047,8 @@
// do array classes also.
array_klasses_do(remove_unshareable_in_class);
+
+ Klass::remove_unshareable_info();
}
static void restore_unshareable_in_class(Klass* k, TRAPS) {
@@ -3512,3 +3513,11 @@
unsigned char * InstanceKlass::get_cached_class_file_bytes() {
return VM_RedefineClasses::get_cached_class_file_bytes(_cached_class_file);
}
+
+objArrayOop InstanceKlass::resolved_references() const {
+ return java_lang_Class::resolved_references(java_mirror());
+}
+
+void InstanceKlass::set_resolved_references(objArrayOop obj_arr) {
+ return java_lang_Class::set_resolved_references(java_mirror(), obj_arr);
+}
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Fri May 15 19:23:11 2015 +0300
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Thu May 21 18:22:33 2015 +0300
@@ -532,6 +532,9 @@
ConstantPool* constants() const { return _constants; }
void set_constants(ConstantPool* c) { _constants = c; }
+ objArrayOop resolved_references() const;
+ void set_resolved_references(objArrayOop obj_arr);
+
// protection domain
oop protection_domain() const;
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Fri May 15 19:23:11 2015 +0300
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Thu May 21 18:22:33 2015 +0300
@@ -3885,7 +3885,10 @@
// Attach new constant pool to the original klass. The original
// klass still refers to the old constant pool (for now).
+ // resolved_references array should be moved as well, since it is located
+ // in klass mirror.
scratch_class->constants()->set_pool_holder(the_class());
+ the_class->set_resolved_references(scratch_class->resolved_references());
#if 0
// In theory, with constant pool merging in place we should be able
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Fri May 15 19:23:11 2015 +0300
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Thu May 21 18:22:33 2015 +0300
@@ -288,7 +288,6 @@
nonstatic_field(ConstantPool, _pool_holder, InstanceKlass*) \
nonstatic_field(ConstantPool, _operands, Array<u2>*) \
nonstatic_field(ConstantPool, _length, int) \
- nonstatic_field(ConstantPool, _resolved_references, jobject) \
nonstatic_field(ConstantPool, _reference_map, Array<u2>*) \
nonstatic_field(ConstantPoolCache, _length, int) \
nonstatic_field(ConstantPoolCache, _constant_pool, ConstantPool*) \