| 1 | /* |
| 2 | * Copyright (c) 1997, 2019, 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 | #include "precompiled.hpp" |
| 26 | #include "classfile/javaClasses.hpp" |
| 27 | #include "classfile/symbolTable.hpp" |
| 28 | #include "classfile/systemDictionary.hpp" |
| 29 | #include "classfile/vmSymbols.hpp" |
| 30 | #include "memory/oopFactory.hpp" |
| 31 | #include "memory/resourceArea.hpp" |
| 32 | #include "oops/instanceKlass.hpp" |
| 33 | #include "oops/method.hpp" |
| 34 | #include "oops/oop.inline.hpp" |
| 35 | #include "oops/symbol.hpp" |
| 36 | #include "prims/jvm_misc.hpp" |
| 37 | #include "prims/nativeLookup.hpp" |
| 38 | #include "prims/unsafe.hpp" |
| 39 | #include "runtime/arguments.hpp" |
| 40 | #include "runtime/handles.inline.hpp" |
| 41 | #include "runtime/javaCalls.hpp" |
| 42 | #include "runtime/os.inline.hpp" |
| 43 | #include "runtime/sharedRuntime.hpp" |
| 44 | #include "runtime/signature.hpp" |
| 45 | #include "utilities/macros.hpp" |
| 46 | #include "utilities/utf8.hpp" |
| 47 | #if INCLUDE_JFR |
| 48 | #include "jfr/jfr.hpp" |
| 49 | #endif |
| 50 | |
| 51 | static void mangle_name_on(outputStream* st, Symbol* name, int begin, int end) { |
| 52 | char* bytes = (char*)name->bytes() + begin; |
| 53 | char* end_bytes = (char*)name->bytes() + end; |
| 54 | while (bytes < end_bytes) { |
| 55 | jchar c; |
| 56 | bytes = UTF8::next(bytes, &c); |
| 57 | if (c <= 0x7f && isalnum(c)) { |
| 58 | st->put((char) c); |
| 59 | } else { |
| 60 | if (c == '_') st->print("_1" ); |
| 61 | else if (c == '/') st->print("_" ); |
| 62 | else if (c == ';') st->print("_2" ); |
| 63 | else if (c == '[') st->print("_3" ); |
| 64 | else st->print("_%.5x" , c); |
| 65 | } |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | |
| 70 | static void mangle_name_on(outputStream* st, Symbol* name) { |
| 71 | mangle_name_on(st, name, 0, name->utf8_length()); |
| 72 | } |
| 73 | |
| 74 | |
| 75 | char* NativeLookup::pure_jni_name(const methodHandle& method) { |
| 76 | stringStream st; |
| 77 | // Prefix |
| 78 | st.print("Java_" ); |
| 79 | // Klass name |
| 80 | mangle_name_on(&st, method->klass_name()); |
| 81 | st.print("_" ); |
| 82 | // Method name |
| 83 | mangle_name_on(&st, method->name()); |
| 84 | return st.as_string(); |
| 85 | } |
| 86 | |
| 87 | |
| 88 | char* NativeLookup::critical_jni_name(const methodHandle& method) { |
| 89 | stringStream st; |
| 90 | // Prefix |
| 91 | st.print("JavaCritical_" ); |
| 92 | // Klass name |
| 93 | mangle_name_on(&st, method->klass_name()); |
| 94 | st.print("_" ); |
| 95 | // Method name |
| 96 | mangle_name_on(&st, method->name()); |
| 97 | return st.as_string(); |
| 98 | } |
| 99 | |
| 100 | |
| 101 | char* NativeLookup::long_jni_name(const methodHandle& method) { |
| 102 | // Signature ignore the wrapping parenteses and the trailing return type |
| 103 | stringStream st; |
| 104 | Symbol* signature = method->signature(); |
| 105 | st.print("__" ); |
| 106 | // find ')' |
| 107 | int end; |
| 108 | for (end = 0; end < signature->utf8_length() && signature->char_at(end) != ')'; end++); |
| 109 | // skip first '(' |
| 110 | mangle_name_on(&st, signature, 1, end); |
| 111 | return st.as_string(); |
| 112 | } |
| 113 | |
| 114 | extern "C" { |
| 115 | void JNICALL JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass unsafecls); |
| 116 | void JNICALL JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass); |
| 117 | void JNICALL JVM_RegisterWhiteBoxMethods(JNIEnv *env, jclass wbclass); |
| 118 | #if INCLUDE_JVMCI |
| 119 | jobject JNICALL JVM_GetJVMCIRuntime(JNIEnv *env, jclass c); |
| 120 | void JNICALL JVM_RegisterJVMCINatives(JNIEnv *env, jclass compilerToVMClass); |
| 121 | #endif |
| 122 | } |
| 123 | |
| 124 | #define CC (char*) /* cast a literal from (const char*) */ |
| 125 | #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) |
| 126 | |
| 127 | static JNINativeMethod lookup_special_native_methods[] = { |
| 128 | { CC"Java_jdk_internal_misc_Unsafe_registerNatives" , NULL, FN_PTR(JVM_RegisterJDKInternalMiscUnsafeMethods) }, |
| 129 | { CC"Java_java_lang_invoke_MethodHandleNatives_registerNatives" , NULL, FN_PTR(JVM_RegisterMethodHandleMethods) }, |
| 130 | { CC"Java_jdk_internal_perf_Perf_registerNatives" , NULL, FN_PTR(JVM_RegisterPerfMethods) }, |
| 131 | { CC"Java_sun_hotspot_WhiteBox_registerNatives" , NULL, FN_PTR(JVM_RegisterWhiteBoxMethods) }, |
| 132 | #if INCLUDE_JVMCI |
| 133 | { CC"Java_jdk_vm_ci_runtime_JVMCI_initializeRuntime" , NULL, FN_PTR(JVM_GetJVMCIRuntime) }, |
| 134 | { CC"Java_jdk_vm_ci_hotspot_CompilerToVM_registerNatives" , NULL, FN_PTR(JVM_RegisterJVMCINatives) }, |
| 135 | #endif |
| 136 | #if INCLUDE_JFR |
| 137 | { CC"Java_jdk_jfr_internal_JVM_registerNatives" , NULL, FN_PTR(jfr_register_natives) }, |
| 138 | #endif |
| 139 | }; |
| 140 | |
| 141 | static address lookup_special_native(char* jni_name) { |
| 142 | int count = sizeof(lookup_special_native_methods) / sizeof(JNINativeMethod); |
| 143 | for (int i = 0; i < count; i++) { |
| 144 | // NB: To ignore the jni prefix and jni postfix strstr is used matching. |
| 145 | if (strstr(jni_name, lookup_special_native_methods[i].name) != NULL) { |
| 146 | return CAST_FROM_FN_PTR(address, lookup_special_native_methods[i].fnPtr); |
| 147 | } |
| 148 | } |
| 149 | return NULL; |
| 150 | } |
| 151 | |
| 152 | address NativeLookup::lookup_style(const methodHandle& method, char* pure_name, const char* long_name, int args_size, bool os_style, bool& in_base_library, TRAPS) { |
| 153 | address entry; |
| 154 | // Compute complete JNI name for style |
| 155 | stringStream st; |
| 156 | if (os_style) os::print_jni_name_prefix_on(&st, args_size); |
| 157 | st.print_raw(pure_name); |
| 158 | st.print_raw(long_name); |
| 159 | if (os_style) os::print_jni_name_suffix_on(&st, args_size); |
| 160 | char* jni_name = st.as_string(); |
| 161 | |
| 162 | // If the loader is null we have a system class, so we attempt a lookup in |
| 163 | // the native Java library. This takes care of any bootstrapping problems. |
| 164 | // Note: It is critical for bootstrapping that Java_java_lang_ClassLoader_00024NativeLibrary_find |
| 165 | // gets found the first time around - otherwise an infinite loop can occure. This is |
| 166 | // another VM/library dependency |
| 167 | Handle loader(THREAD, method->method_holder()->class_loader()); |
| 168 | if (loader.is_null()) { |
| 169 | entry = lookup_special_native(jni_name); |
| 170 | if (entry == NULL) { |
| 171 | entry = (address) os::dll_lookup(os::native_java_library(), jni_name); |
| 172 | } |
| 173 | if (entry != NULL) { |
| 174 | in_base_library = true; |
| 175 | return entry; |
| 176 | } |
| 177 | } |
| 178 | |
| 179 | // Otherwise call static method findNative in ClassLoader |
| 180 | Klass* klass = SystemDictionary::ClassLoader_klass(); |
| 181 | Handle name_arg = java_lang_String::create_from_str(jni_name, CHECK_NULL); |
| 182 | |
| 183 | JavaValue result(T_LONG); |
| 184 | JavaCalls::call_static(&result, |
| 185 | klass, |
| 186 | vmSymbols::findNative_name(), |
| 187 | vmSymbols::classloader_string_long_signature(), |
| 188 | // Arguments |
| 189 | loader, |
| 190 | name_arg, |
| 191 | CHECK_NULL); |
| 192 | entry = (address) (intptr_t) result.get_jlong(); |
| 193 | |
| 194 | if (entry == NULL) { |
| 195 | // findNative didn't find it, if there are any agent libraries look in them |
| 196 | AgentLibrary* agent; |
| 197 | for (agent = Arguments::agents(); agent != NULL; agent = agent->next()) { |
| 198 | entry = (address) os::dll_lookup(agent->os_lib(), jni_name); |
| 199 | if (entry != NULL) { |
| 200 | return entry; |
| 201 | } |
| 202 | } |
| 203 | } |
| 204 | |
| 205 | return entry; |
| 206 | } |
| 207 | |
| 208 | |
| 209 | address NativeLookup::lookup_critical_style(const methodHandle& method, char* pure_name, const char* long_name, int args_size, bool os_style) { |
| 210 | if (!method->has_native_function()) { |
| 211 | return NULL; |
| 212 | } |
| 213 | |
| 214 | address current_entry = method->native_function(); |
| 215 | |
| 216 | char dll_name[JVM_MAXPATHLEN]; |
| 217 | int offset; |
| 218 | if (os::dll_address_to_library_name(current_entry, dll_name, sizeof(dll_name), &offset)) { |
| 219 | char ebuf[32]; |
| 220 | void* dll = os::dll_load(dll_name, ebuf, sizeof(ebuf)); |
| 221 | if (dll != NULL) { |
| 222 | // Compute complete JNI name for style |
| 223 | stringStream st; |
| 224 | if (os_style) os::print_jni_name_prefix_on(&st, args_size); |
| 225 | st.print_raw(pure_name); |
| 226 | st.print_raw(long_name); |
| 227 | if (os_style) os::print_jni_name_suffix_on(&st, args_size); |
| 228 | char* jni_name = st.as_string(); |
| 229 | address critical_entry = (address)os::dll_lookup(dll, jni_name); |
| 230 | // Close the handle to avoid keeping the library alive if the native method holder is unloaded. |
| 231 | // This is fine because the library is still kept alive by JNI (see JVM_LoadLibrary). As soon |
| 232 | // as the holder class and the library are unloaded (see JVM_UnloadLibrary), the native wrapper |
| 233 | // that calls 'critical_entry' becomes unreachable and is unloaded as well. |
| 234 | os::dll_unload(dll); |
| 235 | return critical_entry; |
| 236 | } |
| 237 | } |
| 238 | |
| 239 | return NULL; |
| 240 | } |
| 241 | |
| 242 | |
| 243 | // Check all the formats of native implementation name to see if there is one |
| 244 | // for the specified method. |
| 245 | address NativeLookup::lookup_entry(const methodHandle& method, bool& in_base_library, TRAPS) { |
| 246 | address entry = NULL; |
| 247 | in_base_library = false; |
| 248 | // Compute pure name |
| 249 | char* pure_name = pure_jni_name(method); |
| 250 | |
| 251 | // Compute argument size |
| 252 | int args_size = 1 // JNIEnv |
| 253 | + (method->is_static() ? 1 : 0) // class for static methods |
| 254 | + method->size_of_parameters(); // actual parameters |
| 255 | |
| 256 | // 1) Try JNI short style |
| 257 | entry = lookup_style(method, pure_name, "" , args_size, true, in_base_library, CHECK_NULL); |
| 258 | if (entry != NULL) return entry; |
| 259 | |
| 260 | // Compute long name |
| 261 | char* long_name = long_jni_name(method); |
| 262 | |
| 263 | // 2) Try JNI long style |
| 264 | entry = lookup_style(method, pure_name, long_name, args_size, true, in_base_library, CHECK_NULL); |
| 265 | if (entry != NULL) return entry; |
| 266 | |
| 267 | // 3) Try JNI short style without os prefix/suffix |
| 268 | entry = lookup_style(method, pure_name, "" , args_size, false, in_base_library, CHECK_NULL); |
| 269 | if (entry != NULL) return entry; |
| 270 | |
| 271 | // 4) Try JNI long style without os prefix/suffix |
| 272 | entry = lookup_style(method, pure_name, long_name, args_size, false, in_base_library, CHECK_NULL); |
| 273 | |
| 274 | return entry; // NULL indicates not found |
| 275 | } |
| 276 | |
| 277 | // Check all the formats of native implementation name to see if there is one |
| 278 | // for the specified method. |
| 279 | address NativeLookup::lookup_critical_entry(const methodHandle& method) { |
| 280 | if (!CriticalJNINatives) return NULL; |
| 281 | |
| 282 | if (method->is_synchronized() || |
| 283 | !method->is_static()) { |
| 284 | // Only static non-synchronized methods are allowed |
| 285 | return NULL; |
| 286 | } |
| 287 | |
| 288 | ResourceMark rm; |
| 289 | address entry = NULL; |
| 290 | |
| 291 | Symbol* signature = method->signature(); |
| 292 | for (int end = 0; end < signature->utf8_length(); end++) { |
| 293 | if (signature->char_at(end) == 'L') { |
| 294 | // Don't allow object types |
| 295 | return NULL; |
| 296 | } |
| 297 | } |
| 298 | |
| 299 | // Compute critical name |
| 300 | char* critical_name = critical_jni_name(method); |
| 301 | |
| 302 | // Compute argument size |
| 303 | int args_size = method->size_of_parameters(); |
| 304 | for (SignatureStream ss(signature); !ss.at_return_type(); ss.next()) { |
| 305 | if (ss.is_array()) { |
| 306 | args_size += T_INT_size; // array length parameter |
| 307 | } |
| 308 | } |
| 309 | |
| 310 | // 1) Try JNI short style |
| 311 | entry = lookup_critical_style(method, critical_name, "" , args_size, true); |
| 312 | if (entry != NULL) return entry; |
| 313 | |
| 314 | // Compute long name |
| 315 | char* long_name = long_jni_name(method); |
| 316 | |
| 317 | // 2) Try JNI long style |
| 318 | entry = lookup_critical_style(method, critical_name, long_name, args_size, true); |
| 319 | if (entry != NULL) return entry; |
| 320 | |
| 321 | // 3) Try JNI short style without os prefix/suffix |
| 322 | entry = lookup_critical_style(method, critical_name, "" , args_size, false); |
| 323 | if (entry != NULL) return entry; |
| 324 | |
| 325 | // 4) Try JNI long style without os prefix/suffix |
| 326 | entry = lookup_critical_style(method, critical_name, long_name, args_size, false); |
| 327 | |
| 328 | return entry; // NULL indicates not found |
| 329 | } |
| 330 | |
| 331 | // Check if there are any JVM TI prefixes which have been applied to the native method name. |
| 332 | // If any are found, remove them before attemping the look up of the |
| 333 | // native implementation again. |
| 334 | // See SetNativeMethodPrefix in the JVM TI Spec for more details. |
| 335 | address NativeLookup::lookup_entry_prefixed(const methodHandle& method, bool& in_base_library, TRAPS) { |
| 336 | #if INCLUDE_JVMTI |
| 337 | ResourceMark rm(THREAD); |
| 338 | |
| 339 | int prefix_count; |
| 340 | char** prefixes = JvmtiExport::get_all_native_method_prefixes(&prefix_count); |
| 341 | char* in_name = method->name()->as_C_string(); |
| 342 | char* wrapper_name = in_name; |
| 343 | // last applied prefix will be first -- go backwards |
| 344 | for (int i = prefix_count-1; i >= 0; i--) { |
| 345 | char* prefix = prefixes[i]; |
| 346 | size_t prefix_len = strlen(prefix); |
| 347 | if (strncmp(prefix, wrapper_name, prefix_len) == 0) { |
| 348 | // has this prefix remove it |
| 349 | wrapper_name += prefix_len; |
| 350 | } |
| 351 | } |
| 352 | if (wrapper_name != in_name) { |
| 353 | // we have a name for a wrapping method |
| 354 | int wrapper_name_len = (int)strlen(wrapper_name); |
| 355 | TempNewSymbol wrapper_symbol = SymbolTable::probe(wrapper_name, wrapper_name_len); |
| 356 | if (wrapper_symbol != NULL) { |
| 357 | Klass* k = method->method_holder(); |
| 358 | Method* wrapper_method = k->lookup_method(wrapper_symbol, method->signature()); |
| 359 | if (wrapper_method != NULL && !wrapper_method->is_native()) { |
| 360 | // we found a wrapper method, use its native entry |
| 361 | method->set_is_prefixed_native(); |
| 362 | return lookup_entry(wrapper_method, in_base_library, THREAD); |
| 363 | } |
| 364 | } |
| 365 | } |
| 366 | #endif // INCLUDE_JVMTI |
| 367 | return NULL; |
| 368 | } |
| 369 | |
| 370 | address NativeLookup::lookup_base(const methodHandle& method, bool& in_base_library, TRAPS) { |
| 371 | address entry = NULL; |
| 372 | ResourceMark rm(THREAD); |
| 373 | |
| 374 | entry = lookup_entry(method, in_base_library, THREAD); |
| 375 | if (entry != NULL) return entry; |
| 376 | |
| 377 | // standard native method resolution has failed. Check if there are any |
| 378 | // JVM TI prefixes which have been applied to the native method name. |
| 379 | entry = lookup_entry_prefixed(method, in_base_library, THREAD); |
| 380 | if (entry != NULL) return entry; |
| 381 | |
| 382 | // Native function not found, throw UnsatisfiedLinkError |
| 383 | stringStream ss; |
| 384 | ss.print("'" ); |
| 385 | method->print_external_name(&ss); |
| 386 | ss.print("'" ); |
| 387 | THROW_MSG_0(vmSymbols::java_lang_UnsatisfiedLinkError(), ss.as_string()); |
| 388 | } |
| 389 | |
| 390 | |
| 391 | address NativeLookup::lookup(const methodHandle& method, bool& in_base_library, TRAPS) { |
| 392 | if (!method->has_native_function()) { |
| 393 | address entry = lookup_base(method, in_base_library, CHECK_NULL); |
| 394 | method->set_native_function(entry, |
| 395 | Method::native_bind_event_is_interesting); |
| 396 | // -verbose:jni printing |
| 397 | if (PrintJNIResolving) { |
| 398 | ResourceMark rm(THREAD); |
| 399 | tty->print_cr("[Dynamic-linking native method %s.%s ... JNI]" , |
| 400 | method->method_holder()->external_name(), |
| 401 | method->name()->as_C_string()); |
| 402 | } |
| 403 | } |
| 404 | return method->native_function(); |
| 405 | } |
| 406 | |
| 407 | address NativeLookup::base_library_lookup(const char* class_name, const char* method_name, const char* signature) { |
| 408 | EXCEPTION_MARK; |
| 409 | bool in_base_library = true; // SharedRuntime inits some math methods. |
| 410 | TempNewSymbol c_name = SymbolTable::new_symbol(class_name); |
| 411 | TempNewSymbol m_name = SymbolTable::new_symbol(method_name); |
| 412 | TempNewSymbol s_name = SymbolTable::new_symbol(signature); |
| 413 | |
| 414 | // Find the class |
| 415 | Klass* k = SystemDictionary::resolve_or_fail(c_name, true, CATCH); |
| 416 | InstanceKlass* klass = InstanceKlass::cast(k); |
| 417 | |
| 418 | // Find method and invoke standard lookup |
| 419 | methodHandle method (THREAD, |
| 420 | klass->uncached_lookup_method(m_name, s_name, Klass::find_overpass)); |
| 421 | address result = lookup(method, in_base_library, CATCH); |
| 422 | assert(in_base_library, "must be in basic library" ); |
| 423 | guarantee(result != NULL, "must be non NULL" ); |
| 424 | return result; |
| 425 | } |
| 426 | |