src/hotspot/share/runtime/jniHandles.cpp
changeset 47216 71c04702a3d5
parent 46703 f152b500376e
child 47649 12623954920e
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     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
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  *
       
    23  */
       
    24 
       
    25 #include "precompiled.hpp"
       
    26 #include "classfile/systemDictionary.hpp"
       
    27 #include "logging/log.hpp"
       
    28 #include "memory/iterator.hpp"
       
    29 #include "oops/oop.inline.hpp"
       
    30 #include "prims/jvmtiExport.hpp"
       
    31 #include "runtime/jniHandles.hpp"
       
    32 #include "runtime/mutexLocker.hpp"
       
    33 #include "runtime/thread.inline.hpp"
       
    34 #include "utilities/align.hpp"
       
    35 #if INCLUDE_ALL_GCS
       
    36 #include "gc/g1/g1SATBCardTableModRefBS.hpp"
       
    37 #endif
       
    38 
       
    39 JNIHandleBlock* JNIHandles::_global_handles       = NULL;
       
    40 JNIHandleBlock* JNIHandles::_weak_global_handles  = NULL;
       
    41 oop             JNIHandles::_deleted_handle       = NULL;
       
    42 
       
    43 
       
    44 jobject JNIHandles::make_local(oop obj) {
       
    45   if (obj == NULL) {
       
    46     return NULL;                // ignore null handles
       
    47   } else {
       
    48     Thread* thread = Thread::current();
       
    49     assert(Universe::heap()->is_in_reserved(obj), "sanity check");
       
    50     return thread->active_handles()->allocate_handle(obj);
       
    51   }
       
    52 }
       
    53 
       
    54 
       
    55 // optimized versions
       
    56 
       
    57 jobject JNIHandles::make_local(Thread* thread, oop obj) {
       
    58   if (obj == NULL) {
       
    59     return NULL;                // ignore null handles
       
    60   } else {
       
    61     assert(Universe::heap()->is_in_reserved(obj), "sanity check");
       
    62     return thread->active_handles()->allocate_handle(obj);
       
    63   }
       
    64 }
       
    65 
       
    66 
       
    67 jobject JNIHandles::make_local(JNIEnv* env, oop obj) {
       
    68   if (obj == NULL) {
       
    69     return NULL;                // ignore null handles
       
    70   } else {
       
    71     JavaThread* thread = JavaThread::thread_from_jni_environment(env);
       
    72     assert(Universe::heap()->is_in_reserved(obj), "sanity check");
       
    73     return thread->active_handles()->allocate_handle(obj);
       
    74   }
       
    75 }
       
    76 
       
    77 
       
    78 jobject JNIHandles::make_global(Handle obj) {
       
    79   assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC");
       
    80   jobject res = NULL;
       
    81   if (!obj.is_null()) {
       
    82     // ignore null handles
       
    83     MutexLocker ml(JNIGlobalHandle_lock);
       
    84     assert(Universe::heap()->is_in_reserved(obj()), "sanity check");
       
    85     res = _global_handles->allocate_handle(obj());
       
    86   } else {
       
    87     CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
       
    88   }
       
    89 
       
    90   return res;
       
    91 }
       
    92 
       
    93 
       
    94 jobject JNIHandles::make_weak_global(Handle obj) {
       
    95   assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC");
       
    96   jobject res = NULL;
       
    97   if (!obj.is_null()) {
       
    98     // ignore null handles
       
    99     {
       
   100       MutexLocker ml(JNIGlobalHandle_lock);
       
   101       assert(Universe::heap()->is_in_reserved(obj()), "sanity check");
       
   102       res = _weak_global_handles->allocate_handle(obj());
       
   103     }
       
   104     // Add weak tag.
       
   105     assert(is_aligned(res, weak_tag_alignment), "invariant");
       
   106     char* tptr = reinterpret_cast<char*>(res) + weak_tag_value;
       
   107     res = reinterpret_cast<jobject>(tptr);
       
   108   } else {
       
   109     CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
       
   110   }
       
   111   return res;
       
   112 }
       
   113 
       
   114 template<bool external_guard>
       
   115 oop JNIHandles::resolve_jweak(jweak handle) {
       
   116   assert(is_jweak(handle), "precondition");
       
   117   oop result = jweak_ref(handle);
       
   118   result = guard_value<external_guard>(result);
       
   119 #if INCLUDE_ALL_GCS
       
   120   if (result != NULL && UseG1GC) {
       
   121     G1SATBCardTableModRefBS::enqueue(result);
       
   122   }
       
   123 #endif // INCLUDE_ALL_GCS
       
   124   return result;
       
   125 }
       
   126 
       
   127 template oop JNIHandles::resolve_jweak<true>(jweak);
       
   128 template oop JNIHandles::resolve_jweak<false>(jweak);
       
   129 
       
   130 void JNIHandles::destroy_global(jobject handle) {
       
   131   if (handle != NULL) {
       
   132     assert(is_global_handle(handle), "Invalid delete of global JNI handle");
       
   133     jobject_ref(handle) = deleted_handle();
       
   134   }
       
   135 }
       
   136 
       
   137 
       
   138 void JNIHandles::destroy_weak_global(jobject handle) {
       
   139   if (handle != NULL) {
       
   140     jweak_ref(handle) = deleted_handle();
       
   141   }
       
   142 }
       
   143 
       
   144 
       
   145 void JNIHandles::oops_do(OopClosure* f) {
       
   146   f->do_oop(&_deleted_handle);
       
   147   _global_handles->oops_do(f);
       
   148 }
       
   149 
       
   150 
       
   151 void JNIHandles::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
       
   152   _weak_global_handles->weak_oops_do(is_alive, f);
       
   153 }
       
   154 
       
   155 
       
   156 void JNIHandles::weak_oops_do(OopClosure* f) {
       
   157   AlwaysTrueClosure always_true;
       
   158   weak_oops_do(&always_true, f);
       
   159 }
       
   160 
       
   161 
       
   162 void JNIHandles::initialize() {
       
   163   _global_handles      = JNIHandleBlock::allocate_block();
       
   164   _weak_global_handles = JNIHandleBlock::allocate_block();
       
   165   EXCEPTION_MARK;
       
   166   // We will never reach the CATCH below since Exceptions::_throw will cause
       
   167   // the VM to exit if an exception is thrown during initialization
       
   168   Klass* k      = SystemDictionary::Object_klass();
       
   169   _deleted_handle = InstanceKlass::cast(k)->allocate_instance(CATCH);
       
   170 }
       
   171 
       
   172 
       
   173 bool JNIHandles::is_local_handle(Thread* thread, jobject handle) {
       
   174   JNIHandleBlock* block = thread->active_handles();
       
   175 
       
   176   // Look back past possible native calls to jni_PushLocalFrame.
       
   177   while (block != NULL) {
       
   178     if (block->chain_contains(handle)) {
       
   179       return true;
       
   180     }
       
   181     block = block->pop_frame_link();
       
   182   }
       
   183   return false;
       
   184 }
       
   185 
       
   186 
       
   187 // Determine if the handle is somewhere in the current thread's stack.
       
   188 // We easily can't isolate any particular stack frame the handle might
       
   189 // come from, so we'll check the whole stack.
       
   190 
       
   191 bool JNIHandles::is_frame_handle(JavaThread* thr, jobject obj) {
       
   192   // If there is no java frame, then this must be top level code, such
       
   193   // as the java command executable, in which case, this type of handle
       
   194   // is not permitted.
       
   195   return (thr->has_last_Java_frame() &&
       
   196          (void*)obj < (void*)thr->stack_base() &&
       
   197          (void*)obj >= (void*)thr->last_Java_sp());
       
   198 }
       
   199 
       
   200 
       
   201 bool JNIHandles::is_global_handle(jobject handle) {
       
   202   return _global_handles->chain_contains(handle);
       
   203 }
       
   204 
       
   205 
       
   206 bool JNIHandles::is_weak_global_handle(jobject handle) {
       
   207   return _weak_global_handles->chain_contains(handle);
       
   208 }
       
   209 
       
   210 long JNIHandles::global_handle_memory_usage() {
       
   211   return _global_handles->memory_usage();
       
   212 }
       
   213 
       
   214 long JNIHandles::weak_global_handle_memory_usage() {
       
   215   return _weak_global_handles->memory_usage();
       
   216 }
       
   217 
       
   218 
       
   219 class CountHandleClosure: public OopClosure {
       
   220 private:
       
   221   int _count;
       
   222 public:
       
   223   CountHandleClosure(): _count(0) {}
       
   224   virtual void do_oop(oop* ooph) {
       
   225     if (*ooph != JNIHandles::deleted_handle()) {
       
   226       _count++;
       
   227     }
       
   228   }
       
   229   virtual void do_oop(narrowOop* unused) { ShouldNotReachHere(); }
       
   230   int count() { return _count; }
       
   231 };
       
   232 
       
   233 // We assume this is called at a safepoint: no lock is needed.
       
   234 void JNIHandles::print_on(outputStream* st) {
       
   235   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
       
   236   assert(_global_handles != NULL && _weak_global_handles != NULL,
       
   237          "JNIHandles not initialized");
       
   238 
       
   239   CountHandleClosure global_handle_count;
       
   240   oops_do(&global_handle_count);
       
   241   weak_oops_do(&global_handle_count);
       
   242 
       
   243   st->print_cr("JNI global references: %d", global_handle_count.count());
       
   244   st->cr();
       
   245   st->flush();
       
   246 }
       
   247 
       
   248 class VerifyHandleClosure: public OopClosure {
       
   249 public:
       
   250   virtual void do_oop(oop* root) {
       
   251     (*root)->verify();
       
   252   }
       
   253   virtual void do_oop(narrowOop* root) { ShouldNotReachHere(); }
       
   254 };
       
   255 
       
   256 void JNIHandles::verify() {
       
   257   VerifyHandleClosure verify_handle;
       
   258 
       
   259   oops_do(&verify_handle);
       
   260   weak_oops_do(&verify_handle);
       
   261 }
       
   262 
       
   263 
       
   264 
       
   265 void jni_handles_init() {
       
   266   JNIHandles::initialize();
       
   267 }
       
   268 
       
   269 
       
   270 int             JNIHandleBlock::_blocks_allocated     = 0;
       
   271 JNIHandleBlock* JNIHandleBlock::_block_free_list      = NULL;
       
   272 #ifndef PRODUCT
       
   273 JNIHandleBlock* JNIHandleBlock::_block_list           = NULL;
       
   274 #endif
       
   275 
       
   276 
       
   277 void JNIHandleBlock::zap() {
       
   278   // Zap block values
       
   279   _top = 0;
       
   280   for (int index = 0; index < block_size_in_oops; index++) {
       
   281     _handles[index] = badJNIHandle;
       
   282   }
       
   283 }
       
   284 
       
   285 JNIHandleBlock* JNIHandleBlock::allocate_block(Thread* thread)  {
       
   286   assert(thread == NULL || thread == Thread::current(), "sanity check");
       
   287   JNIHandleBlock* block;
       
   288   // Check the thread-local free list for a block so we don't
       
   289   // have to acquire a mutex.
       
   290   if (thread != NULL && thread->free_handle_block() != NULL) {
       
   291     block = thread->free_handle_block();
       
   292     thread->set_free_handle_block(block->_next);
       
   293   }
       
   294   else {
       
   295     // locking with safepoint checking introduces a potential deadlock:
       
   296     // - we would hold JNIHandleBlockFreeList_lock and then Threads_lock
       
   297     // - another would hold Threads_lock (jni_AttachCurrentThread) and then
       
   298     //   JNIHandleBlockFreeList_lock (JNIHandleBlock::allocate_block)
       
   299     MutexLockerEx ml(JNIHandleBlockFreeList_lock,
       
   300                      Mutex::_no_safepoint_check_flag);
       
   301     if (_block_free_list == NULL) {
       
   302       // Allocate new block
       
   303       block = new JNIHandleBlock();
       
   304       _blocks_allocated++;
       
   305       if (ZapJNIHandleArea) block->zap();
       
   306       #ifndef PRODUCT
       
   307       // Link new block to list of all allocated blocks
       
   308       block->_block_list_link = _block_list;
       
   309       _block_list = block;
       
   310       #endif
       
   311     } else {
       
   312       // Get block from free list
       
   313       block = _block_free_list;
       
   314       _block_free_list = _block_free_list->_next;
       
   315     }
       
   316   }
       
   317   block->_top = 0;
       
   318   block->_next = NULL;
       
   319   block->_pop_frame_link = NULL;
       
   320   block->_planned_capacity = block_size_in_oops;
       
   321   // _last, _free_list & _allocate_before_rebuild initialized in allocate_handle
       
   322   debug_only(block->_last = NULL);
       
   323   debug_only(block->_free_list = NULL);
       
   324   debug_only(block->_allocate_before_rebuild = -1);
       
   325   return block;
       
   326 }
       
   327 
       
   328 
       
   329 void JNIHandleBlock::release_block(JNIHandleBlock* block, Thread* thread) {
       
   330   assert(thread == NULL || thread == Thread::current(), "sanity check");
       
   331   JNIHandleBlock* pop_frame_link = block->pop_frame_link();
       
   332   // Put returned block at the beginning of the thread-local free list.
       
   333   // Note that if thread == NULL, we use it as an implicit argument that
       
   334   // we _don't_ want the block to be kept on the free_handle_block.
       
   335   // See for instance JavaThread::exit().
       
   336   if (thread != NULL ) {
       
   337     if (ZapJNIHandleArea) block->zap();
       
   338     JNIHandleBlock* freelist = thread->free_handle_block();
       
   339     block->_pop_frame_link = NULL;
       
   340     thread->set_free_handle_block(block);
       
   341 
       
   342     // Add original freelist to end of chain
       
   343     if ( freelist != NULL ) {
       
   344       while ( block->_next != NULL ) block = block->_next;
       
   345       block->_next = freelist;
       
   346     }
       
   347     block = NULL;
       
   348   }
       
   349   if (block != NULL) {
       
   350     // Return blocks to free list
       
   351     // locking with safepoint checking introduces a potential deadlock:
       
   352     // - we would hold JNIHandleBlockFreeList_lock and then Threads_lock
       
   353     // - another would hold Threads_lock (jni_AttachCurrentThread) and then
       
   354     //   JNIHandleBlockFreeList_lock (JNIHandleBlock::allocate_block)
       
   355     MutexLockerEx ml(JNIHandleBlockFreeList_lock,
       
   356                      Mutex::_no_safepoint_check_flag);
       
   357     while (block != NULL) {
       
   358       if (ZapJNIHandleArea) block->zap();
       
   359       JNIHandleBlock* next = block->_next;
       
   360       block->_next = _block_free_list;
       
   361       _block_free_list = block;
       
   362       block = next;
       
   363     }
       
   364   }
       
   365   if (pop_frame_link != NULL) {
       
   366     // As a sanity check we release blocks pointed to by the pop_frame_link.
       
   367     // This should never happen (only if PopLocalFrame is not called the
       
   368     // correct number of times).
       
   369     release_block(pop_frame_link, thread);
       
   370   }
       
   371 }
       
   372 
       
   373 
       
   374 void JNIHandleBlock::oops_do(OopClosure* f) {
       
   375   JNIHandleBlock* current_chain = this;
       
   376   // Iterate over chain of blocks, followed by chains linked through the
       
   377   // pop frame links.
       
   378   while (current_chain != NULL) {
       
   379     for (JNIHandleBlock* current = current_chain; current != NULL;
       
   380          current = current->_next) {
       
   381       assert(current == current_chain || current->pop_frame_link() == NULL,
       
   382         "only blocks first in chain should have pop frame link set");
       
   383       for (int index = 0; index < current->_top; index++) {
       
   384         oop* root = &(current->_handles)[index];
       
   385         oop value = *root;
       
   386         // traverse heap pointers only, not deleted handles or free list
       
   387         // pointers
       
   388         if (value != NULL && Universe::heap()->is_in_reserved(value)) {
       
   389           f->do_oop(root);
       
   390         }
       
   391       }
       
   392       // the next handle block is valid only if current block is full
       
   393       if (current->_top < block_size_in_oops) {
       
   394         break;
       
   395       }
       
   396     }
       
   397     current_chain = current_chain->pop_frame_link();
       
   398   }
       
   399 }
       
   400 
       
   401 
       
   402 void JNIHandleBlock::weak_oops_do(BoolObjectClosure* is_alive,
       
   403                                   OopClosure* f) {
       
   404   for (JNIHandleBlock* current = this; current != NULL; current = current->_next) {
       
   405     assert(current->pop_frame_link() == NULL,
       
   406       "blocks holding weak global JNI handles should not have pop frame link set");
       
   407     for (int index = 0; index < current->_top; index++) {
       
   408       oop* root = &(current->_handles)[index];
       
   409       oop value = *root;
       
   410       // traverse heap pointers only, not deleted handles or free list pointers
       
   411       if (value != NULL && Universe::heap()->is_in_reserved(value)) {
       
   412         if (is_alive->do_object_b(value)) {
       
   413           // The weakly referenced object is alive, update pointer
       
   414           f->do_oop(root);
       
   415         } else {
       
   416           // The weakly referenced object is not alive, clear the reference by storing NULL
       
   417           log_develop_trace(gc, ref)("Clearing JNI weak reference (" INTPTR_FORMAT ")", p2i(root));
       
   418           *root = NULL;
       
   419         }
       
   420       }
       
   421     }
       
   422     // the next handle block is valid only if current block is full
       
   423     if (current->_top < block_size_in_oops) {
       
   424       break;
       
   425     }
       
   426   }
       
   427 
       
   428   /*
       
   429    * JVMTI data structures may also contain weak oops.  The iteration of them
       
   430    * is placed here so that we don't need to add it to each of the collectors.
       
   431    */
       
   432   JvmtiExport::weak_oops_do(is_alive, f);
       
   433 }
       
   434 
       
   435 
       
   436 jobject JNIHandleBlock::allocate_handle(oop obj) {
       
   437   assert(Universe::heap()->is_in_reserved(obj), "sanity check");
       
   438   if (_top == 0) {
       
   439     // This is the first allocation or the initial block got zapped when
       
   440     // entering a native function. If we have any following blocks they are
       
   441     // not valid anymore.
       
   442     for (JNIHandleBlock* current = _next; current != NULL;
       
   443          current = current->_next) {
       
   444       assert(current->_last == NULL, "only first block should have _last set");
       
   445       assert(current->_free_list == NULL,
       
   446              "only first block should have _free_list set");
       
   447       if (current->_top == 0) {
       
   448         // All blocks after the first clear trailing block are already cleared.
       
   449 #ifdef ASSERT
       
   450         for (current = current->_next; current != NULL; current = current->_next) {
       
   451           assert(current->_top == 0, "trailing blocks must already be cleared");
       
   452         }
       
   453 #endif
       
   454         break;
       
   455       }
       
   456       current->_top = 0;
       
   457       if (ZapJNIHandleArea) current->zap();
       
   458     }
       
   459     // Clear initial block
       
   460     _free_list = NULL;
       
   461     _allocate_before_rebuild = 0;
       
   462     _last = this;
       
   463     if (ZapJNIHandleArea) zap();
       
   464   }
       
   465 
       
   466   // Try last block
       
   467   if (_last->_top < block_size_in_oops) {
       
   468     oop* handle = &(_last->_handles)[_last->_top++];
       
   469     *handle = obj;
       
   470     return (jobject) handle;
       
   471   }
       
   472 
       
   473   // Try free list
       
   474   if (_free_list != NULL) {
       
   475     oop* handle = _free_list;
       
   476     _free_list = (oop*) *_free_list;
       
   477     *handle = obj;
       
   478     return (jobject) handle;
       
   479   }
       
   480   // Check if unused block follow last
       
   481   if (_last->_next != NULL) {
       
   482     // update last and retry
       
   483     _last = _last->_next;
       
   484     return allocate_handle(obj);
       
   485   }
       
   486 
       
   487   // No space available, we have to rebuild free list or expand
       
   488   if (_allocate_before_rebuild == 0) {
       
   489       rebuild_free_list();        // updates _allocate_before_rebuild counter
       
   490   } else {
       
   491     // Append new block
       
   492     Thread* thread = Thread::current();
       
   493     Handle obj_handle(thread, obj);
       
   494     // This can block, so we need to preserve obj across call.
       
   495     _last->_next = JNIHandleBlock::allocate_block(thread);
       
   496     _last = _last->_next;
       
   497     _allocate_before_rebuild--;
       
   498     obj = obj_handle();
       
   499   }
       
   500   return allocate_handle(obj);  // retry
       
   501 }
       
   502 
       
   503 void JNIHandleBlock::release_handle(jobject h) {
       
   504   if (h != NULL) {
       
   505     assert(chain_contains(h), "does not contain the JNI handle");
       
   506     // Mark the handle as deleted, allocate will reuse it
       
   507     *((oop*)h) = JNIHandles::deleted_handle();
       
   508   }
       
   509 }
       
   510 
       
   511 
       
   512 void JNIHandleBlock::rebuild_free_list() {
       
   513   assert(_allocate_before_rebuild == 0 && _free_list == NULL, "just checking");
       
   514   int free = 0;
       
   515   int blocks = 0;
       
   516   for (JNIHandleBlock* current = this; current != NULL; current = current->_next) {
       
   517     for (int index = 0; index < current->_top; index++) {
       
   518       oop* handle = &(current->_handles)[index];
       
   519       if (*handle ==  JNIHandles::deleted_handle()) {
       
   520         // this handle was cleared out by a delete call, reuse it
       
   521         *handle = (oop) _free_list;
       
   522         _free_list = handle;
       
   523         free++;
       
   524       }
       
   525     }
       
   526     // we should not rebuild free list if there are unused handles at the end
       
   527     assert(current->_top == block_size_in_oops, "just checking");
       
   528     blocks++;
       
   529   }
       
   530   // Heuristic: if more than half of the handles are free we rebuild next time
       
   531   // as well, otherwise we append a corresponding number of new blocks before
       
   532   // attempting a free list rebuild again.
       
   533   int total = blocks * block_size_in_oops;
       
   534   int extra = total - 2*free;
       
   535   if (extra > 0) {
       
   536     // Not as many free handles as we would like - compute number of new blocks to append
       
   537     _allocate_before_rebuild = (extra + block_size_in_oops - 1) / block_size_in_oops;
       
   538   }
       
   539 }
       
   540 
       
   541 
       
   542 bool JNIHandleBlock::contains(jobject handle) const {
       
   543   return ((jobject)&_handles[0] <= handle && handle<(jobject)&_handles[_top]);
       
   544 }
       
   545 
       
   546 
       
   547 bool JNIHandleBlock::chain_contains(jobject handle) const {
       
   548   for (JNIHandleBlock* current = (JNIHandleBlock*) this; current != NULL; current = current->_next) {
       
   549     if (current->contains(handle)) {
       
   550       return true;
       
   551     }
       
   552   }
       
   553   return false;
       
   554 }
       
   555 
       
   556 
       
   557 int JNIHandleBlock::length() const {
       
   558   int result = 1;
       
   559   for (JNIHandleBlock* current = _next; current != NULL; current = current->_next) {
       
   560     result++;
       
   561   }
       
   562   return result;
       
   563 }
       
   564 
       
   565 const size_t JNIHandleBlock::get_number_of_live_handles() {
       
   566   CountHandleClosure counter;
       
   567   oops_do(&counter);
       
   568   return counter.count();
       
   569 }
       
   570 
       
   571 // This method is not thread-safe, i.e., must be called while holding a lock on the
       
   572 // structure.
       
   573 long JNIHandleBlock::memory_usage() const {
       
   574   return length() * sizeof(JNIHandleBlock);
       
   575 }
       
   576 
       
   577 
       
   578 #ifndef PRODUCT
       
   579 
       
   580 bool JNIHandleBlock::any_contains(jobject handle) {
       
   581   for (JNIHandleBlock* current = _block_list; current != NULL; current = current->_block_list_link) {
       
   582     if (current->contains(handle)) {
       
   583       return true;
       
   584     }
       
   585   }
       
   586   return false;
       
   587 }
       
   588 
       
   589 void JNIHandleBlock::print_statistics() {
       
   590   int used_blocks = 0;
       
   591   int free_blocks = 0;
       
   592   int used_handles = 0;
       
   593   int free_handles = 0;
       
   594   JNIHandleBlock* block = _block_list;
       
   595   while (block != NULL) {
       
   596     if (block->_top > 0) {
       
   597       used_blocks++;
       
   598     } else {
       
   599       free_blocks++;
       
   600     }
       
   601     used_handles += block->_top;
       
   602     free_handles += (block_size_in_oops - block->_top);
       
   603     block = block->_block_list_link;
       
   604   }
       
   605   tty->print_cr("JNIHandleBlocks statistics");
       
   606   tty->print_cr("- blocks allocated: %d", used_blocks + free_blocks);
       
   607   tty->print_cr("- blocks in use:    %d", used_blocks);
       
   608   tty->print_cr("- blocks free:      %d", free_blocks);
       
   609   tty->print_cr("- handles in use:   %d", used_handles);
       
   610   tty->print_cr("- handles free:     %d", free_handles);
       
   611 }
       
   612 
       
   613 #endif