src/hotspot/share/runtime/jniHandles.cpp
changeset 48787 7638bf98a312
parent 48465 f82e79958beb
child 48808 2b0b7f222800
equal deleted inserted replaced
48786:cc231bd80c8b 48787:7638bf98a312
     1 /*
     1 /*
     2  * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    21  * questions.
    21  * questions.
    22  *
    22  *
    23  */
    23  */
    24 
    24 
    25 #include "precompiled.hpp"
    25 #include "precompiled.hpp"
    26 #include "classfile/systemDictionary.hpp"
    26 #include "gc/shared/oopStorage.hpp"
    27 #include "logging/log.hpp"
    27 #include "logging/log.hpp"
    28 #include "memory/iterator.hpp"
    28 #include "memory/iterator.hpp"
    29 #include "oops/oop.inline.hpp"
    29 #include "oops/oop.inline.hpp"
    30 #include "runtime/jniHandles.hpp"
    30 #include "runtime/jniHandles.hpp"
    31 #include "runtime/mutexLocker.hpp"
    31 #include "runtime/mutexLocker.hpp"
    32 #include "runtime/thread.inline.hpp"
    32 #include "runtime/thread.inline.hpp"
    33 #include "trace/traceMacros.hpp"
    33 #include "trace/traceMacros.hpp"
    34 #include "utilities/align.hpp"
    34 #include "utilities/align.hpp"
       
    35 #include "utilities/debug.hpp"
    35 #if INCLUDE_ALL_GCS
    36 #if INCLUDE_ALL_GCS
    36 #include "gc/g1/g1SATBCardTableModRefBS.hpp"
    37 #include "gc/g1/g1SATBCardTableModRefBS.hpp"
    37 #endif
    38 #endif
    38 
    39 
    39 JNIHandleBlock* JNIHandles::_global_handles       = NULL;
    40 OopStorage* JNIHandles::_global_handles = NULL;
    40 JNIHandleBlock* JNIHandles::_weak_global_handles  = NULL;
    41 OopStorage* JNIHandles::_weak_global_handles = NULL;
    41 oop             JNIHandles::_deleted_handle       = NULL;
       
    42 
    42 
    43 
    43 
    44 jobject JNIHandles::make_local(oop obj) {
    44 jobject JNIHandles::make_local(oop obj) {
    45   if (obj == NULL) {
    45   if (obj == NULL) {
    46     return NULL;                // ignore null handles
    46     return NULL;                // ignore null handles
    47   } else {
    47   } else {
    48     Thread* thread = Thread::current();
    48     Thread* thread = Thread::current();
    49     assert(Universe::heap()->is_in_reserved(obj), "sanity check");
    49     assert(oopDesc::is_oop(obj), "not an oop");
    50     assert(!current_thread_in_native(), "must not be in native");
    50     assert(!current_thread_in_native(), "must not be in native");
    51     return thread->active_handles()->allocate_handle(obj);
    51     return thread->active_handles()->allocate_handle(obj);
    52   }
    52   }
    53 }
    53 }
    54 
    54 
    57 
    57 
    58 jobject JNIHandles::make_local(Thread* thread, oop obj) {
    58 jobject JNIHandles::make_local(Thread* thread, oop obj) {
    59   if (obj == NULL) {
    59   if (obj == NULL) {
    60     return NULL;                // ignore null handles
    60     return NULL;                // ignore null handles
    61   } else {
    61   } else {
    62     assert(Universe::heap()->is_in_reserved(obj), "sanity check");
    62     assert(oopDesc::is_oop(obj), "not an oop");
    63     assert(thread->is_Java_thread(), "not a Java thread");
    63     assert(thread->is_Java_thread(), "not a Java thread");
    64     assert(!current_thread_in_native(), "must not be in native");
    64     assert(!current_thread_in_native(), "must not be in native");
    65     return thread->active_handles()->allocate_handle(obj);
    65     return thread->active_handles()->allocate_handle(obj);
    66   }
    66   }
    67 }
    67 }
    70 jobject JNIHandles::make_local(JNIEnv* env, oop obj) {
    70 jobject JNIHandles::make_local(JNIEnv* env, oop obj) {
    71   if (obj == NULL) {
    71   if (obj == NULL) {
    72     return NULL;                // ignore null handles
    72     return NULL;                // ignore null handles
    73   } else {
    73   } else {
    74     JavaThread* thread = JavaThread::thread_from_jni_environment(env);
    74     JavaThread* thread = JavaThread::thread_from_jni_environment(env);
    75     assert(Universe::heap()->is_in_reserved(obj), "sanity check");
    75     assert(oopDesc::is_oop(obj), "not an oop");
    76     assert(!current_thread_in_native(), "must not be in native");
    76     assert(!current_thread_in_native(), "must not be in native");
    77     return thread->active_handles()->allocate_handle(obj);
    77     return thread->active_handles()->allocate_handle(obj);
    78   }
    78   }
    79 }
    79 }
    80 
    80 
    81 
    81 
    82 jobject JNIHandles::make_global(Handle obj) {
    82 static void report_handle_allocation_failure(AllocFailType alloc_failmode,
       
    83                                              const char* handle_kind) {
       
    84   if (alloc_failmode == AllocFailStrategy::EXIT_OOM) {
       
    85     // Fake size value, since we don't know the min allocation size here.
       
    86     vm_exit_out_of_memory(sizeof(oop), OOM_MALLOC_ERROR,
       
    87                           "Cannot create %s JNI handle", handle_kind);
       
    88   } else {
       
    89     assert(alloc_failmode == AllocFailStrategy::RETURN_NULL, "invariant");
       
    90   }
       
    91 }
       
    92 
       
    93 jobject JNIHandles::make_global(Handle obj, AllocFailType alloc_failmode) {
    83   assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC");
    94   assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC");
    84   assert(!current_thread_in_native(), "must not be in native");
    95   assert(!current_thread_in_native(), "must not be in native");
    85   jobject res = NULL;
    96   jobject res = NULL;
    86   if (!obj.is_null()) {
    97   if (!obj.is_null()) {
    87     // ignore null handles
    98     // ignore null handles
    88     MutexLocker ml(JNIGlobalHandle_lock);
    99     assert(oopDesc::is_oop(obj()), "not an oop");
    89     assert(Universe::heap()->is_in_reserved(obj()), "sanity check");
   100     oop* ptr = _global_handles->allocate();
    90     res = _global_handles->allocate_handle(obj());
   101     // Return NULL on allocation failure.
       
   102     if (ptr != NULL) {
       
   103       *ptr = obj();
       
   104       res = reinterpret_cast<jobject>(ptr);
       
   105     } else {
       
   106       report_handle_allocation_failure(alloc_failmode, "global");
       
   107     }
    91   } else {
   108   } else {
    92     CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
   109     CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
    93   }
   110   }
    94 
   111 
    95   return res;
   112   return res;
    96 }
   113 }
    97 
   114 
    98 
   115 
    99 jobject JNIHandles::make_weak_global(Handle obj) {
   116 jobject JNIHandles::make_weak_global(Handle obj, AllocFailType alloc_failmode) {
   100   assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC");
   117   assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC");
   101   assert(!current_thread_in_native(), "must not be in native");
   118   assert(!current_thread_in_native(), "must not be in native");
   102   jobject res = NULL;
   119   jobject res = NULL;
   103   if (!obj.is_null()) {
   120   if (!obj.is_null()) {
   104     // ignore null handles
   121     // ignore null handles
   105     {
   122     assert(oopDesc::is_oop(obj()), "not an oop");
   106       MutexLocker ml(JNIGlobalHandle_lock);
   123     oop* ptr = _weak_global_handles->allocate();
   107       assert(Universe::heap()->is_in_reserved(obj()), "sanity check");
   124     // Return NULL on allocation failure.
   108       res = _weak_global_handles->allocate_handle(obj());
   125     if (ptr != NULL) {
   109     }
   126       *ptr = obj();
   110     // Add weak tag.
   127       char* tptr = reinterpret_cast<char*>(ptr) + weak_tag_value;
   111     assert(is_aligned(res, weak_tag_alignment), "invariant");
   128       res = reinterpret_cast<jobject>(tptr);
   112     char* tptr = reinterpret_cast<char*>(res) + weak_tag_value;
   129     } else {
   113     res = reinterpret_cast<jobject>(tptr);
   130       report_handle_allocation_failure(alloc_failmode, "weak global");
       
   131     }
   114   } else {
   132   } else {
   115     CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
   133     CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
   116   }
   134   }
   117   return res;
   135   return res;
   118 }
   136 }
   119 
   137 
   120 template<bool external_guard>
       
   121 oop JNIHandles::resolve_jweak(jweak handle) {
   138 oop JNIHandles::resolve_jweak(jweak handle) {
   122   assert(is_jweak(handle), "precondition");
   139   assert(is_jweak(handle), "precondition");
   123   oop result = jweak_ref(handle);
   140   oop result = jweak_ref(handle);
   124   result = guard_value<external_guard>(result);
       
   125 #if INCLUDE_ALL_GCS
   141 #if INCLUDE_ALL_GCS
   126   if (result != NULL && UseG1GC) {
   142   if (result != NULL && UseG1GC) {
   127     G1SATBCardTableModRefBS::enqueue(result);
   143     G1SATBCardTableModRefBS::enqueue(result);
   128   }
   144   }
   129 #endif // INCLUDE_ALL_GCS
   145 #endif // INCLUDE_ALL_GCS
   130   return result;
   146   return result;
   131 }
   147 }
   132 
   148 
   133 template oop JNIHandles::resolve_jweak<true>(jweak);
       
   134 template oop JNIHandles::resolve_jweak<false>(jweak);
       
   135 
       
   136 bool JNIHandles::is_global_weak_cleared(jweak handle) {
   149 bool JNIHandles::is_global_weak_cleared(jweak handle) {
   137   assert(is_jweak(handle), "not a weak handle");
   150   assert(is_jweak(handle), "not a weak handle");
   138   return guard_value<false>(jweak_ref(handle)) == NULL;
   151   return jweak_ref(handle) == NULL;
   139 }
   152 }
   140 
   153 
   141 void JNIHandles::destroy_global(jobject handle) {
   154 void JNIHandles::destroy_global(jobject handle) {
   142   if (handle != NULL) {
   155   if (handle != NULL) {
   143     assert(is_global_handle(handle), "Invalid delete of global JNI handle");
   156     assert(!is_jweak(handle), "wrong method for detroying jweak");
   144     jobject_ref(handle) = deleted_handle();
   157     jobject_ref(handle) = NULL;
       
   158     _global_handles->release(&jobject_ref(handle));
   145   }
   159   }
   146 }
   160 }
   147 
   161 
   148 
   162 
   149 void JNIHandles::destroy_weak_global(jobject handle) {
   163 void JNIHandles::destroy_weak_global(jobject handle) {
   150   if (handle != NULL) {
   164   if (handle != NULL) {
   151     jweak_ref(handle) = deleted_handle();
   165     assert(is_jweak(handle), "JNI handle not jweak");
       
   166     jweak_ref(handle) = NULL;
       
   167     _weak_global_handles->release(&jweak_ref(handle));
   152   }
   168   }
   153 }
   169 }
   154 
   170 
   155 
   171 
   156 void JNIHandles::oops_do(OopClosure* f) {
   172 void JNIHandles::oops_do(OopClosure* f) {
   157   f->do_oop(&_deleted_handle);
       
   158   _global_handles->oops_do(f);
   173   _global_handles->oops_do(f);
   159 }
   174 }
   160 
   175 
   161 
   176 
   162 void JNIHandles::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
   177 void JNIHandles::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
   163   _weak_global_handles->weak_oops_do(is_alive, f);
   178   _weak_global_handles->weak_oops_do(is_alive, f);
   164 }
   179 }
   165 
   180 
   166 
   181 
   167 void JNIHandles::weak_oops_do(OopClosure* f) {
   182 void JNIHandles::weak_oops_do(OopClosure* f) {
   168   AlwaysTrueClosure always_true;
   183   _weak_global_handles->weak_oops_do(f);
   169   weak_oops_do(&always_true, f);
       
   170 }
   184 }
   171 
   185 
   172 
   186 
   173 void JNIHandles::initialize() {
   187 void JNIHandles::initialize() {
   174   _global_handles      = JNIHandleBlock::allocate_block();
   188   _global_handles = new OopStorage("JNI Global",
   175   _weak_global_handles = JNIHandleBlock::allocate_block();
   189                                    JNIGlobalAlloc_lock,
   176   EXCEPTION_MARK;
   190                                    JNIGlobalActive_lock);
   177   // We will never reach the CATCH below since Exceptions::_throw will cause
   191   _weak_global_handles = new OopStorage("JNI Weak",
   178   // the VM to exit if an exception is thrown during initialization
   192                                         JNIWeakAlloc_lock,
   179   Klass* k      = SystemDictionary::Object_klass();
   193                                         JNIWeakActive_lock);
   180   _deleted_handle = InstanceKlass::cast(k)->allocate_instance(CATCH);
   194 }
       
   195 
       
   196 
       
   197 inline bool is_storage_handle(const OopStorage* storage, const oop* ptr) {
       
   198   return storage->allocation_status(ptr) == OopStorage::ALLOCATED_ENTRY;
       
   199 }
       
   200 
       
   201 
       
   202 jobjectRefType JNIHandles::handle_type(Thread* thread, jobject handle) {
       
   203   jobjectRefType result = JNIInvalidRefType;
       
   204   if (is_jweak(handle)) {
       
   205     if (is_storage_handle(_weak_global_handles, &jweak_ref(handle))) {
       
   206       result = JNIWeakGlobalRefType;
       
   207     }
       
   208   } else {
       
   209     switch (_global_handles->allocation_status(&jobject_ref(handle))) {
       
   210     case OopStorage::ALLOCATED_ENTRY:
       
   211       result = JNIGlobalRefType;
       
   212       break;
       
   213 
       
   214     case OopStorage::UNALLOCATED_ENTRY:
       
   215       break;                    // Invalid global handle
       
   216 
       
   217     case OopStorage::INVALID_ENTRY:
       
   218       // Not in global storage.  Might be a local handle.
       
   219       if (is_local_handle(thread, handle) ||
       
   220           (thread->is_Java_thread() &&
       
   221            is_frame_handle((JavaThread*)thread, handle))) {
       
   222         result = JNILocalRefType;
       
   223       }
       
   224       break;
       
   225 
       
   226     default:
       
   227       ShouldNotReachHere();
       
   228     }
       
   229   }
       
   230   return result;
   181 }
   231 }
   182 
   232 
   183 
   233 
   184 bool JNIHandles::is_local_handle(Thread* thread, jobject handle) {
   234 bool JNIHandles::is_local_handle(Thread* thread, jobject handle) {
   185   JNIHandleBlock* block = thread->active_handles();
   235   JNIHandleBlock* block = thread->active_handles();
   208          (void*)obj >= (void*)thr->last_Java_sp());
   258          (void*)obj >= (void*)thr->last_Java_sp());
   209 }
   259 }
   210 
   260 
   211 
   261 
   212 bool JNIHandles::is_global_handle(jobject handle) {
   262 bool JNIHandles::is_global_handle(jobject handle) {
   213   return _global_handles->chain_contains(handle);
   263   return !is_jweak(handle) && is_storage_handle(_global_handles, &jobject_ref(handle));
   214 }
   264 }
   215 
   265 
   216 
   266 
   217 bool JNIHandles::is_weak_global_handle(jobject handle) {
   267 bool JNIHandles::is_weak_global_handle(jobject handle) {
   218   return _weak_global_handles->chain_contains(handle);
   268   return is_jweak(handle) && is_storage_handle(_weak_global_handles, &jweak_ref(handle));
   219 }
   269 }
   220 
   270 
   221 long JNIHandles::global_handle_memory_usage() {
   271 size_t JNIHandles::global_handle_memory_usage() {
   222   return _global_handles->memory_usage();
   272   return _global_handles->total_memory_usage();
   223 }
   273 }
   224 
   274 
   225 long JNIHandles::weak_global_handle_memory_usage() {
   275 size_t JNIHandles::weak_global_handle_memory_usage() {
   226   return _weak_global_handles->memory_usage();
   276   return _weak_global_handles->total_memory_usage();
   227 }
   277 }
   228 
   278 
   229 
       
   230 class CountHandleClosure: public OopClosure {
       
   231 private:
       
   232   int _count;
       
   233 public:
       
   234   CountHandleClosure(): _count(0) {}
       
   235   virtual void do_oop(oop* ooph) {
       
   236     if (*ooph != JNIHandles::deleted_handle()) {
       
   237       _count++;
       
   238     }
       
   239   }
       
   240   virtual void do_oop(narrowOop* unused) { ShouldNotReachHere(); }
       
   241   int count() { return _count; }
       
   242 };
       
   243 
   279 
   244 // We assume this is called at a safepoint: no lock is needed.
   280 // We assume this is called at a safepoint: no lock is needed.
   245 void JNIHandles::print_on(outputStream* st) {
   281 void JNIHandles::print_on(outputStream* st) {
   246   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
   282   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
   247   assert(_global_handles != NULL && _weak_global_handles != NULL,
   283   assert(_global_handles != NULL && _weak_global_handles != NULL,
   248          "JNIHandles not initialized");
   284          "JNIHandles not initialized");
   249 
   285 
   250   CountHandleClosure global_handle_count;
   286   st->print_cr("JNI global refs: " SIZE_FORMAT ", weak refs: " SIZE_FORMAT,
   251   oops_do(&global_handle_count);
   287                _global_handles->allocation_count(),
   252   weak_oops_do(&global_handle_count);
   288                _weak_global_handles->allocation_count());
   253 
       
   254   st->print_cr("JNI global references: %d", global_handle_count.count());
       
   255   st->cr();
   289   st->cr();
   256   st->flush();
   290   st->flush();
   257 }
   291 }
   258 
   292 
   259 class VerifyHandleClosure: public OopClosure {
   293 class VerifyJNIHandles: public OopClosure {
   260 public:
   294 public:
   261   virtual void do_oop(oop* root) {
   295   virtual void do_oop(oop* root) {
   262     (*root)->verify();
   296     (*root)->verify();
   263   }
   297   }
   264   virtual void do_oop(narrowOop* root) { ShouldNotReachHere(); }
   298   virtual void do_oop(narrowOop* root) { ShouldNotReachHere(); }
   265 };
   299 };
   266 
   300 
   267 void JNIHandles::verify() {
   301 void JNIHandles::verify() {
   268   VerifyHandleClosure verify_handle;
   302   VerifyJNIHandles verify_handle;
   269 
   303 
   270   oops_do(&verify_handle);
   304   oops_do(&verify_handle);
   271   weak_oops_do(&verify_handle);
   305   weak_oops_do(&verify_handle);
   272 }
   306 }
   273 
   307 
   417     current_chain = current_chain->pop_frame_link();
   451     current_chain = current_chain->pop_frame_link();
   418   }
   452   }
   419 }
   453 }
   420 
   454 
   421 
   455 
   422 void JNIHandleBlock::weak_oops_do(BoolObjectClosure* is_alive,
       
   423                                   OopClosure* f) {
       
   424   for (JNIHandleBlock* current = this; current != NULL; current = current->_next) {
       
   425     assert(current->pop_frame_link() == NULL,
       
   426       "blocks holding weak global JNI handles should not have pop frame link set");
       
   427     for (int index = 0; index < current->_top; index++) {
       
   428       oop* root = &(current->_handles)[index];
       
   429       oop value = *root;
       
   430       // traverse heap pointers only, not deleted handles or free list pointers
       
   431       if (value != NULL && Universe::heap()->is_in_reserved(value)) {
       
   432         if (is_alive->do_object_b(value)) {
       
   433           // The weakly referenced object is alive, update pointer
       
   434           f->do_oop(root);
       
   435         } else {
       
   436           // The weakly referenced object is not alive, clear the reference by storing NULL
       
   437           log_develop_trace(gc, ref)("Clearing JNI weak reference (" INTPTR_FORMAT ")", p2i(root));
       
   438           *root = NULL;
       
   439         }
       
   440       }
       
   441     }
       
   442     // the next handle block is valid only if current block is full
       
   443     if (current->_top < block_size_in_oops) {
       
   444       break;
       
   445     }
       
   446   }
       
   447 }
       
   448 
       
   449 
       
   450 jobject JNIHandleBlock::allocate_handle(oop obj) {
   456 jobject JNIHandleBlock::allocate_handle(oop obj) {
   451   assert(Universe::heap()->is_in_reserved(obj), "sanity check");
   457   assert(Universe::heap()->is_in_reserved(obj), "sanity check");
   452   if (_top == 0) {
   458   if (_top == 0) {
   453     // This is the first allocation or the initial block got zapped when
   459     // This is the first allocation or the initial block got zapped when
   454     // entering a native function. If we have any following blocks they are
   460     // entering a native function. If we have any following blocks they are
   512     obj = obj_handle();
   518     obj = obj_handle();
   513   }
   519   }
   514   return allocate_handle(obj);  // retry
   520   return allocate_handle(obj);  // retry
   515 }
   521 }
   516 
   522 
   517 void JNIHandleBlock::release_handle(jobject h) {
       
   518   if (h != NULL) {
       
   519     assert(chain_contains(h), "does not contain the JNI handle");
       
   520     // Mark the handle as deleted, allocate will reuse it
       
   521     *((oop*)h) = JNIHandles::deleted_handle();
       
   522   }
       
   523 }
       
   524 
       
   525 
       
   526 void JNIHandleBlock::rebuild_free_list() {
   523 void JNIHandleBlock::rebuild_free_list() {
   527   assert(_allocate_before_rebuild == 0 && _free_list == NULL, "just checking");
   524   assert(_allocate_before_rebuild == 0 && _free_list == NULL, "just checking");
   528   int free = 0;
   525   int free = 0;
   529   int blocks = 0;
   526   int blocks = 0;
   530   for (JNIHandleBlock* current = this; current != NULL; current = current->_next) {
   527   for (JNIHandleBlock* current = this; current != NULL; current = current->_next) {
   531     for (int index = 0; index < current->_top; index++) {
   528     for (int index = 0; index < current->_top; index++) {
   532       oop* handle = &(current->_handles)[index];
   529       oop* handle = &(current->_handles)[index];
   533       if (*handle ==  JNIHandles::deleted_handle()) {
   530       if (*handle == NULL) {
   534         // this handle was cleared out by a delete call, reuse it
   531         // this handle was cleared out by a delete call, reuse it
   535         *handle = (oop) _free_list;
   532         *handle = (oop) _free_list;
   536         _free_list = handle;
   533         _free_list = handle;
   537         free++;
   534         free++;
   538       }
   535       }
   566   }
   563   }
   567   return false;
   564   return false;
   568 }
   565 }
   569 
   566 
   570 
   567 
   571 int JNIHandleBlock::length() const {
   568 size_t JNIHandleBlock::length() const {
   572   int result = 1;
   569   size_t result = 1;
   573   for (JNIHandleBlock* current = _next; current != NULL; current = current->_next) {
   570   for (JNIHandleBlock* current = _next; current != NULL; current = current->_next) {
   574     result++;
   571     result++;
   575   }
   572   }
   576   return result;
   573   return result;
   577 }
   574 }
   578 
   575 
       
   576 class CountJNIHandleClosure: public OopClosure {
       
   577 private:
       
   578   int _count;
       
   579 public:
       
   580   CountJNIHandleClosure(): _count(0) {}
       
   581   virtual void do_oop(oop* ooph) { _count++; }
       
   582   virtual void do_oop(narrowOop* unused) { ShouldNotReachHere(); }
       
   583   int count() { return _count; }
       
   584 };
       
   585 
   579 const size_t JNIHandleBlock::get_number_of_live_handles() {
   586 const size_t JNIHandleBlock::get_number_of_live_handles() {
   580   CountHandleClosure counter;
   587   CountJNIHandleClosure counter;
   581   oops_do(&counter);
   588   oops_do(&counter);
   582   return counter.count();
   589   return counter.count();
   583 }
   590 }
   584 
   591 
   585 // This method is not thread-safe, i.e., must be called while holding a lock on the
   592 // This method is not thread-safe, i.e., must be called while holding a lock on the
   586 // structure.
   593 // structure.
   587 long JNIHandleBlock::memory_usage() const {
   594 size_t JNIHandleBlock::memory_usage() const {
   588   return length() * sizeof(JNIHandleBlock);
   595   return length() * sizeof(JNIHandleBlock);
   589 }
   596 }
   590 
   597 
   591 
   598 
   592 #ifndef PRODUCT
   599 #ifndef PRODUCT
       
   600 
       
   601 bool JNIHandles::is_local_handle(jobject handle) {
       
   602   return JNIHandleBlock::any_contains(handle);
       
   603 }
   593 
   604 
   594 bool JNIHandleBlock::any_contains(jobject handle) {
   605 bool JNIHandleBlock::any_contains(jobject handle) {
   595   for (JNIHandleBlock* current = _block_list; current != NULL; current = current->_block_list_link) {
   606   for (JNIHandleBlock* current = _block_list; current != NULL; current = current->_block_list_link) {
   596     if (current->contains(handle)) {
   607     if (current->contains(handle)) {
   597       return true;
   608       return true;