8186088: ConstantPoolCache::_resolved_references is not a JNIHandle
authorcoleenp
Wed, 23 Aug 2017 12:00:39 -0400
changeset 46961 c9094b1e5f87
parent 46959 1863b25339a9
child 46962 9e627420cbf9
8186088: ConstantPoolCache::_resolved_references is not a JNIHandle Summary: Make an OopHandle type to replace jobject to encapsulate these oop pointers in metadata and module entry. Reviewed-by: sspitsyn, dholmes, jiangli, twisti
hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp
hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp
hotspot/src/cpu/arm/vm/interp_masm_arm.cpp
hotspot/src/cpu/arm/vm/macroAssembler_arm.cpp
hotspot/src/cpu/arm/vm/macroAssembler_arm.hpp
hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp
hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp
hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp
hotspot/src/cpu/s390/vm/interp_masm_s390.cpp
hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp
hotspot/src/cpu/s390/vm/macroAssembler_s390.hpp
hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp
hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp
hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp
hotspot/src/cpu/x86/vm/interp_masm_x86.cpp
hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
hotspot/src/share/vm/classfile/classLoaderData.cpp
hotspot/src/share/vm/classfile/classLoaderData.hpp
hotspot/src/share/vm/classfile/javaClasses.cpp
hotspot/src/share/vm/classfile/moduleEntry.cpp
hotspot/src/share/vm/classfile/moduleEntry.hpp
hotspot/src/share/vm/oops/constantPool.cpp
hotspot/src/share/vm/oops/constantPool.hpp
hotspot/src/share/vm/oops/cpCache.hpp
hotspot/src/share/vm/oops/oopHandle.hpp
hotspot/src/share/vm/prims/jvmtiEnvBase.cpp
hotspot/src/share/vm/prims/jvmtiEnvBase.hpp
hotspot/src/share/vm/prims/jvmtiExport.cpp
hotspot/src/share/vm/runtime/vmStructs.cpp
--- a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp	Wed Aug 23 12:00:39 2017 -0400
@@ -272,8 +272,7 @@
   // load pointer for resolved_references[] objArray
   ldr(result, Address(result, ConstantPool::cache_offset_in_bytes()));
   ldr(result, Address(result, ConstantPoolCache::resolved_references_offset_in_bytes()));
-  // JNIHandles::resolve(obj);
-  ldr(result, Address(result, 0));
+  resolve_oop_handle(result);
   // Add in the index
   add(result, result, tmp);
   load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp	Wed Aug 23 12:00:39 2017 -0400
@@ -3279,6 +3279,12 @@
   }
 }
 
+// ((OopHandle)result).resolve();
+void MacroAssembler::resolve_oop_handle(Register result) {
+  // OopHandle::resolve is an indirection.
+  ldr(result, Address(result, 0));
+}
+
 void MacroAssembler::load_mirror(Register dst, Register method) {
   const int mirror_offset = in_bytes(Klass::java_mirror_offset());
   ldr(dst, Address(rmethod, Method::const_offset()));
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp	Wed Aug 23 12:00:39 2017 -0400
@@ -790,6 +790,7 @@
   void store_klass(Register dst, Register src);
   void cmp_klass(Register oop, Register trial_klass, Register tmp);
 
+  void resolve_oop_handle(Register result);
   void load_mirror(Register dst, Register method);
 
   void load_heap_oop(Register dst, Address src);
--- a/hotspot/src/cpu/arm/vm/interp_masm_arm.cpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/cpu/arm/vm/interp_masm_arm.cpp	Wed Aug 23 12:00:39 2017 -0400
@@ -300,8 +300,7 @@
   // load pointer for resolved_references[] objArray
   ldr(cache, Address(result, ConstantPool::cache_offset_in_bytes()));
   ldr(cache, Address(result, ConstantPoolCache::resolved_references_offset_in_bytes()));
-  // JNIHandles::resolve(result)
-  ldr(cache, Address(cache, 0));
+  resolve_oop_handle(cache);
   // Add in the 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
--- a/hotspot/src/cpu/arm/vm/macroAssembler_arm.cpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/cpu/arm/vm/macroAssembler_arm.cpp	Wed Aug 23 12:00:39 2017 -0400
@@ -2887,6 +2887,11 @@
   return offset();
 }
 
+// ((OopHandle)result).resolve();
+void MacroAssembler::resolve_oop_handle(Register result) {
+  // OopHandle::resolve is an indirection.
+  ldr(result, Address(result, 0));
+}
 
 void MacroAssembler::load_mirror(Register mirror, Register method, Register tmp) {
   const int mirror_offset = in_bytes(Klass::java_mirror_offset());
@@ -2896,6 +2901,7 @@
   ldr(mirror, Address(tmp, mirror_offset));
 }
 
+
 ///////////////////////////////////////////////////////////////////////////////
 
 // Compressed pointers
--- a/hotspot/src/cpu/arm/vm/macroAssembler_arm.hpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/cpu/arm/vm/macroAssembler_arm.hpp	Wed Aug 23 12:00:39 2017 -0400
@@ -687,6 +687,7 @@
     AbstractAssembler::emit_address((address)L.data());
   }
 
+  void resolve_oop_handle(Register result);
   void load_mirror(Register mirror, Register method, Register tmp);
 
   // Porting layer between 32-bit ARM and AArch64
--- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp	Wed Aug 23 12:00:39 2017 -0400
@@ -464,8 +464,7 @@
   // Load pointer for resolved_references[] objArray.
   ld(result, ConstantPool::cache_offset_in_bytes(), result);
   ld(result, ConstantPoolCache::resolved_references_offset_in_bytes(), result);
-  // JNIHandles::resolve(result)
-  ld(result, 0, result);
+  resolve_oop_handle(result);
 #ifdef ASSERT
   Label index_ok;
   lwa(R0, arrayOopDesc::length_offset_in_bytes(), result);
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp	Wed Aug 23 12:00:39 2017 -0400
@@ -3372,6 +3372,12 @@
   }
 }
 
+// ((OopHandle)result).resolve();
+void MacroAssembler::resolve_oop_handle(Register result) {
+  // OopHandle::resolve is an indirection.
+  ld(result, 0, result);
+}
+
 void MacroAssembler::load_mirror_from_const_method(Register mirror, Register const_method) {
   ld(mirror, in_bytes(ConstMethod::constants_offset()), const_method);
   ld(mirror, ConstantPool::pool_holder_offset_in_bytes(), mirror);
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp	Wed Aug 23 12:00:39 2017 -0400
@@ -725,6 +725,7 @@
   void store_klass(Register dst_oop, Register klass, Register tmp = R0);
   void store_klass_gap(Register dst_oop, Register val = noreg); // Will store 0 if val not specified.
 
+  void resolve_oop_handle(Register result);
   void load_mirror_from_const_method(Register mirror, Register const_method);
 
   static int instr_size_for_decode_klass_not_null();
--- a/hotspot/src/cpu/s390/vm/interp_masm_s390.cpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/cpu/s390/vm/interp_masm_s390.cpp	Wed Aug 23 12:00:39 2017 -0400
@@ -364,8 +364,7 @@
   // Load pointer for resolved_references[] objArray.
   z_lg(result, ConstantPool::cache_offset_in_bytes(), result);
   z_lg(result, ConstantPoolCache::resolved_references_offset_in_bytes(), result);
-  // JNIHandles::resolve(result)
-  z_lg(result, 0, result); // Load resolved references array itself.
+  resolve_oop_handle(result); // Load resolved references array itself.
 #ifdef ASSERT
   NearLabel index_ok;
   z_lgf(Z_R0, Address(result, arrayOopDesc::length_offset_in_bytes()));
--- a/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp	Wed Aug 23 12:00:39 2017 -0400
@@ -4660,6 +4660,12 @@
   }
 }
 
+// ((OopHandle)result).resolve();
+void MacroAssembler::resolve_oop_handle(Register result) {
+  // OopHandle::resolve is an indirection.
+  z_lg(result, 0, result);
+}
+
 void MacroAssembler::load_mirror(Register mirror, Register method) {
   mem2reg_opt(mirror, Address(method, Method::const_offset()));
   mem2reg_opt(mirror, Address(mirror, ConstMethod::constants_offset()));
--- a/hotspot/src/cpu/s390/vm/macroAssembler_s390.hpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/cpu/s390/vm/macroAssembler_s390.hpp	Wed Aug 23 12:00:39 2017 -0400
@@ -832,6 +832,7 @@
   void oop_decoder(Register Rdst, Register Rsrc, bool maybeNULL,
                    Register Rbase = Z_R1, int pow2_offset = -1);
 
+  void resolve_oop_handle(Register result);
   void load_mirror(Register mirror, Register method);
 
   //--------------------------
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp	Wed Aug 23 12:00:39 2017 -0400
@@ -730,8 +730,7 @@
   // load pointer for resolved_references[] objArray
   ld_ptr(result, ConstantPool::cache_offset_in_bytes(), result);
   ld_ptr(result, ConstantPoolCache::resolved_references_offset_in_bytes(), result);
-  // JNIHandles::resolve(result)
-  ld_ptr(result, 0, result);
+  resolve_oop_handle(result);
   // Add in the index
   add(result, tmp, result);
   load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result);
--- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp	Wed Aug 23 12:00:39 2017 -0400
@@ -3822,6 +3822,12 @@
   card_table_write(bs->byte_map_base, tmp, store_addr);
 }
 
+// ((OopHandle)result).resolve();
+void MacroAssembler::resolve_oop_handle(Register result) {
+  // OopHandle::resolve is an indirection.
+  ld_ptr(result, 0, result);
+}
+
 void MacroAssembler::load_mirror(Register mirror, Register method) {
   const int mirror_offset = in_bytes(Klass::java_mirror_offset());
   ld_ptr(method, in_bytes(Method::const_offset()), mirror);
--- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp	Wed Aug 23 12:00:39 2017 -0400
@@ -995,6 +995,7 @@
   inline void ldbool(const Address& a, Register d);
   inline void movbool( bool boolconst, Register d);
 
+  void resolve_oop_handle(Register result);
   void load_mirror(Register mirror, Register method);
 
   // klass oop manipulations if compressed
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp	Wed Aug 23 12:00:39 2017 -0400
@@ -511,8 +511,7 @@
   // load pointer for resolved_references[] objArray
   movptr(result, Address(result, ConstantPool::cache_offset_in_bytes()));
   movptr(result, Address(result, ConstantPoolCache::resolved_references_offset_in_bytes()));
-  // JNIHandles::resolve(obj);
-  movptr(result, Address(result, 0));
+  resolve_oop_handle(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/macroAssembler_x86.cpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp	Wed Aug 23 12:00:39 2017 -0400
@@ -6604,6 +6604,12 @@
 #endif // _LP64
 }
 
+// ((OopHandle)result).resolve();
+void MacroAssembler::resolve_oop_handle(Register result) {
+  // OopHandle::resolve is an indirection.
+  movptr(result, Address(result, 0));
+}
+
 void MacroAssembler::load_mirror(Register mirror, Register method) {
   // get mirror
   const int mirror_offset = in_bytes(Klass::java_mirror_offset());
@@ -7030,7 +7036,6 @@
 
 #endif // _LP64
 
-
 // C2 compiled method's prolog code.
 void MacroAssembler::verified_entry(int framesize, int stack_bang_size, bool fp_mode_24b) {
 
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp	Wed Aug 23 12:00:39 2017 -0400
@@ -327,6 +327,7 @@
   void movbool(Address dst, Register src);
   void testbool(Register dst);
 
+  void resolve_oop_handle(Register result);
   void load_mirror(Register mirror, Register method);
 
   // oop manipulations
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp	Wed Aug 23 12:00:39 2017 -0400
@@ -759,14 +759,18 @@
   return metaspace;
 }
 
-jobject ClassLoaderData::add_handle(Handle h) {
+OopHandle ClassLoaderData::add_handle(Handle h) {
   MutexLockerEx ml(metaspace_lock(),  Mutex::_no_safepoint_check_flag);
-  return (jobject) _handles.add(h());
+  return OopHandle(_handles.add(h()));
 }
 
-void ClassLoaderData::remove_handle_unsafe(jobject h) {
-  assert(_handles.contains((oop*) h), "Got unexpected handle " PTR_FORMAT, p2i((oop*) h));
-  *((oop*) h) = NULL;
+void ClassLoaderData::init_handle_locked(OopHandle& dest, Handle h) {
+  MutexLockerEx ml(metaspace_lock(),  Mutex::_no_safepoint_check_flag);
+  if (dest.resolve() != NULL) {
+    return;
+  } else {
+    dest = _handles.add(h());
+  }
 }
 
 // Add this metadata pointer to be freed when it's safe.  This is only during
--- a/hotspot/src/share/vm/classfile/classLoaderData.hpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp	Wed Aug 23 12:00:39 2017 -0400
@@ -29,6 +29,7 @@
 #include "memory/memRegion.hpp"
 #include "memory/metaspace.hpp"
 #include "memory/metaspaceCounters.hpp"
+#include "oops/oopHandle.hpp"
 #include "runtime/mutex.hpp"
 #include "trace/traceMacros.hpp"
 #include "utilities/growableArray.hpp"
@@ -362,8 +363,8 @@
   void verify();
   const char* loader_name();
 
-  jobject add_handle(Handle h);
-  void remove_handle_unsafe(jobject h);
+  OopHandle add_handle(Handle h);
+  void init_handle_locked(OopHandle& pd, Handle h);  // used for concurrent access to ModuleEntry::_pd field
   void add_class(Klass* k, bool publicize = true);
   void remove_class(Klass* k);
   bool contains_klass(Klass* k);
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp	Wed Aug 23 12:00:39 2017 -0400
@@ -799,7 +799,7 @@
     // If java.base was already defined then patch this particular class with java.base.
     if (javabase_was_defined) {
       ModuleEntry *javabase_entry = ModuleEntryTable::javabase_moduleEntry();
-      assert(javabase_entry != NULL && javabase_entry->module_handle() != NULL,
+      assert(javabase_entry != NULL && javabase_entry->module() != NULL,
              "Setting class module field, " JAVA_BASE_NAME " should be defined");
       Handle javabase_handle(THREAD, javabase_entry->module());
       set_module(mirror(), javabase_handle());
--- a/hotspot/src/share/vm/classfile/moduleEntry.cpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/share/vm/classfile/moduleEntry.cpp	Wed Aug 23 12:00:39 2017 -0400
@@ -80,19 +80,16 @@
 }
 
 // Returns the shared ProtectionDomain
-Handle ModuleEntry::shared_protection_domain() {
-  return Handle(Thread::current(), JNIHandles::resolve(_pd));
+oop ModuleEntry::shared_protection_domain() {
+  return _pd.resolve();
 }
 
 // Set the shared ProtectionDomain atomically
 void ModuleEntry::set_shared_protection_domain(ClassLoaderData *loader_data,
                                                Handle pd_h) {
   // Create a handle for the shared ProtectionDomain and save it atomically.
-  // If someone beats us setting the _pd cache, the created handle is destroyed.
-  jobject obj = loader_data->add_handle(pd_h);
-  if (Atomic::cmpxchg_ptr(obj, &_pd, NULL) != NULL) {
-    loader_data->remove_handle_unsafe(obj);
-  }
+  // init_handle_locked checks if someone beats us setting the _pd cache.
+  loader_data->init_handle_locked(_pd, pd_h);
 }
 
 // Returns true if this module can read module m
--- a/hotspot/src/share/vm/classfile/moduleEntry.hpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/share/vm/classfile/moduleEntry.hpp	Wed Aug 23 12:00:39 2017 -0400
@@ -27,6 +27,7 @@
 
 #include "classfile/classLoaderData.hpp"
 #include "classfile/vmSymbols.hpp"
+#include "oops/oopHandle.hpp"
 #include "oops/symbol.hpp"
 #include "prims/jni.h"
 #include "runtime/jniHandles.hpp"
@@ -56,8 +57,8 @@
 // data structure.
 class ModuleEntry : public HashtableEntry<Symbol*, mtModule> {
 private:
-  jobject _module;                     // java.lang.Module
-  jobject _pd;                         // java.security.ProtectionDomain, cached
+  OopHandle _module;                   // java.lang.Module
+  OopHandle _pd;                       // java.security.ProtectionDomain, cached
                                        // for shared classes from this module
   ClassLoaderData* _loader_data;
   GrowableArray<ModuleEntry*>* _reads; // list of modules that are readable by this module
@@ -89,16 +90,16 @@
   Symbol*          name() const                        { return literal(); }
   void             set_name(Symbol* n)                 { set_literal(n); }
 
-  oop              module() const                      { return JNIHandles::resolve(_module); }
-  jobject          module_handle() const               { return _module; }
-  void             set_module(jobject j)               { _module = j; }
+  oop              module() const                      { return _module.resolve(); }
+  OopHandle        module_handle() const               { return _module; }
+  void             set_module(OopHandle j)             { _module = j; }
 
   // The shared ProtectionDomain reference is set once the VM loads a shared class
   // originated from the current Module. The referenced ProtectionDomain object is
   // created by the ClassLoader when loading a class (shared or non-shared) from the
   // Module for the first time. This ProtectionDomain object is used for all
   // classes from the Module loaded by the same ClassLoader.
-  Handle           shared_protection_domain();
+  oop              shared_protection_domain();
   void             set_shared_protection_domain(ClassLoaderData *loader_data, Handle pd);
 
   ClassLoaderData* loader_data() const                 { return _loader_data; }
@@ -246,7 +247,7 @@
   static void set_javabase_moduleEntry(ModuleEntry* java_base) { _javabase_module = java_base; }
 
   static bool javabase_defined() { return ((_javabase_module != NULL) &&
-                                           (_javabase_module->module_handle() != NULL)); }
+                                           (_javabase_module->module() != NULL)); }
   static void finalize_javabase(Handle module_handle, Symbol* version, Symbol* location);
   static void patch_javabase_entries(Handle module_handle);
 
--- a/hotspot/src/share/vm/oops/constantPool.cpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/share/vm/oops/constantPool.cpp	Wed Aug 23 12:00:39 2017 -0400
@@ -134,7 +134,7 @@
 }
 
 objArrayOop ConstantPool::resolved_references() const {
-  return (objArrayOop)JNIHandles::resolve(_cache->resolved_references());
+  return (objArrayOop)_cache->resolved_references();
 }
 
 // Create resolved_references array and mapping array for original cp indexes
--- a/hotspot/src/share/vm/oops/constantPool.hpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/share/vm/oops/constantPool.hpp	Wed Aug 23 12:00:39 2017 -0400
@@ -28,6 +28,7 @@
 #include "oops/arrayOop.hpp"
 #include "oops/cpCache.hpp"
 #include "oops/objArrayOop.hpp"
+#include "oops/oopHandle.hpp"
 #include "oops/symbol.hpp"
 #include "oops/typeArrayOop.hpp"
 #include "runtime/handles.hpp"
@@ -821,7 +822,7 @@
 
  private:
 
-  void set_resolved_references(jobject s) { _cache->set_resolved_references(s); }
+  void set_resolved_references(OopHandle s) { _cache->set_resolved_references(s); }
   Array<u2>* reference_map() const        {  return (_cache == NULL) ? NULL :  _cache->reference_map(); }
   void set_reference_map(Array<u2>* o)    { _cache->set_reference_map(o); }
 
--- a/hotspot/src/share/vm/oops/cpCache.hpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/share/vm/oops/cpCache.hpp	Wed Aug 23 12:00:39 2017 -0400
@@ -28,6 +28,7 @@
 #include "interpreter/bytecodes.hpp"
 #include "memory/allocation.hpp"
 #include "oops/array.hpp"
+#include "oops/oopHandle.hpp"
 #include "runtime/orderAccess.hpp"
 #include "utilities/align.hpp"
 
@@ -413,7 +414,7 @@
   // stored in the ConstantPool, which is read-only.
   // Array of resolved objects from the constant pool and map from resolved
   // object index to original constant pool index
-  jobject              _resolved_references;
+  OopHandle            _resolved_references;
   Array<u2>*           _reference_map;
   // The narrowOop pointer to the archived resolved_references. Set at CDS dump
   // time when caching java heap object is supported.
@@ -455,8 +456,8 @@
   oop  archived_references() NOT_CDS_JAVA_HEAP_RETURN_(NULL);
   void set_archived_references(oop o) NOT_CDS_JAVA_HEAP_RETURN;
 
-  jobject resolved_references()           { return _resolved_references; }
-  void set_resolved_references(jobject s) { _resolved_references = s; }
+  oop resolved_references()                 { return _resolved_references.resolve(); }
+  void set_resolved_references(OopHandle s) { _resolved_references = s; }
   Array<u2>* reference_map() const        { return _reference_map; }
   void set_reference_map(Array<u2>* o)    { _reference_map = o; }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/oops/oopHandle.hpp	Wed Aug 23 12:00:39 2017 -0400
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017, 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_OOPS_OOPHANDLE_HPP
+#define SHARE_VM_OOPS_OOPHANDLE_HPP
+
+#include "oops/oop.hpp"
+#include "runtime/atomic.hpp"
+#include "runtime/orderAccess.hpp"
+
+// Simple class for encapsulating oop pointers stored in metadata.
+// These are different from Handle.  The Handle class stores pointers
+// to oops on the stack, and manages the allocation from a thread local
+// area in the constructor.
+// This assumes that the caller will allocate the handle in the appropriate
+// area.  The reason for the encapsulation is to help with naming and to allow
+// future uses for read barriers.
+
+class OopHandle {
+private:
+  oop* _obj;
+
+public:
+  OopHandle() : _obj(NULL) {}
+  OopHandle(oop* w) : _obj(w) {}
+
+  oop resolve() const { return (_obj == NULL) ? (oop)NULL : *_obj; }
+};
+
+#endif // SHARE_VM_OOPS_OOPHANDLE_HPP
--- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp	Wed Aug 23 12:00:39 2017 -0400
@@ -1490,14 +1490,14 @@
   }
 }
 
-GrowableArray<jobject>* JvmtiModuleClosure::_tbl = NULL;
+GrowableArray<OopHandle>* JvmtiModuleClosure::_tbl = NULL;
 
 jvmtiError
 JvmtiModuleClosure::get_all_modules(JvmtiEnv* env, jint* module_count_ptr, jobject** modules_ptr) {
   ResourceMark rm;
   MutexLocker ml(Module_lock);
 
-  _tbl = new GrowableArray<jobject>(77);
+  _tbl = new GrowableArray<OopHandle>(77);
   if (_tbl == NULL) {
     return JVMTI_ERROR_OUT_OF_MEMORY;
   }
@@ -1513,7 +1513,7 @@
     return JVMTI_ERROR_OUT_OF_MEMORY;
   }
   for (jint idx = 0; idx < len; idx++) {
-    array[idx] = _tbl->at(idx);
+    array[idx] = JNIHandles::make_local(Thread::current(), _tbl->at(idx).resolve());
   }
   _tbl = NULL;
   *modules_ptr = array;
--- a/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp	Wed Aug 23 12:00:39 2017 -0400
@@ -30,6 +30,7 @@
 #include "prims/jvmtiEventController.hpp"
 #include "prims/jvmtiThreadState.hpp"
 #include "prims/jvmtiThreadState.inline.hpp"
+#include "oops/oopHandle.hpp"
 #include "runtime/fieldDescriptor.hpp"
 #include "runtime/frame.hpp"
 #include "runtime/handles.inline.hpp"
@@ -704,12 +705,12 @@
 // Jvmti module closure to collect all modules loaded to the system.
 class JvmtiModuleClosure : public StackObj {
 private:
-  static GrowableArray<jobject> *_tbl; // Protected with Module_lock
+  static GrowableArray<OopHandle> *_tbl; // Protected with Module_lock
 
   static void do_module(ModuleEntry* entry) {
     assert_locked_or_safepoint(Module_lock);
-    jobject module = entry->module_handle();
-    guarantee(module != NULL, "module object is NULL");
+    OopHandle module = entry->module_handle();
+    guarantee(module.resolve() != NULL, "module object is NULL");
     _tbl->push(module);
   }
 
--- a/hotspot/src/share/vm/prims/jvmtiExport.cpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp	Wed Aug 23 12:00:39 2017 -0400
@@ -764,7 +764,7 @@
         ModuleEntry* module_entry = InstanceKlass::cast(klass)->module();
         assert(module_entry != NULL, "module_entry should always be set");
         if (module_entry->is_named() &&
-            module_entry->module_handle() != NULL &&
+            module_entry->module() != NULL &&
             !module_entry->has_default_read_edges()) {
           if (!module_entry->set_has_default_read_edges()) {
             // We won a potential race.
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp	Wed Aug 23 15:47:41 2017 +0200
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp	Wed Aug 23 12:00:39 2017 -0400
@@ -83,6 +83,7 @@
 #include "oops/objArrayKlass.hpp"
 #include "oops/objArrayOop.hpp"
 #include "oops/oop.inline.hpp"
+#include "oops/oopHandle.hpp"
 #include "oops/symbol.hpp"
 #include "oops/typeArrayKlass.hpp"
 #include "oops/typeArrayOop.hpp"
@@ -235,7 +236,7 @@
   nonstatic_field(ConstantPool,                _operands,                                     Array<u2>*)                            \
   nonstatic_field(ConstantPool,                _resolved_klasses,                             Array<Klass*>*)                        \
   nonstatic_field(ConstantPool,                _length,                                       int)                                   \
-  nonstatic_field(ConstantPoolCache,           _resolved_references,                          jobject)                               \
+  nonstatic_field(ConstantPoolCache,           _resolved_references,                          OopHandle)                             \
   nonstatic_field(ConstantPoolCache,           _reference_map,                                Array<u2>*)                            \
   nonstatic_field(ConstantPoolCache,           _length,                                       int)                                   \
   nonstatic_field(ConstantPoolCache,           _constant_pool,                                ConstantPool*)                         \
@@ -1438,6 +1439,7 @@
   declare_oop_type(oop)                                                   \
   declare_oop_type(narrowOop)                                             \
   declare_oop_type(typeArrayOop)                                          \
+  declare_oop_type(OopHandle)                                             \
                                                                           \
   /*************************************/                                 \
   /* MethodOop-related data structures */                                 \