Mercurial > hg > truffle
annotate src/share/vm/runtime/jniHandles.cpp @ 1721:413ad0331a0c
6977924: Changes for 6975078 produce build error with certain gcc versions
Summary: The changes introduced for 6975078 assign badHeapOopVal to the _allocation field in the ResourceObj class. In 32 bit linux builds with certain versions of gcc this assignment will be flagged as an error while compiling allocation.cpp. In 32 bit builds the constant value badHeapOopVal (which is cast to an intptr_t) is negative. The _allocation field is typed as an unsigned intptr_t and gcc catches this as an error.
Reviewed-by: jcoomes, ysr, phh
author | johnc |
---|---|
date | Wed, 18 Aug 2010 10:59:06 -0700 |
parents | 38e8278318ca |
children | f95d63e2154a |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1142
diff
changeset
|
2 * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1142
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1142
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1142
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 # include "incls/_precompiled.incl" | |
26 # include "incls/_jniHandles.cpp.incl" | |
27 | |
28 | |
29 JNIHandleBlock* JNIHandles::_global_handles = NULL; | |
30 JNIHandleBlock* JNIHandles::_weak_global_handles = NULL; | |
31 oop JNIHandles::_deleted_handle = NULL; | |
32 | |
33 | |
34 jobject JNIHandles::make_local(oop obj) { | |
35 if (obj == NULL) { | |
36 return NULL; // ignore null handles | |
37 } else { | |
38 Thread* thread = Thread::current(); | |
39 assert(Universe::heap()->is_in_reserved(obj), "sanity check"); | |
40 return thread->active_handles()->allocate_handle(obj); | |
41 } | |
42 } | |
43 | |
44 | |
45 // optimized versions | |
46 | |
47 jobject JNIHandles::make_local(Thread* thread, oop obj) { | |
48 if (obj == NULL) { | |
49 return NULL; // ignore null handles | |
50 } else { | |
51 assert(Universe::heap()->is_in_reserved(obj), "sanity check"); | |
52 return thread->active_handles()->allocate_handle(obj); | |
53 } | |
54 } | |
55 | |
56 | |
57 jobject JNIHandles::make_local(JNIEnv* env, oop obj) { | |
58 if (obj == NULL) { | |
59 return NULL; // ignore null handles | |
60 } else { | |
61 JavaThread* thread = JavaThread::thread_from_jni_environment(env); | |
62 assert(Universe::heap()->is_in_reserved(obj), "sanity check"); | |
63 return thread->active_handles()->allocate_handle(obj); | |
64 } | |
65 } | |
66 | |
67 | |
68 jobject JNIHandles::make_global(Handle obj) { | |
1616
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1552
diff
changeset
|
69 assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC"); |
0 | 70 jobject res = NULL; |
71 if (!obj.is_null()) { | |
72 // ignore null handles | |
73 MutexLocker ml(JNIGlobalHandle_lock); | |
74 assert(Universe::heap()->is_in_reserved(obj()), "sanity check"); | |
75 res = _global_handles->allocate_handle(obj()); | |
76 } else { | |
77 CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops()); | |
78 } | |
79 | |
80 return res; | |
81 } | |
82 | |
83 | |
84 jobject JNIHandles::make_weak_global(Handle obj) { | |
1616
38e8278318ca
6656830: assert((*p)->is_oop(),"expected an oop while scanning weak refs")
never
parents:
1552
diff
changeset
|
85 assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC"); |
0 | 86 jobject res = NULL; |
87 if (!obj.is_null()) { | |
88 // ignore null handles | |
89 MutexLocker ml(JNIGlobalHandle_lock); | |
90 assert(Universe::heap()->is_in_reserved(obj()), "sanity check"); | |
91 res = _weak_global_handles->allocate_handle(obj()); | |
92 } else { | |
93 CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops()); | |
94 } | |
95 return res; | |
96 } | |
97 | |
98 jmethodID JNIHandles::make_jmethod_id(methodHandle mh) { | |
99 return (jmethodID) make_weak_global(mh); | |
100 } | |
101 | |
102 | |
103 | |
104 void JNIHandles::change_method_associated_with_jmethod_id(jmethodID jmid, methodHandle mh) { | |
105 MutexLocker ml(JNIGlobalHandle_lock); // Is this necessary? | |
106 Handle obj = (Handle)mh; | |
107 oop* jobj = (oop*)jmid; | |
108 *jobj = obj(); | |
109 } | |
110 | |
111 | |
112 void JNIHandles::destroy_global(jobject handle) { | |
113 if (handle != NULL) { | |
114 assert(is_global_handle(handle), "Invalid delete of global JNI handle"); | |
115 *((oop*)handle) = deleted_handle(); // Mark the handle as deleted, allocate will reuse it | |
116 } | |
117 } | |
118 | |
119 | |
120 void JNIHandles::destroy_weak_global(jobject handle) { | |
121 if (handle != NULL) { | |
122 assert(!CheckJNICalls || is_weak_global_handle(handle), "Invalid delete of weak global JNI handle"); | |
123 *((oop*)handle) = deleted_handle(); // Mark the handle as deleted, allocate will reuse it | |
124 } | |
125 } | |
126 | |
127 void JNIHandles::destroy_jmethod_id(jmethodID mid) { | |
128 destroy_weak_global((jobject)mid); | |
129 } | |
130 | |
131 | |
132 void JNIHandles::oops_do(OopClosure* f) { | |
133 f->do_oop(&_deleted_handle); | |
134 _global_handles->oops_do(f); | |
135 } | |
136 | |
137 | |
138 void JNIHandles::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) { | |
139 _weak_global_handles->weak_oops_do(is_alive, f); | |
140 } | |
141 | |
142 | |
143 void JNIHandles::initialize() { | |
144 _global_handles = JNIHandleBlock::allocate_block(); | |
145 _weak_global_handles = JNIHandleBlock::allocate_block(); | |
146 EXCEPTION_MARK; | |
147 // We will never reach the CATCH below since Exceptions::_throw will cause | |
148 // the VM to exit if an exception is thrown during initialization | |
1142 | 149 klassOop k = SystemDictionary::Object_klass(); |
0 | 150 _deleted_handle = instanceKlass::cast(k)->allocate_permanent_instance(CATCH); |
151 } | |
152 | |
153 | |
154 bool JNIHandles::is_local_handle(Thread* thread, jobject handle) { | |
155 JNIHandleBlock* block = thread->active_handles(); | |
156 | |
157 // Look back past possible native calls to jni_PushLocalFrame. | |
158 while (block != NULL) { | |
159 if (block->chain_contains(handle)) { | |
160 return true; | |
161 } | |
162 block = block->pop_frame_link(); | |
163 } | |
164 return false; | |
165 } | |
166 | |
167 | |
168 // Determine if the handle is somewhere in the current thread's stack. | |
169 // We easily can't isolate any particular stack frame the handle might | |
170 // come from, so we'll check the whole stack. | |
171 | |
172 bool JNIHandles::is_frame_handle(JavaThread* thr, jobject obj) { | |
173 // If there is no java frame, then this must be top level code, such | |
174 // as the java command executable, in which case, this type of handle | |
175 // is not permitted. | |
176 return (thr->has_last_Java_frame() && | |
177 (void*)obj < (void*)thr->stack_base() && | |
178 (void*)obj >= (void*)thr->last_Java_sp()); | |
179 } | |
180 | |
181 | |
182 bool JNIHandles::is_global_handle(jobject handle) { | |
183 return _global_handles->chain_contains(handle); | |
184 } | |
185 | |
186 | |
187 bool JNIHandles::is_weak_global_handle(jobject handle) { | |
188 return _weak_global_handles->chain_contains(handle); | |
189 } | |
190 | |
191 long JNIHandles::global_handle_memory_usage() { | |
192 return _global_handles->memory_usage(); | |
193 } | |
194 | |
195 long JNIHandles::weak_global_handle_memory_usage() { | |
196 return _weak_global_handles->memory_usage(); | |
197 } | |
198 | |
199 | |
200 class AlwaysAliveClosure: public BoolObjectClosure { | |
201 public: | |
202 bool do_object_b(oop obj) { return true; } | |
203 void do_object(oop obj) { assert(false, "Don't call"); } | |
204 }; | |
205 | |
206 class CountHandleClosure: public OopClosure { | |
207 private: | |
208 int _count; | |
209 public: | |
210 CountHandleClosure(): _count(0) {} | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
211 virtual void do_oop(oop* unused) { |
0 | 212 _count++; |
213 } | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
214 virtual void do_oop(narrowOop* unused) { ShouldNotReachHere(); } |
0 | 215 int count() { return _count; } |
216 }; | |
217 | |
218 // We assume this is called at a safepoint: no lock is needed. | |
219 void JNIHandles::print_on(outputStream* st) { | |
220 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); | |
221 assert(_global_handles != NULL && _weak_global_handles != NULL, | |
222 "JNIHandles not initialized"); | |
223 | |
224 CountHandleClosure global_handle_count; | |
225 AlwaysAliveClosure always_alive; | |
226 oops_do(&global_handle_count); | |
227 weak_oops_do(&always_alive, &global_handle_count); | |
228 | |
229 st->print_cr("JNI global references: %d", global_handle_count.count()); | |
230 st->cr(); | |
231 st->flush(); | |
232 } | |
233 | |
234 class VerifyHandleClosure: public OopClosure { | |
235 public: | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
236 virtual void do_oop(oop* root) { |
0 | 237 (*root)->verify(); |
238 } | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
239 virtual void do_oop(narrowOop* root) { ShouldNotReachHere(); } |
0 | 240 }; |
241 | |
242 void JNIHandles::verify() { | |
243 VerifyHandleClosure verify_handle; | |
244 AlwaysAliveClosure always_alive; | |
245 | |
246 oops_do(&verify_handle); | |
247 weak_oops_do(&always_alive, &verify_handle); | |
248 } | |
249 | |
250 | |
251 | |
252 void jni_handles_init() { | |
253 JNIHandles::initialize(); | |
254 } | |
255 | |
256 | |
257 int JNIHandleBlock::_blocks_allocated = 0; | |
258 JNIHandleBlock* JNIHandleBlock::_block_free_list = NULL; | |
259 #ifndef PRODUCT | |
260 JNIHandleBlock* JNIHandleBlock::_block_list = NULL; | |
261 #endif | |
262 | |
263 | |
264 void JNIHandleBlock::zap() { | |
265 // Zap block values | |
266 _top = 0; | |
267 for (int index = 0; index < block_size_in_oops; index++) { | |
268 _handles[index] = badJNIHandle; | |
269 } | |
270 } | |
271 | |
272 JNIHandleBlock* JNIHandleBlock::allocate_block(Thread* thread) { | |
273 assert(thread == NULL || thread == Thread::current(), "sanity check"); | |
274 JNIHandleBlock* block; | |
275 // Check the thread-local free list for a block so we don't | |
276 // have to acquire a mutex. | |
277 if (thread != NULL && thread->free_handle_block() != NULL) { | |
278 block = thread->free_handle_block(); | |
279 thread->set_free_handle_block(block->_next); | |
280 } | |
281 else { | |
282 // locking with safepoint checking introduces a potential deadlock: | |
283 // - we would hold JNIHandleBlockFreeList_lock and then Threads_lock | |
284 // - another would hold Threads_lock (jni_AttachCurrentThread) and then | |
285 // JNIHandleBlockFreeList_lock (JNIHandleBlock::allocate_block) | |
286 MutexLockerEx ml(JNIHandleBlockFreeList_lock, | |
287 Mutex::_no_safepoint_check_flag); | |
288 if (_block_free_list == NULL) { | |
289 // Allocate new block | |
290 block = new JNIHandleBlock(); | |
291 _blocks_allocated++; | |
292 if (TraceJNIHandleAllocation) { | |
293 tty->print_cr("JNIHandleBlock " INTPTR_FORMAT " allocated (%d total blocks)", | |
294 block, _blocks_allocated); | |
295 } | |
296 if (ZapJNIHandleArea) block->zap(); | |
297 #ifndef PRODUCT | |
298 // Link new block to list of all allocated blocks | |
299 block->_block_list_link = _block_list; | |
300 _block_list = block; | |
301 #endif | |
302 } else { | |
303 // Get block from free list | |
304 block = _block_free_list; | |
305 _block_free_list = _block_free_list->_next; | |
306 } | |
307 } | |
308 block->_top = 0; | |
309 block->_next = NULL; | |
310 block->_pop_frame_link = NULL; | |
311 // _last, _free_list & _allocate_before_rebuild initialized in allocate_handle | |
312 debug_only(block->_last = NULL); | |
313 debug_only(block->_free_list = NULL); | |
314 debug_only(block->_allocate_before_rebuild = -1); | |
315 return block; | |
316 } | |
317 | |
318 | |
319 void JNIHandleBlock::release_block(JNIHandleBlock* block, Thread* thread) { | |
320 assert(thread == NULL || thread == Thread::current(), "sanity check"); | |
321 JNIHandleBlock* pop_frame_link = block->pop_frame_link(); | |
322 // Put returned block at the beginning of the thread-local free list. | |
323 // Note that if thread == NULL, we use it as an implicit argument that | |
324 // we _don't_ want the block to be kept on the free_handle_block. | |
325 // See for instance JavaThread::exit(). | |
326 if (thread != NULL ) { | |
327 if (ZapJNIHandleArea) block->zap(); | |
328 JNIHandleBlock* freelist = thread->free_handle_block(); | |
329 block->_pop_frame_link = NULL; | |
330 thread->set_free_handle_block(block); | |
331 | |
332 // Add original freelist to end of chain | |
333 if ( freelist != NULL ) { | |
334 while ( block->_next != NULL ) block = block->_next; | |
335 block->_next = freelist; | |
336 } | |
337 block = NULL; | |
338 } | |
339 if (block != NULL) { | |
340 // Return blocks to free list | |
341 // locking with safepoint checking introduces a potential deadlock: | |
342 // - we would hold JNIHandleBlockFreeList_lock and then Threads_lock | |
343 // - another would hold Threads_lock (jni_AttachCurrentThread) and then | |
344 // JNIHandleBlockFreeList_lock (JNIHandleBlock::allocate_block) | |
345 MutexLockerEx ml(JNIHandleBlockFreeList_lock, | |
346 Mutex::_no_safepoint_check_flag); | |
347 while (block != NULL) { | |
348 if (ZapJNIHandleArea) block->zap(); | |
349 JNIHandleBlock* next = block->_next; | |
350 block->_next = _block_free_list; | |
351 _block_free_list = block; | |
352 block = next; | |
353 } | |
354 } | |
355 if (pop_frame_link != NULL) { | |
356 // As a sanity check we release blocks pointed to by the pop_frame_link. | |
357 // This should never happen (only if PopLocalFrame is not called the | |
358 // correct number of times). | |
359 release_block(pop_frame_link, thread); | |
360 } | |
361 } | |
362 | |
363 | |
364 void JNIHandleBlock::oops_do(OopClosure* f) { | |
365 JNIHandleBlock* current_chain = this; | |
366 // Iterate over chain of blocks, followed by chains linked through the | |
367 // pop frame links. | |
368 while (current_chain != NULL) { | |
369 for (JNIHandleBlock* current = current_chain; current != NULL; | |
370 current = current->_next) { | |
371 assert(current == current_chain || current->pop_frame_link() == NULL, | |
372 "only blocks first in chain should have pop frame link set"); | |
373 for (int index = 0; index < current->_top; index++) { | |
374 oop* root = &(current->_handles)[index]; | |
375 oop value = *root; | |
376 // traverse heap pointers only, not deleted handles or free list | |
377 // pointers | |
378 if (value != NULL && Universe::heap()->is_in_reserved(value)) { | |
379 f->do_oop(root); | |
380 } | |
381 } | |
382 // the next handle block is valid only if current block is full | |
383 if (current->_top < block_size_in_oops) { | |
384 break; | |
385 } | |
386 } | |
387 current_chain = current_chain->pop_frame_link(); | |
388 } | |
389 } | |
390 | |
391 | |
392 void JNIHandleBlock::weak_oops_do(BoolObjectClosure* is_alive, | |
393 OopClosure* f) { | |
394 for (JNIHandleBlock* current = this; current != NULL; current = current->_next) { | |
395 assert(current->pop_frame_link() == NULL, | |
396 "blocks holding weak global JNI handles should not have pop frame link set"); | |
397 for (int index = 0; index < current->_top; index++) { | |
398 oop* root = &(current->_handles)[index]; | |
399 oop value = *root; | |
400 // traverse heap pointers only, not deleted handles or free list pointers | |
401 if (value != NULL && Universe::heap()->is_in_reserved(value)) { | |
402 if (is_alive->do_object_b(value)) { | |
403 // The weakly referenced object is alive, update pointer | |
404 f->do_oop(root); | |
405 } else { | |
406 // The weakly referenced object is not alive, clear the reference by storing NULL | |
407 if (TraceReferenceGC) { | |
408 tty->print_cr("Clearing JNI weak reference (" INTPTR_FORMAT ")", root); | |
409 } | |
410 *root = NULL; | |
411 } | |
412 } | |
413 } | |
414 // the next handle block is valid only if current block is full | |
415 if (current->_top < block_size_in_oops) { | |
416 break; | |
417 } | |
418 } | |
419 } | |
420 | |
421 | |
422 jobject JNIHandleBlock::allocate_handle(oop obj) { | |
423 assert(Universe::heap()->is_in_reserved(obj), "sanity check"); | |
424 if (_top == 0) { | |
425 // This is the first allocation or the initial block got zapped when | |
426 // entering a native function. If we have any following blocks they are | |
427 // not valid anymore. | |
428 for (JNIHandleBlock* current = _next; current != NULL; | |
429 current = current->_next) { | |
430 assert(current->_last == NULL, "only first block should have _last set"); | |
431 assert(current->_free_list == NULL, | |
432 "only first block should have _free_list set"); | |
433 current->_top = 0; | |
434 if (ZapJNIHandleArea) current->zap(); | |
435 } | |
436 // Clear initial block | |
437 _free_list = NULL; | |
438 _allocate_before_rebuild = 0; | |
439 _last = this; | |
440 if (ZapJNIHandleArea) zap(); | |
441 } | |
442 | |
443 // Try last block | |
444 if (_last->_top < block_size_in_oops) { | |
445 oop* handle = &(_last->_handles)[_last->_top++]; | |
446 *handle = obj; | |
447 return (jobject) handle; | |
448 } | |
449 | |
450 // Try free list | |
451 if (_free_list != NULL) { | |
452 oop* handle = _free_list; | |
453 _free_list = (oop*) *_free_list; | |
454 *handle = obj; | |
455 return (jobject) handle; | |
456 } | |
457 // Check if unused block follow last | |
458 if (_last->_next != NULL) { | |
459 // update last and retry | |
460 _last = _last->_next; | |
461 return allocate_handle(obj); | |
462 } | |
463 | |
464 // No space available, we have to rebuild free list or expand | |
465 if (_allocate_before_rebuild == 0) { | |
466 rebuild_free_list(); // updates _allocate_before_rebuild counter | |
467 } else { | |
468 // Append new block | |
469 Thread* thread = Thread::current(); | |
470 Handle obj_handle(thread, obj); | |
471 // This can block, so we need to preserve obj accross call. | |
472 _last->_next = JNIHandleBlock::allocate_block(thread); | |
473 _last = _last->_next; | |
474 _allocate_before_rebuild--; | |
475 obj = obj_handle(); | |
476 } | |
477 return allocate_handle(obj); // retry | |
478 } | |
479 | |
480 | |
481 void JNIHandleBlock::rebuild_free_list() { | |
482 assert(_allocate_before_rebuild == 0 && _free_list == NULL, "just checking"); | |
483 int free = 0; | |
484 int blocks = 0; | |
485 for (JNIHandleBlock* current = this; current != NULL; current = current->_next) { | |
486 for (int index = 0; index < current->_top; index++) { | |
487 oop* handle = &(current->_handles)[index]; | |
488 if (*handle == JNIHandles::deleted_handle()) { | |
489 // this handle was cleared out by a delete call, reuse it | |
490 *handle = (oop) _free_list; | |
491 _free_list = handle; | |
492 free++; | |
493 } | |
494 } | |
495 // we should not rebuild free list if there are unused handles at the end | |
496 assert(current->_top == block_size_in_oops, "just checking"); | |
497 blocks++; | |
498 } | |
499 // Heuristic: if more than half of the handles are free we rebuild next time | |
500 // as well, otherwise we append a corresponding number of new blocks before | |
501 // attempting a free list rebuild again. | |
502 int total = blocks * block_size_in_oops; | |
503 int extra = total - 2*free; | |
504 if (extra > 0) { | |
505 // Not as many free handles as we would like - compute number of new blocks to append | |
506 _allocate_before_rebuild = (extra + block_size_in_oops - 1) / block_size_in_oops; | |
507 } | |
508 if (TraceJNIHandleAllocation) { | |
509 tty->print_cr("Rebuild free list JNIHandleBlock " INTPTR_FORMAT " blocks=%d used=%d free=%d add=%d", | |
510 this, blocks, total-free, free, _allocate_before_rebuild); | |
511 } | |
512 } | |
513 | |
514 | |
515 bool JNIHandleBlock::contains(jobject handle) const { | |
516 return ((jobject)&_handles[0] <= handle && handle<(jobject)&_handles[_top]); | |
517 } | |
518 | |
519 | |
520 bool JNIHandleBlock::chain_contains(jobject handle) const { | |
521 for (JNIHandleBlock* current = (JNIHandleBlock*) this; current != NULL; current = current->_next) { | |
522 if (current->contains(handle)) { | |
523 return true; | |
524 } | |
525 } | |
526 return false; | |
527 } | |
528 | |
529 | |
530 int JNIHandleBlock::length() const { | |
531 int result = 1; | |
532 for (JNIHandleBlock* current = _next; current != NULL; current = current->_next) { | |
533 result++; | |
534 } | |
535 return result; | |
536 } | |
537 | |
538 // This method is not thread-safe, i.e., must be called whule holding a lock on the | |
539 // structure. | |
540 long JNIHandleBlock::memory_usage() const { | |
541 return length() * sizeof(JNIHandleBlock); | |
542 } | |
543 | |
544 | |
545 #ifndef PRODUCT | |
546 | |
547 bool JNIHandleBlock::any_contains(jobject handle) { | |
548 for (JNIHandleBlock* current = _block_list; current != NULL; current = current->_block_list_link) { | |
549 if (current->contains(handle)) { | |
550 return true; | |
551 } | |
552 } | |
553 return false; | |
554 } | |
555 | |
556 void JNIHandleBlock::print_statistics() { | |
557 int used_blocks = 0; | |
558 int free_blocks = 0; | |
559 int used_handles = 0; | |
560 int free_handles = 0; | |
561 JNIHandleBlock* block = _block_list; | |
562 while (block != NULL) { | |
563 if (block->_top > 0) { | |
564 used_blocks++; | |
565 } else { | |
566 free_blocks++; | |
567 } | |
568 used_handles += block->_top; | |
569 free_handles += (block_size_in_oops - block->_top); | |
570 block = block->_block_list_link; | |
571 } | |
572 tty->print_cr("JNIHandleBlocks statistics"); | |
573 tty->print_cr("- blocks allocated: %d", used_blocks + free_blocks); | |
574 tty->print_cr("- blocks in use: %d", used_blocks); | |
575 tty->print_cr("- blocks free: %d", free_blocks); | |
576 tty->print_cr("- handles in use: %d", used_handles); | |
577 tty->print_cr("- handles free: %d", free_handles); | |
578 } | |
579 | |
580 #endif |