1.1 --- a/src/share/vm/runtime/jniHandles.hpp Thu Nov 05 11:42:42 2015 +0100 1.2 +++ b/src/share/vm/runtime/jniHandles.hpp Tue May 07 20:38:26 2019 +0000 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -40,7 +40,28 @@ 1.11 static JNIHandleBlock* _weak_global_handles; // First weak global handle block 1.12 static oop _deleted_handle; // Sentinel marking deleted handles 1.13 1.14 + inline static bool is_jweak(jobject handle); 1.15 + inline static oop& jobject_ref(jobject handle); // NOT jweak! 1.16 + inline static oop& jweak_ref(jobject handle); 1.17 + 1.18 + template<bool external_guard> inline static oop guard_value(oop value); 1.19 + template<bool external_guard> inline static oop resolve_impl(jobject handle); 1.20 + template<bool external_guard> static oop resolve_jweak(jweak handle); 1.21 + 1.22 public: 1.23 + // Low tag bit in jobject used to distinguish a jweak. jweak is 1.24 + // type equivalent to jobject, but there are places where we need to 1.25 + // be able to distinguish jweak values from other jobjects, and 1.26 + // is_weak_global_handle is unsuitable for performance reasons. To 1.27 + // provide such a test we add weak_tag_value to the (aligned) byte 1.28 + // address designated by the jobject to produce the corresponding 1.29 + // jweak. Accessing the value of a jobject must account for it 1.30 + // being a possibly offset jweak. 1.31 + static const uintptr_t weak_tag_size = 1; 1.32 + static const uintptr_t weak_tag_alignment = (1u << weak_tag_size); 1.33 + static const uintptr_t weak_tag_mask = weak_tag_alignment - 1; 1.34 + static const int weak_tag_value = 1; 1.35 + 1.36 // Resolve handle into oop 1.37 inline static oop resolve(jobject handle); 1.38 // Resolve externally provided handle into oop with some guards 1.39 @@ -173,36 +194,85 @@ 1.40 #endif 1.41 }; 1.42 1.43 +inline bool JNIHandles::is_jweak(jobject handle) { 1.44 + STATIC_ASSERT(weak_tag_size == 1); 1.45 + STATIC_ASSERT(weak_tag_value == 1); 1.46 + return (reinterpret_cast<uintptr_t>(handle) & weak_tag_mask) != 0; 1.47 +} 1.48 + 1.49 +inline oop& JNIHandles::jobject_ref(jobject handle) { 1.50 + assert(!is_jweak(handle), "precondition"); 1.51 + return *reinterpret_cast<oop*>(handle); 1.52 +} 1.53 + 1.54 +inline oop& JNIHandles::jweak_ref(jobject handle) { 1.55 + assert(is_jweak(handle), "precondition"); 1.56 + char* ptr = reinterpret_cast<char*>(handle) - weak_tag_value; 1.57 + return *reinterpret_cast<oop*>(ptr); 1.58 +} 1.59 + 1.60 +// external_guard is true if called from resolve_external_guard. 1.61 +// Treat deleted (and possibly zapped) as NULL for external_guard, 1.62 +// else as (asserted) error. 1.63 +template<bool external_guard> 1.64 +inline oop JNIHandles::guard_value(oop value) { 1.65 + if (!external_guard) { 1.66 + assert(value != badJNIHandle, "Pointing to zapped jni handle area"); 1.67 + assert(value != deleted_handle(), "Used a deleted global handle"); 1.68 + } else if ((value == badJNIHandle) || (value == deleted_handle())) { 1.69 + value = NULL; 1.70 + } 1.71 + return value; 1.72 +} 1.73 + 1.74 +// external_guard is true if called from resolve_external_guard. 1.75 +template<bool external_guard> 1.76 +inline oop JNIHandles::resolve_impl(jobject handle) { 1.77 + assert(handle != NULL, "precondition"); 1.78 + oop result; 1.79 + if (is_jweak(handle)) { // Unlikely 1.80 + result = resolve_jweak<external_guard>(handle); 1.81 + } else { 1.82 + result = jobject_ref(handle); 1.83 + // Construction of jobjects canonicalize a null value into a null 1.84 + // jobject, so for non-jweak the pointee should never be null. 1.85 + assert(external_guard || result != NULL, 1.86 + "Invalid value read from jni handle"); 1.87 + result = guard_value<external_guard>(result); 1.88 + } 1.89 + return result; 1.90 +} 1.91 1.92 inline oop JNIHandles::resolve(jobject handle) { 1.93 - oop result = (handle == NULL ? (oop)NULL : *(oop*)handle); 1.94 - assert(result != NULL || (handle == NULL || !CheckJNICalls || is_weak_global_handle(handle)), "Invalid value read from jni handle"); 1.95 - assert(result != badJNIHandle, "Pointing to zapped jni handle area"); 1.96 + oop result = NULL; 1.97 + if (handle != NULL) { 1.98 + result = resolve_impl<false /* external_guard */ >(handle); 1.99 + } 1.100 return result; 1.101 -}; 1.102 +} 1.103 1.104 - 1.105 +// Resolve some erroneous cases to NULL, rather than treating them as 1.106 +// possibly unchecked errors. In particular, deleted handles are 1.107 +// treated as NULL (though a deleted and later reallocated handle 1.108 +// isn't detected). 1.109 inline oop JNIHandles::resolve_external_guard(jobject handle) { 1.110 - if (handle == NULL) return NULL; 1.111 - oop result = *(oop*)handle; 1.112 - if (result == NULL || result == badJNIHandle) return NULL; 1.113 + oop result = NULL; 1.114 + if (handle != NULL) { 1.115 + result = resolve_impl<true /* external_guard */ >(handle); 1.116 + } 1.117 return result; 1.118 -}; 1.119 - 1.120 +} 1.121 1.122 inline oop JNIHandles::resolve_non_null(jobject handle) { 1.123 assert(handle != NULL, "JNI handle should not be null"); 1.124 - oop result = *(oop*)handle; 1.125 - assert(result != NULL, "Invalid value read from jni handle"); 1.126 - assert(result != badJNIHandle, "Pointing to zapped jni handle area"); 1.127 - // Don't let that private _deleted_handle object escape into the wild. 1.128 - assert(result != deleted_handle(), "Used a deleted global handle."); 1.129 + oop result = resolve_impl<false /* external_guard */ >(handle); 1.130 + assert(result != NULL, "NULL read from jni handle"); 1.131 return result; 1.132 -}; 1.133 +} 1.134 1.135 inline void JNIHandles::destroy_local(jobject handle) { 1.136 if (handle != NULL) { 1.137 - *((oop*)handle) = deleted_handle(); // Mark the handle as deleted, allocate will reuse it 1.138 + jobject_ref(handle) = deleted_handle(); 1.139 } 1.140 } 1.141