38 private: |
38 private: |
39 static JNIHandleBlock* _global_handles; // First global handle block |
39 static JNIHandleBlock* _global_handles; // First global handle block |
40 static JNIHandleBlock* _weak_global_handles; // First weak global handle block |
40 static JNIHandleBlock* _weak_global_handles; // First weak global handle block |
41 static oop _deleted_handle; // Sentinel marking deleted handles |
41 static oop _deleted_handle; // Sentinel marking deleted handles |
42 |
42 |
|
43 inline static bool is_jweak(jobject handle); |
|
44 inline static oop& jobject_ref(jobject handle); // NOT jweak! |
|
45 inline static oop& jweak_ref(jobject handle); |
|
46 |
|
47 template<bool external_guard> inline static oop guard_value(oop value); |
|
48 template<bool external_guard> inline static oop resolve_impl(jobject handle); |
|
49 template<bool external_guard> static oop resolve_jweak(jweak handle); |
|
50 |
43 public: |
51 public: |
|
52 // Low tag bit in jobject used to distinguish a jweak. jweak is |
|
53 // type equivalent to jobject, but there are places where we need to |
|
54 // be able to distinguish jweak values from other jobjects, and |
|
55 // is_weak_global_handle is unsuitable for performance reasons. To |
|
56 // provide such a test we add weak_tag_value to the (aligned) byte |
|
57 // address designated by the jobject to produce the corresponding |
|
58 // jweak. Accessing the value of a jobject must account for it |
|
59 // being a possibly offset jweak. |
|
60 static const uintptr_t weak_tag_size = 1; |
|
61 static const uintptr_t weak_tag_alignment = (1u << weak_tag_size); |
|
62 static const uintptr_t weak_tag_mask = weak_tag_alignment - 1; |
|
63 static const int weak_tag_value = 1; |
|
64 |
44 // Resolve handle into oop |
65 // Resolve handle into oop |
45 inline static oop resolve(jobject handle); |
66 inline static oop resolve(jobject handle); |
46 // Resolve externally provided handle into oop with some guards |
67 // Resolve externally provided handle into oop with some guards |
47 inline static oop resolve_external_guard(jobject handle); |
68 inline static oop resolve_external_guard(jobject handle); |
48 // Resolve handle into oop, result guaranteed not to be null |
69 // Resolve handle into oop, result guaranteed not to be null |
174 static bool any_contains(jobject handle); // Does any block currently in use contain handle |
195 static bool any_contains(jobject handle); // Does any block currently in use contain handle |
175 static void print_statistics(); |
196 static void print_statistics(); |
176 #endif |
197 #endif |
177 }; |
198 }; |
178 |
199 |
|
200 inline bool JNIHandles::is_jweak(jobject handle) { |
|
201 STATIC_ASSERT(weak_tag_size == 1); |
|
202 STATIC_ASSERT(weak_tag_value == 1); |
|
203 return (reinterpret_cast<uintptr_t>(handle) & weak_tag_mask) != 0; |
|
204 } |
|
205 |
|
206 inline oop& JNIHandles::jobject_ref(jobject handle) { |
|
207 assert(!is_jweak(handle), "precondition"); |
|
208 return *reinterpret_cast<oop*>(handle); |
|
209 } |
|
210 |
|
211 inline oop& JNIHandles::jweak_ref(jobject handle) { |
|
212 assert(is_jweak(handle), "precondition"); |
|
213 char* ptr = reinterpret_cast<char*>(handle) - weak_tag_value; |
|
214 return *reinterpret_cast<oop*>(ptr); |
|
215 } |
|
216 |
|
217 // external_guard is true if called from resolve_external_guard. |
|
218 // Treat deleted (and possibly zapped) as NULL for external_guard, |
|
219 // else as (asserted) error. |
|
220 template<bool external_guard> |
|
221 inline oop JNIHandles::guard_value(oop value) { |
|
222 if (!external_guard) { |
|
223 assert(value != badJNIHandle, "Pointing to zapped jni handle area"); |
|
224 assert(value != deleted_handle(), "Used a deleted global handle"); |
|
225 } else if ((value == badJNIHandle) || (value == deleted_handle())) { |
|
226 value = NULL; |
|
227 } |
|
228 return value; |
|
229 } |
|
230 |
|
231 // external_guard is true if called from resolve_external_guard. |
|
232 template<bool external_guard> |
|
233 inline oop JNIHandles::resolve_impl(jobject handle) { |
|
234 assert(handle != NULL, "precondition"); |
|
235 oop result; |
|
236 if (is_jweak(handle)) { // Unlikely |
|
237 result = resolve_jweak<external_guard>(handle); |
|
238 } else { |
|
239 result = jobject_ref(handle); |
|
240 // Construction of jobjects canonicalize a null value into a null |
|
241 // jobject, so for non-jweak the pointee should never be null. |
|
242 assert(external_guard || result != NULL, |
|
243 "Invalid value read from jni handle"); |
|
244 result = guard_value<external_guard>(result); |
|
245 } |
|
246 return result; |
|
247 } |
179 |
248 |
180 inline oop JNIHandles::resolve(jobject handle) { |
249 inline oop JNIHandles::resolve(jobject handle) { |
181 oop result = (handle == NULL ? (oop)NULL : *(oop*)handle); |
250 oop result = NULL; |
182 assert(result != NULL || (handle == NULL || !CheckJNICalls || is_weak_global_handle(handle)), "Invalid value read from jni handle"); |
251 if (handle != NULL) { |
183 assert(result != badJNIHandle, "Pointing to zapped jni handle area"); |
252 result = resolve_impl<false /* external_guard */ >(handle); |
184 return result; |
253 } |
185 }; |
254 return result; |
186 |
255 } |
187 |
256 |
|
257 // Resolve some erroneous cases to NULL, rather than treating them as |
|
258 // possibly unchecked errors. In particular, deleted handles are |
|
259 // treated as NULL (though a deleted and later reallocated handle |
|
260 // isn't detected). |
188 inline oop JNIHandles::resolve_external_guard(jobject handle) { |
261 inline oop JNIHandles::resolve_external_guard(jobject handle) { |
189 if (handle == NULL) return NULL; |
262 oop result = NULL; |
190 oop result = *(oop*)handle; |
263 if (handle != NULL) { |
191 if (result == NULL || result == badJNIHandle) return NULL; |
264 result = resolve_impl<true /* external_guard */ >(handle); |
192 return result; |
265 } |
193 }; |
266 return result; |
194 |
267 } |
195 |
268 |
196 inline oop JNIHandles::resolve_non_null(jobject handle) { |
269 inline oop JNIHandles::resolve_non_null(jobject handle) { |
197 assert(handle != NULL, "JNI handle should not be null"); |
270 assert(handle != NULL, "JNI handle should not be null"); |
198 oop result = *(oop*)handle; |
271 oop result = resolve_impl<false /* external_guard */ >(handle); |
199 assert(result != NULL, "Invalid value read from jni handle"); |
272 assert(result != NULL, "NULL read from jni handle"); |
200 assert(result != badJNIHandle, "Pointing to zapped jni handle area"); |
273 return result; |
201 // Don't let that private _deleted_handle object escape into the wild. |
274 } |
202 assert(result != deleted_handle(), "Used a deleted global handle."); |
|
203 return result; |
|
204 }; |
|
205 |
275 |
206 inline void JNIHandles::destroy_local(jobject handle) { |
276 inline void JNIHandles::destroy_local(jobject handle) { |
207 if (handle != NULL) { |
277 if (handle != NULL) { |
208 *((oop*)handle) = deleted_handle(); // Mark the handle as deleted, allocate will reuse it |
278 jobject_ref(handle) = deleted_handle(); |
209 } |
279 } |
210 } |
280 } |
211 |
281 |
212 #endif // SHARE_VM_RUNTIME_JNIHANDLES_HPP |
282 #endif // SHARE_VM_RUNTIME_JNIHANDLES_HPP |