|
1 /* |
|
2 * Copyright (c) 1998, 2012, 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 #ifndef SHARE_VM_RUNTIME_JNIHANDLES_HPP |
|
26 #define SHARE_VM_RUNTIME_JNIHANDLES_HPP |
|
27 |
|
28 #include "runtime/handles.hpp" |
|
29 #include "utilities/top.hpp" |
|
30 |
|
31 class JNIHandleBlock; |
|
32 |
|
33 |
|
34 // Interface for creating and resolving local/global JNI handles |
|
35 |
|
36 class JNIHandles : AllStatic { |
|
37 friend class VMStructs; |
|
38 private: |
|
39 static JNIHandleBlock* _global_handles; // First global handle block |
|
40 static JNIHandleBlock* _weak_global_handles; // First weak global handle block |
|
41 static oop _deleted_handle; // Sentinel marking deleted handles |
|
42 |
|
43 public: |
|
44 // Resolve handle into oop |
|
45 inline static oop resolve(jobject handle); |
|
46 // Resolve externally provided handle into oop with some guards |
|
47 inline static oop resolve_external_guard(jobject handle); |
|
48 // Resolve handle into oop, result guaranteed not to be null |
|
49 inline static oop resolve_non_null(jobject handle); |
|
50 |
|
51 // Local handles |
|
52 static jobject make_local(oop obj); |
|
53 static jobject make_local(JNIEnv* env, oop obj); // Fast version when env is known |
|
54 static jobject make_local(Thread* thread, oop obj); // Even faster version when current thread is known |
|
55 inline static void destroy_local(jobject handle); |
|
56 |
|
57 // Global handles |
|
58 static jobject make_global(Handle obj); |
|
59 static void destroy_global(jobject handle); |
|
60 |
|
61 // Weak global handles |
|
62 static jobject make_weak_global(Handle obj); |
|
63 static void destroy_weak_global(jobject handle); |
|
64 |
|
65 // Sentinel marking deleted handles in block. Note that we cannot store NULL as |
|
66 // the sentinel, since clearing weak global JNI refs are done by storing NULL in |
|
67 // the handle. The handle may not be reused before destroy_weak_global is called. |
|
68 static oop deleted_handle() { return _deleted_handle; } |
|
69 |
|
70 // Initialization |
|
71 static void initialize(); |
|
72 |
|
73 // Debugging |
|
74 static void print_on(outputStream* st); |
|
75 static void print() { print_on(tty); } |
|
76 static void verify(); |
|
77 static bool is_local_handle(Thread* thread, jobject handle); |
|
78 static bool is_frame_handle(JavaThread* thr, jobject obj); |
|
79 static bool is_global_handle(jobject handle); |
|
80 static bool is_weak_global_handle(jobject handle); |
|
81 static long global_handle_memory_usage(); |
|
82 static long weak_global_handle_memory_usage(); |
|
83 |
|
84 // Garbage collection support(global handles only, local handles are traversed from thread) |
|
85 // Traversal of regular global handles |
|
86 static void oops_do(OopClosure* f); |
|
87 // Traversal of weak global handles. Unreachable oops are cleared. |
|
88 static void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f); |
|
89 }; |
|
90 |
|
91 |
|
92 |
|
93 // JNI handle blocks holding local/global JNI handles |
|
94 |
|
95 class JNIHandleBlock : public CHeapObj<mtInternal> { |
|
96 friend class VMStructs; |
|
97 friend class CppInterpreter; |
|
98 |
|
99 private: |
|
100 enum SomeConstants { |
|
101 block_size_in_oops = 32 // Number of handles per handle block |
|
102 }; |
|
103 |
|
104 oop _handles[block_size_in_oops]; // The handles |
|
105 int _top; // Index of next unused handle |
|
106 JNIHandleBlock* _next; // Link to next block |
|
107 |
|
108 // The following instance variables are only used by the first block in a chain. |
|
109 // Having two types of blocks complicates the code and the space overhead in negligble. |
|
110 JNIHandleBlock* _last; // Last block in use |
|
111 JNIHandleBlock* _pop_frame_link; // Block to restore on PopLocalFrame call |
|
112 oop* _free_list; // Handle free list |
|
113 int _allocate_before_rebuild; // Number of blocks to allocate before rebuilding free list |
|
114 |
|
115 #ifndef PRODUCT |
|
116 JNIHandleBlock* _block_list_link; // Link for list below |
|
117 static JNIHandleBlock* _block_list; // List of all allocated blocks (for debugging only) |
|
118 #endif |
|
119 |
|
120 static JNIHandleBlock* _block_free_list; // Free list of currently unused blocks |
|
121 static int _blocks_allocated; // For debugging/printing |
|
122 |
|
123 // Fill block with bad_handle values |
|
124 void zap(); |
|
125 |
|
126 protected: |
|
127 // No more handles in the both the current and following blocks |
|
128 void clear() { _top = 0; } |
|
129 |
|
130 private: |
|
131 // Free list computation |
|
132 void rebuild_free_list(); |
|
133 |
|
134 public: |
|
135 // Handle allocation |
|
136 jobject allocate_handle(oop obj); |
|
137 |
|
138 // Block allocation and block free list management |
|
139 static JNIHandleBlock* allocate_block(Thread* thread = NULL); |
|
140 static void release_block(JNIHandleBlock* block, Thread* thread = NULL); |
|
141 |
|
142 // JNI PushLocalFrame/PopLocalFrame support |
|
143 JNIHandleBlock* pop_frame_link() const { return _pop_frame_link; } |
|
144 void set_pop_frame_link(JNIHandleBlock* block) { _pop_frame_link = block; } |
|
145 |
|
146 // Stub generator support |
|
147 static int top_offset_in_bytes() { return offset_of(JNIHandleBlock, _top); } |
|
148 |
|
149 // Garbage collection support |
|
150 // Traversal of regular handles |
|
151 void oops_do(OopClosure* f); |
|
152 // Traversal of weak handles. Unreachable oops are cleared. |
|
153 void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f); |
|
154 |
|
155 // Debugging |
|
156 bool chain_contains(jobject handle) const; // Does this block or following blocks contain handle |
|
157 bool contains(jobject handle) const; // Does this block contain handle |
|
158 int length() const; // Length of chain starting with this block |
|
159 long memory_usage() const; |
|
160 #ifndef PRODUCT |
|
161 static bool any_contains(jobject handle); // Does any block currently in use contain handle |
|
162 static void print_statistics(); |
|
163 #endif |
|
164 }; |
|
165 |
|
166 |
|
167 inline oop JNIHandles::resolve(jobject handle) { |
|
168 oop result = (handle == NULL ? (oop)NULL : *(oop*)handle); |
|
169 assert(result != NULL || (handle == NULL || !CheckJNICalls || is_weak_global_handle(handle)), "Invalid value read from jni handle"); |
|
170 assert(result != badJNIHandle, "Pointing to zapped jni handle area"); |
|
171 return result; |
|
172 }; |
|
173 |
|
174 |
|
175 inline oop JNIHandles::resolve_external_guard(jobject handle) { |
|
176 if (handle == NULL) return NULL; |
|
177 oop result = *(oop*)handle; |
|
178 if (result == NULL || result == badJNIHandle) return NULL; |
|
179 return result; |
|
180 }; |
|
181 |
|
182 |
|
183 inline oop JNIHandles::resolve_non_null(jobject handle) { |
|
184 assert(handle != NULL, "JNI handle should not be null"); |
|
185 oop result = *(oop*)handle; |
|
186 assert(result != NULL, "Invalid value read from jni handle"); |
|
187 assert(result != badJNIHandle, "Pointing to zapped jni handle area"); |
|
188 // Don't let that private _deleted_handle object escape into the wild. |
|
189 assert(result != deleted_handle(), "Used a deleted global handle."); |
|
190 return result; |
|
191 }; |
|
192 |
|
193 inline void JNIHandles::destroy_local(jobject handle) { |
|
194 if (handle != NULL) { |
|
195 *((oop*)handle) = deleted_handle(); // Mark the handle as deleted, allocate will reuse it |
|
196 } |
|
197 } |
|
198 |
|
199 #endif // SHARE_VM_RUNTIME_JNIHANDLES_HPP |