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 |
171 static bool any_contains(jobject handle); // Does any block currently in use contain handle |
192 static bool any_contains(jobject handle); // Does any block currently in use contain handle |
172 static void print_statistics(); |
193 static void print_statistics(); |
173 #endif |
194 #endif |
174 }; |
195 }; |
175 |
196 |
|
197 inline bool JNIHandles::is_jweak(jobject handle) { |
|
198 STATIC_ASSERT(weak_tag_size == 1); |
|
199 STATIC_ASSERT(weak_tag_value == 1); |
|
200 return (reinterpret_cast<uintptr_t>(handle) & weak_tag_mask) != 0; |
|
201 } |
|
202 |
|
203 inline oop& JNIHandles::jobject_ref(jobject handle) { |
|
204 assert(!is_jweak(handle), "precondition"); |
|
205 return *reinterpret_cast<oop*>(handle); |
|
206 } |
|
207 |
|
208 inline oop& JNIHandles::jweak_ref(jobject handle) { |
|
209 assert(is_jweak(handle), "precondition"); |
|
210 char* ptr = reinterpret_cast<char*>(handle) - weak_tag_value; |
|
211 return *reinterpret_cast<oop*>(ptr); |
|
212 } |
|
213 |
|
214 // external_guard is true if called from resolve_external_guard. |
|
215 // Treat deleted (and possibly zapped) as NULL for external_guard, |
|
216 // else as (asserted) error. |
|
217 template<bool external_guard> |
|
218 inline oop JNIHandles::guard_value(oop value) { |
|
219 if (!external_guard) { |
|
220 assert(value != badJNIHandle, "Pointing to zapped jni handle area"); |
|
221 assert(value != deleted_handle(), "Used a deleted global handle"); |
|
222 } else if ((value == badJNIHandle) || (value == deleted_handle())) { |
|
223 value = NULL; |
|
224 } |
|
225 return value; |
|
226 } |
|
227 |
|
228 // external_guard is true if called from resolve_external_guard. |
|
229 template<bool external_guard> |
|
230 inline oop JNIHandles::resolve_impl(jobject handle) { |
|
231 assert(handle != NULL, "precondition"); |
|
232 oop result; |
|
233 if (is_jweak(handle)) { // Unlikely |
|
234 result = resolve_jweak<external_guard>(handle); |
|
235 } else { |
|
236 result = jobject_ref(handle); |
|
237 // Construction of jobjects canonicalize a null value into a null |
|
238 // jobject, so for non-jweak the pointee should never be null. |
|
239 assert(external_guard || result != NULL, |
|
240 "Invalid value read from jni handle"); |
|
241 result = guard_value<external_guard>(result); |
|
242 } |
|
243 return result; |
|
244 } |
176 |
245 |
177 inline oop JNIHandles::resolve(jobject handle) { |
246 inline oop JNIHandles::resolve(jobject handle) { |
178 oop result = (handle == NULL ? (oop)NULL : *(oop*)handle); |
247 oop result = NULL; |
179 assert(result != NULL || (handle == NULL || !CheckJNICalls || is_weak_global_handle(handle)), "Invalid value read from jni handle"); |
248 if (handle != NULL) { |
180 assert(result != badJNIHandle, "Pointing to zapped jni handle area"); |
249 result = resolve_impl<false /* external_guard */ >(handle); |
181 return result; |
250 } |
182 }; |
251 return result; |
183 |
252 } |
184 |
253 |
|
254 // Resolve some erroneous cases to NULL, rather than treating them as |
|
255 // possibly unchecked errors. In particular, deleted handles are |
|
256 // treated as NULL (though a deleted and later reallocated handle |
|
257 // isn't detected). |
185 inline oop JNIHandles::resolve_external_guard(jobject handle) { |
258 inline oop JNIHandles::resolve_external_guard(jobject handle) { |
186 if (handle == NULL) return NULL; |
259 oop result = NULL; |
187 oop result = *(oop*)handle; |
260 if (handle != NULL) { |
188 if (result == NULL || result == badJNIHandle) return NULL; |
261 result = resolve_impl<true /* external_guard */ >(handle); |
189 return result; |
262 } |
190 }; |
263 return result; |
191 |
264 } |
192 |
265 |
193 inline oop JNIHandles::resolve_non_null(jobject handle) { |
266 inline oop JNIHandles::resolve_non_null(jobject handle) { |
194 assert(handle != NULL, "JNI handle should not be null"); |
267 assert(handle != NULL, "JNI handle should not be null"); |
195 oop result = *(oop*)handle; |
268 oop result = resolve_impl<false /* external_guard */ >(handle); |
196 assert(result != NULL, "Invalid value read from jni handle"); |
269 assert(result != NULL, "NULL read from jni handle"); |
197 assert(result != badJNIHandle, "Pointing to zapped jni handle area"); |
270 return result; |
198 // Don't let that private _deleted_handle object escape into the wild. |
271 } |
199 assert(result != deleted_handle(), "Used a deleted global handle."); |
|
200 return result; |
|
201 }; |
|
202 |
272 |
203 inline void JNIHandles::destroy_local(jobject handle) { |
273 inline void JNIHandles::destroy_local(jobject handle) { |
204 if (handle != NULL) { |
274 if (handle != NULL) { |
205 *((oop*)handle) = deleted_handle(); // Mark the handle as deleted, allocate will reuse it |
275 jobject_ref(handle) = deleted_handle(); |
206 } |
276 } |
207 } |
277 } |
208 |
278 |
209 #endif // SHARE_VM_RUNTIME_JNIHANDLES_HPP |
279 #endif // SHARE_VM_RUNTIME_JNIHANDLES_HPP |