aoqi@0: /* poonam@7627: * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: #ifndef SHARE_VM_RUNTIME_JNIHANDLES_HPP aoqi@0: #define SHARE_VM_RUNTIME_JNIHANDLES_HPP aoqi@0: aoqi@0: #include "runtime/handles.hpp" aoqi@0: #include "utilities/top.hpp" aoqi@0: aoqi@0: class JNIHandleBlock; aoqi@0: aoqi@0: aoqi@0: // Interface for creating and resolving local/global JNI handles aoqi@0: aoqi@0: class JNIHandles : AllStatic { aoqi@0: friend class VMStructs; aoqi@0: private: aoqi@0: static JNIHandleBlock* _global_handles; // First global handle block aoqi@0: static JNIHandleBlock* _weak_global_handles; // First weak global handle block aoqi@0: static oop _deleted_handle; // Sentinel marking deleted handles aoqi@0: aoqi@0: public: aoqi@0: // Resolve handle into oop aoqi@0: inline static oop resolve(jobject handle); aoqi@0: // Resolve externally provided handle into oop with some guards aoqi@0: inline static oop resolve_external_guard(jobject handle); aoqi@0: // Resolve handle into oop, result guaranteed not to be null aoqi@0: inline static oop resolve_non_null(jobject handle); aoqi@0: aoqi@0: // Local handles aoqi@0: static jobject make_local(oop obj); aoqi@0: static jobject make_local(JNIEnv* env, oop obj); // Fast version when env is known aoqi@0: static jobject make_local(Thread* thread, oop obj); // Even faster version when current thread is known aoqi@0: inline static void destroy_local(jobject handle); aoqi@0: aoqi@0: // Global handles aoqi@0: static jobject make_global(Handle obj); aoqi@0: static void destroy_global(jobject handle); aoqi@0: aoqi@0: // Weak global handles aoqi@0: static jobject make_weak_global(Handle obj); aoqi@0: static void destroy_weak_global(jobject handle); aoqi@0: aoqi@0: // Sentinel marking deleted handles in block. Note that we cannot store NULL as aoqi@0: // the sentinel, since clearing weak global JNI refs are done by storing NULL in aoqi@0: // the handle. The handle may not be reused before destroy_weak_global is called. aoqi@0: static oop deleted_handle() { return _deleted_handle; } aoqi@0: aoqi@0: // Initialization aoqi@0: static void initialize(); aoqi@0: aoqi@0: // Debugging aoqi@0: static void print_on(outputStream* st); aoqi@0: static void print() { print_on(tty); } aoqi@0: static void verify(); aoqi@0: static bool is_local_handle(Thread* thread, jobject handle); aoqi@0: static bool is_frame_handle(JavaThread* thr, jobject obj); aoqi@0: static bool is_global_handle(jobject handle); aoqi@0: static bool is_weak_global_handle(jobject handle); aoqi@0: static long global_handle_memory_usage(); aoqi@0: static long weak_global_handle_memory_usage(); aoqi@0: aoqi@0: // Garbage collection support(global handles only, local handles are traversed from thread) aoqi@0: // Traversal of regular global handles aoqi@0: static void oops_do(OopClosure* f); aoqi@0: // Traversal of weak global handles. Unreachable oops are cleared. aoqi@0: static void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f); aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: aoqi@0: // JNI handle blocks holding local/global JNI handles aoqi@0: aoqi@0: class JNIHandleBlock : public CHeapObj { aoqi@0: friend class VMStructs; aoqi@0: friend class CppInterpreter; aoqi@0: aoqi@0: private: aoqi@0: enum SomeConstants { aoqi@0: block_size_in_oops = 32 // Number of handles per handle block aoqi@0: }; aoqi@0: aoqi@0: oop _handles[block_size_in_oops]; // The handles aoqi@0: int _top; // Index of next unused handle aoqi@0: JNIHandleBlock* _next; // Link to next block aoqi@0: aoqi@0: // The following instance variables are only used by the first block in a chain. aoqi@0: // Having two types of blocks complicates the code and the space overhead in negligble. aoqi@0: JNIHandleBlock* _last; // Last block in use aoqi@0: JNIHandleBlock* _pop_frame_link; // Block to restore on PopLocalFrame call aoqi@0: oop* _free_list; // Handle free list aoqi@0: int _allocate_before_rebuild; // Number of blocks to allocate before rebuilding free list aoqi@0: poonam@7627: // Check JNI, "planned capacity" for current frame (or push/ensure) poonam@7627: size_t _planned_capacity; poonam@7627: aoqi@0: #ifndef PRODUCT aoqi@0: JNIHandleBlock* _block_list_link; // Link for list below aoqi@0: static JNIHandleBlock* _block_list; // List of all allocated blocks (for debugging only) aoqi@0: #endif aoqi@0: aoqi@0: static JNIHandleBlock* _block_free_list; // Free list of currently unused blocks aoqi@0: static int _blocks_allocated; // For debugging/printing aoqi@0: aoqi@0: // Fill block with bad_handle values aoqi@0: void zap(); aoqi@0: aoqi@0: protected: aoqi@0: // No more handles in the both the current and following blocks aoqi@0: void clear() { _top = 0; } aoqi@0: aoqi@0: private: aoqi@0: // Free list computation aoqi@0: void rebuild_free_list(); aoqi@0: aoqi@0: public: aoqi@0: // Handle allocation aoqi@0: jobject allocate_handle(oop obj); aoqi@0: aoqi@0: // Block allocation and block free list management aoqi@0: static JNIHandleBlock* allocate_block(Thread* thread = NULL); aoqi@0: static void release_block(JNIHandleBlock* block, Thread* thread = NULL); aoqi@0: aoqi@0: // JNI PushLocalFrame/PopLocalFrame support aoqi@0: JNIHandleBlock* pop_frame_link() const { return _pop_frame_link; } aoqi@0: void set_pop_frame_link(JNIHandleBlock* block) { _pop_frame_link = block; } aoqi@0: aoqi@0: // Stub generator support aoqi@0: static int top_offset_in_bytes() { return offset_of(JNIHandleBlock, _top); } aoqi@0: aoqi@0: // Garbage collection support aoqi@0: // Traversal of regular handles aoqi@0: void oops_do(OopClosure* f); aoqi@0: // Traversal of weak handles. Unreachable oops are cleared. aoqi@0: void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f); aoqi@0: poonam@7627: // Checked JNI support poonam@7627: void set_planned_capacity(size_t planned_capacity) { _planned_capacity = planned_capacity; } poonam@7627: const size_t get_planned_capacity() { return _planned_capacity; } poonam@7627: const size_t get_number_of_live_handles(); poonam@7627: aoqi@0: // Debugging aoqi@0: bool chain_contains(jobject handle) const; // Does this block or following blocks contain handle aoqi@0: bool contains(jobject handle) const; // Does this block contain handle aoqi@0: int length() const; // Length of chain starting with this block aoqi@0: long memory_usage() const; aoqi@0: #ifndef PRODUCT aoqi@0: static bool any_contains(jobject handle); // Does any block currently in use contain handle aoqi@0: static void print_statistics(); aoqi@0: #endif aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: inline oop JNIHandles::resolve(jobject handle) { aoqi@0: oop result = (handle == NULL ? (oop)NULL : *(oop*)handle); aoqi@0: assert(result != NULL || (handle == NULL || !CheckJNICalls || is_weak_global_handle(handle)), "Invalid value read from jni handle"); aoqi@0: assert(result != badJNIHandle, "Pointing to zapped jni handle area"); aoqi@0: return result; aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: inline oop JNIHandles::resolve_external_guard(jobject handle) { aoqi@0: if (handle == NULL) return NULL; aoqi@0: oop result = *(oop*)handle; aoqi@0: if (result == NULL || result == badJNIHandle) return NULL; aoqi@0: return result; aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: inline oop JNIHandles::resolve_non_null(jobject handle) { aoqi@0: assert(handle != NULL, "JNI handle should not be null"); aoqi@0: oop result = *(oop*)handle; aoqi@0: assert(result != NULL, "Invalid value read from jni handle"); aoqi@0: assert(result != badJNIHandle, "Pointing to zapped jni handle area"); aoqi@0: // Don't let that private _deleted_handle object escape into the wild. aoqi@0: assert(result != deleted_handle(), "Used a deleted global handle."); aoqi@0: return result; aoqi@0: }; aoqi@0: aoqi@0: inline void JNIHandles::destroy_local(jobject handle) { aoqi@0: if (handle != NULL) { aoqi@0: *((oop*)handle) = deleted_handle(); // Mark the handle as deleted, allocate will reuse it aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: #endif // SHARE_VM_RUNTIME_JNIHANDLES_HPP