/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
*
*/
#include "precompiled.hpp"
#include "classfile/systemDictionary.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "runtime/jniHandles.hpp"
#include "runtime/mutexLocker.hpp"
#ifdef TARGET_OS_FAMILY_linux
# include "thread_linux.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_solaris
# include "thread_solaris.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_windows
# include "thread_windows.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_bsd
# include "thread_bsd.inline.hpp"
#endif
return NULL; // ignore null handles
} else {
}
}
// optimized versions
return NULL; // ignore null handles
} else {
}
}
return NULL; // ignore null handles
} else {
}
}
// ignore null handles
} else {
}
return res;
}
// ignore null handles
} else {
}
return res;
}
}
}
}
}
assert(!CheckJNICalls || is_weak_global_handle(handle), "Invalid delete of weak global JNI handle");
}
}
}
f->do_oop(&_deleted_handle);
_global_handles->oops_do(f);
}
}
// We will never reach the CATCH below since Exceptions::_throw will cause
// the VM to exit if an exception is thrown during initialization
}
// Look back past possible native calls to jni_PushLocalFrame.
return true;
}
}
return false;
}
// Determine if the handle is somewhere in the current thread's stack.
// We easily can't isolate any particular stack frame the handle might
// come from, so we'll check the whole stack.
// If there is no java frame, then this must be top level code, such
// as the java command executable, in which case, this type of handle
// is not permitted.
return (thr->has_last_Java_frame() &&
}
}
}
return _global_handles->memory_usage();
}
return _weak_global_handles->memory_usage();
}
public:
};
private:
int _count;
public:
_count++;
}
};
// We assume this is called at a safepoint: no lock is needed.
"JNIHandles not initialized");
}
public:
}
};
}
void jni_handles_init() {
JNIHandles::initialize();
}
#ifndef PRODUCT
#endif
// Zap block values
_top = 0;
}
}
// Check the thread-local free list for a block so we don't
// have to acquire a mutex.
}
else {
// locking with safepoint checking introduces a potential deadlock:
// - we would hold JNIHandleBlockFreeList_lock and then Threads_lock
// - another would hold Threads_lock (jni_AttachCurrentThread) and then
// JNIHandleBlockFreeList_lock (JNIHandleBlock::allocate_block)
if (_block_free_list == NULL) {
// Allocate new block
block = new JNIHandleBlock();
if (TraceJNIHandleAllocation) {
}
#ifndef PRODUCT
// Link new block to list of all allocated blocks
_block_list = block;
#endif
} else {
// Get block from free list
}
}
// _last, _free_list & _allocate_before_rebuild initialized in allocate_handle
return block;
}
// Put returned block at the beginning of the thread-local free list.
// Note that if thread == NULL, we use it as an implicit argument that
// we _don't_ want the block to be kept on the free_handle_block.
// See for instance JavaThread::exit().
// Add original freelist to end of chain
}
}
// Return blocks to free list
// locking with safepoint checking introduces a potential deadlock:
// - we would hold JNIHandleBlockFreeList_lock and then Threads_lock
// - another would hold Threads_lock (jni_AttachCurrentThread) and then
// JNIHandleBlockFreeList_lock (JNIHandleBlock::allocate_block)
}
}
if (pop_frame_link != NULL) {
// As a sanity check we release blocks pointed to by the pop_frame_link.
// This should never happen (only if PopLocalFrame is not called the
// correct number of times).
}
}
// Iterate over chain of blocks, followed by chains linked through the
// pop frame links.
while (current_chain != NULL) {
"only blocks first in chain should have pop frame link set");
// traverse heap pointers only, not deleted handles or free list
// pointers
}
}
// the next handle block is valid only if current block is full
break;
}
}
}
}
OopClosure* f) {
"blocks holding weak global JNI handles should not have pop frame link set");
// traverse heap pointers only, not deleted handles or free list pointers
// The weakly referenced object is alive, update pointer
} else {
// The weakly referenced object is not alive, clear the reference by storing NULL
if (TraceReferenceGC) {
}
}
}
}
// the next handle block is valid only if current block is full
break;
}
}
/*
* JVMTI data structures may also contain weak oops. The iteration of them
* is placed here so that we don't need to add it to each of the collectors.
*/
}
if (_top == 0) {
// This is the first allocation or the initial block got zapped when
// entering a native function. If we have any following blocks they are
// not valid anymore.
"only first block should have _free_list set");
}
// Clear initial block
_free_list = NULL;
_last = this;
if (ZapJNIHandleArea) zap();
}
// Try last block
}
// Try free list
if (_free_list != NULL) {
}
// Check if unused block follow last
// update last and retry
return allocate_handle(obj);
}
// No space available, we have to rebuild free list or expand
if (_allocate_before_rebuild == 0) {
rebuild_free_list(); // updates _allocate_before_rebuild counter
} else {
// Append new block
// This can block, so we need to preserve obj accross call.
obj = obj_handle();
}
}
int free = 0;
int blocks = 0;
// this handle was cleared out by a delete call, reuse it
_free_list = handle;
free++;
}
}
// we should not rebuild free list if there are unused handles at the end
blocks++;
}
// Heuristic: if more than half of the handles are free we rebuild next time
// as well, otherwise we append a corresponding number of new blocks before
// attempting a free list rebuild again.
if (extra > 0) {
// Not as many free handles as we would like - compute number of new blocks to append
}
if (TraceJNIHandleAllocation) {
tty->print_cr("Rebuild free list JNIHandleBlock " INTPTR_FORMAT " blocks=%d used=%d free=%d add=%d",
}
}
}
return true;
}
}
return false;
}
result++;
}
return result;
}
// This method is not thread-safe, i.e., must be called whule holding a lock on the
// structure.
return length() * sizeof(JNIHandleBlock);
}
#ifndef PRODUCT
return true;
}
}
return false;
}
int used_blocks = 0;
int free_blocks = 0;
int used_handles = 0;
int free_handles = 0;
used_blocks++;
} else {
free_blocks++;
}
}
}
#endif