1 /*
2  * Copyright (c) 1997, 2020, 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 "logging/log.hpp"
31 #include "logging/logTag.hpp"
32 #include "memory/oopFactory.hpp"
33 #include "memory/resourceArea.hpp"
34 #include "oops/instanceKlass.hpp"
35 #include "oops/klass.inline.hpp"
36 #include "oops/method.hpp"
37 #include "oops/oop.inline.hpp"
38 #include "oops/symbol.hpp"
39 #include "prims/jvm_misc.hpp"
40 #include "prims/jvmtiExport.hpp"
41 #include "prims/nativeLookup.hpp"
42 #include "prims/unsafe.hpp"
43 #include "prims/scopedMemoryAccess.hpp"
44 #include "runtime/arguments.hpp"
45 #include "runtime/handles.inline.hpp"
46 #include "runtime/interfaceSupport.inline.hpp"
47 #include "runtime/javaCalls.hpp"
48 #include "runtime/os.inline.hpp"
49 #include "runtime/sharedRuntime.hpp"
50 #include "runtime/signature.hpp"
51 #include "utilities/macros.hpp"
52 #include "utilities/utf8.hpp"
53 #if INCLUDE_JFR
54 #include "jfr/jfr.hpp"
55 #endif
56 
57 /*
58 
59 The JNI specification defines the mapping from a Java native method name to
60 a C native library implementation function name as follows:
61 
62   The mapping produces a native method name by concatenating the following components
63   derived from a `native` method declaration:
64 
65   1. the prefix Java_
66   2. given the binary name, in internal form, of the class which declares the native method:
67      the result of escaping the name.
68   3. an underscore ("_")
69   4. the escaped method name
70   5. if the native method declaration is overloaded: two underscores ("__") followed by the
71    escaped parameter descriptor (JVMS 4.3.3) of the method declaration.
72 
73   Escaping leaves every alphanumeric ASCII character (A-Za-z0-9) unchanged, and replaces each
74   UTF-16 code unit n the table below with the corresponding escape sequence. If the name to be
75   escaped contains a surrogate pair, then the high-surrogate code unit and the low-surrogate code
76   unit are escaped separately. The result of escaping is a string consisting only of the ASCII
77   characters A-Za-z0-9 and underscore.
78 
79   ------------------------------                  ------------------------------------
80   UTF-16 code unit                                Escape sequence
81   ------------------------------                  ------------------------------------
82   Forward slash (/, U+002F)                       _
83   Underscore (_, U+005F)                          _1
84   Semicolon (;, U+003B)                           _2
85   Left square bracket ([, U+005B)                 _3
86   Any UTF-16 code unit \u_WXYZ_ that does not     _0wxyz where w, x, y, and z are the lower-case
87   represent alphanumeric ASCII (A-Za-z0-9),       forms of the hexadecimal digits W, X, Y, and Z.
88   forward slash, underscore, semicolon,           (For example, U+ABCD becomes _0abcd.)
89   or left square bracket
90   ------------------------------                  ------------------------------------
91 
92   Note that escape sequences can safely begin _0, _1, etc, because class and method
93   names in Java source code never begin with a number. However, that is not the case in
94   class files that were not generated from Java source code.
95 
96   To preserve the 1:1 mapping to a native method name, the VM checks the resulting name as
97   follows. If the process of escaping any precursor string from the native  method declaration
98   (class or method name, or argument type) causes a "0", "1", "2", or "3" character
99   from the precursor string to appear unchanged in the result *either* immediately after an
100   underscore *or* at the beginning of the escaped string (where it will follow an underscore
101   in the fully assembled name), then the escaping process is said to have "failed".
102   In such cases, no native library search is performed, and the attempt to link the native
103   method invocation will throw UnsatisfiedLinkError.
104 
105 
106 For example:
107 
108   package/my_class/method
109 
110 and
111 
112   package/my/1class/method
113 
114 both map to
115 
116   Java_package_my_1class_method
117 
118 To address this potential conflict we need only check if the character after
119 / is a digit 0..3, or if the first character after an injected '_' seperator
120 is a digit 0..3. If we encounter an invalid identifier we reset the
121 stringStream and return false. Otherwise the stringStream contains the mapped
122 name and we return true.
123 
124 */
map_escaped_name_on(stringStream * st,Symbol * name,int begin,int end)125 static bool map_escaped_name_on(stringStream* st, Symbol* name, int begin, int end) {
126   char* bytes = (char*)name->bytes() + begin;
127   char* end_bytes = (char*)name->bytes() + end;
128   bool check_escape_char = true; // initially true as first character here follows '_'
129   while (bytes < end_bytes) {
130     jchar c;
131     bytes = UTF8::next(bytes, &c);
132     if (c <= 0x7f && isalnum(c)) {
133       if (check_escape_char && (c >= '0' && c <= '3')) {
134         // This is a non-Java identifier and we won't escape it to
135         // ensure no name collisions with a Java identifier.
136         if (log_is_enabled(Debug, jni, resolve)) {
137           ResourceMark rm;
138           log_debug(jni, resolve)("[Lookup of native method with non-Java identifier rejected: %s]",
139                                   name->as_C_string());
140         }
141         st->reset();  // restore to "" on error
142         return false;
143       }
144       st->put((char) c);
145       check_escape_char = false;
146     } else {
147       check_escape_char = false;
148       if (c == '_') st->print("_1");
149       else if (c == '/') {
150         st->print("_");
151         // Following a / we must have non-escape character
152         check_escape_char = true;
153       }
154       else if (c == ';') st->print("_2");
155       else if (c == '[') st->print("_3");
156       else               st->print("_%.5x", c);
157     }
158   }
159   return true;
160 }
161 
162 
map_escaped_name_on(stringStream * st,Symbol * name)163 static bool map_escaped_name_on(stringStream* st, Symbol* name) {
164   return map_escaped_name_on(st, name, 0, name->utf8_length());
165 }
166 
167 
pure_jni_name(const methodHandle & method)168 char* NativeLookup::pure_jni_name(const methodHandle& method) {
169   stringStream st;
170   // Prefix
171   st.print("Java_");
172   // Klass name
173   if (!map_escaped_name_on(&st, method->klass_name())) {
174     return NULL;
175   }
176   st.print("_");
177   // Method name
178   if (!map_escaped_name_on(&st, method->name())) {
179     return NULL;
180   }
181   return st.as_string();
182 }
183 
184 
critical_jni_name(const methodHandle & method)185 char* NativeLookup::critical_jni_name(const methodHandle& method) {
186   stringStream st;
187   // Prefix
188   st.print("JavaCritical_");
189   // Klass name
190   if (!map_escaped_name_on(&st, method->klass_name())) {
191     return NULL;
192   }
193   st.print("_");
194   // Method name
195   if (!map_escaped_name_on(&st, method->name())) {
196     return NULL;
197   }
198   return st.as_string();
199 }
200 
201 
long_jni_name(const methodHandle & method)202 char* NativeLookup::long_jni_name(const methodHandle& method) {
203   // Signatures ignore the wrapping parentheses and the trailing return type
204   stringStream st;
205   Symbol* signature = method->signature();
206   st.print("__");
207   // find ')'
208   int end;
209   for (end = 0; end < signature->utf8_length() && signature->char_at(end) != JVM_SIGNATURE_ENDFUNC; end++);
210   // skip first '('
211   if (!map_escaped_name_on(&st, signature, 1, end)) {
212     return NULL;
213   }
214 
215   return st.as_string();
216 }
217 
218 extern "C" {
219   void JNICALL JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass unsafecls);
220   void JNICALL JVM_RegisterReferencesMethods(JNIEnv *env, jclass unsafecls);
221   void JNICALL JVM_RegisterUpcallHandlerMethods(JNIEnv *env, jclass unsafecls);
222   void JNICALL JVM_RegisterProgrammableUpcallHandlerMethods(JNIEnv *env, jclass unsafecls);
223   void JNICALL JVM_RegisterProgrammableInvokerMethods(JNIEnv *env, jclass unsafecls);
224   void JNICALL JVM_RegisterNativeEntryPointMethods(JNIEnv *env, jclass unsafecls);
225   void JNICALL JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass);
226   void JNICALL JVM_RegisterWhiteBoxMethods(JNIEnv *env, jclass wbclass);
227   void JNICALL JVM_RegisterVectorSupportMethods(JNIEnv *env, jclass vsclass);
228 #if INCLUDE_JVMCI
229   jobject  JNICALL JVM_GetJVMCIRuntime(JNIEnv *env, jclass c);
230   void     JNICALL JVM_RegisterJVMCINatives(JNIEnv *env, jclass compilerToVMClass);
231 #endif
232 }
233 
234 #define CC (char*)  /* cast a literal from (const char*) */
235 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
236 
237 static JNINativeMethod lookup_special_native_methods[] = {
238   { CC"Java_jdk_internal_misc_Unsafe_registerNatives",             NULL, FN_PTR(JVM_RegisterJDKInternalMiscUnsafeMethods) },
239   { CC"Java_java_lang_invoke_MethodHandleNatives_registerNatives", NULL, FN_PTR(JVM_RegisterMethodHandleMethods) },
240   { CC"Java_jdk_internal_foreign_abi_UpcallStubs_registerNatives",      NULL, FN_PTR(JVM_RegisterUpcallHandlerMethods) },
241   { CC"Java_jdk_internal_foreign_abi_ProgrammableUpcallHandler_registerNatives",      NULL, FN_PTR(JVM_RegisterProgrammableUpcallHandlerMethods) },
242   { CC"Java_jdk_internal_foreign_abi_ProgrammableInvoker_registerNatives",      NULL, FN_PTR(JVM_RegisterProgrammableInvokerMethods) },
243   { CC"Java_jdk_internal_invoke_NativeEntryPoint_registerNatives",      NULL, FN_PTR(JVM_RegisterNativeEntryPointMethods) },
244   { CC"Java_jdk_internal_perf_Perf_registerNatives",               NULL, FN_PTR(JVM_RegisterPerfMethods)         },
245   { CC"Java_sun_hotspot_WhiteBox_registerNatives",                 NULL, FN_PTR(JVM_RegisterWhiteBoxMethods)     },
246   { CC"Java_jdk_internal_vm_vector_VectorSupport_registerNatives", NULL, FN_PTR(JVM_RegisterVectorSupportMethods)},
247 #if INCLUDE_JVMCI
248   { CC"Java_jdk_vm_ci_runtime_JVMCI_initializeRuntime",            NULL, FN_PTR(JVM_GetJVMCIRuntime)             },
249   { CC"Java_jdk_vm_ci_hotspot_CompilerToVM_registerNatives",       NULL, FN_PTR(JVM_RegisterJVMCINatives)        },
250 #endif
251 #if INCLUDE_JFR
252   { CC"Java_jdk_jfr_internal_JVM_registerNatives",                 NULL, FN_PTR(jfr_register_natives)            },
253 #endif
254   { CC"Java_jdk_internal_misc_ScopedMemoryAccess_registerNatives", NULL, FN_PTR(JVM_RegisterJDKInternalMiscScopedMemoryAccessMethods) },
255 };
256 
lookup_special_native(const char * jni_name)257 static address lookup_special_native(const char* jni_name) {
258   int count = sizeof(lookup_special_native_methods) / sizeof(JNINativeMethod);
259   for (int i = 0; i < count; i++) {
260     // NB: To ignore the jni prefix and jni postfix strstr is used matching.
261     if (strstr(jni_name, lookup_special_native_methods[i].name) != NULL) {
262       return CAST_FROM_FN_PTR(address, lookup_special_native_methods[i].fnPtr);
263     }
264   }
265   return NULL;
266 }
267 
lookup_style(const methodHandle & method,char * pure_name,const char * long_name,int args_size,bool os_style,bool & in_base_library,TRAPS)268 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) {
269   address entry;
270   const char* jni_name = compute_complete_jni_name(pure_name, long_name, args_size, os_style);
271 
272 
273   // If the loader is null we have a system class, so we attempt a lookup in
274   // the native Java library. This takes care of any bootstrapping problems.
275   // Note: It is critical for bootstrapping that Java_java_lang_ClassLoader_findNative
276   // gets found the first time around - otherwise an infinite loop can occure. This is
277   // another VM/library dependency
278   Handle loader(THREAD, method->method_holder()->class_loader());
279   if (loader.is_null()) {
280     entry = lookup_special_native(jni_name);
281     if (entry == NULL) {
282        entry = (address) os::dll_lookup(os::native_java_library(), jni_name);
283     }
284     if (entry != NULL) {
285       in_base_library = true;
286       return entry;
287     }
288   }
289 
290   // Otherwise call static method findNative in ClassLoader
291   Klass*   klass = SystemDictionary::ClassLoader_klass();
292   Handle name_arg = java_lang_String::create_from_str(jni_name, CHECK_NULL);
293 
294   JavaValue result(T_LONG);
295   JavaCalls::call_static(&result,
296                          klass,
297                          vmSymbols::findNative_name(),
298                          vmSymbols::classloader_string_long_signature(),
299                          // Arguments
300                          loader,
301                          name_arg,
302                          CHECK_NULL);
303   entry = (address) (intptr_t) result.get_jlong();
304 
305   if (entry == NULL) {
306     // findNative didn't find it, if there are any agent libraries look in them
307     AgentLibrary* agent;
308     for (agent = Arguments::agents(); agent != NULL; agent = agent->next()) {
309       entry = (address) os::dll_lookup(agent->os_lib(), jni_name);
310       if (entry != NULL) {
311         return entry;
312       }
313     }
314   }
315 
316   return entry;
317 }
318 
compute_complete_jni_name(const char * pure_name,const char * long_name,int args_size,bool os_style)319 const char* NativeLookup::compute_complete_jni_name(const char* pure_name, const char* long_name, int args_size, bool os_style) {
320   stringStream st;
321   if (os_style) {
322     os::print_jni_name_prefix_on(&st, args_size);
323   }
324 
325   st.print_raw(pure_name);
326   st.print_raw(long_name);
327   if (os_style) {
328     os::print_jni_name_suffix_on(&st, args_size);
329   }
330 
331   return st.as_string();
332 }
333 
lookup_critical_style(void * dll,const char * pure_name,const char * long_name,int args_size,bool os_style)334 address NativeLookup::lookup_critical_style(void* dll, const char* pure_name, const char* long_name, int args_size, bool os_style) {
335   const char* jni_name = compute_complete_jni_name(pure_name, long_name, args_size, os_style);
336   assert(dll != NULL, "dll must be loaded");
337   return (address)os::dll_lookup(dll, jni_name);
338 }
339 
340 // Check all the formats of native implementation name to see if there is one
341 // for the specified method.
lookup_entry(const methodHandle & method,bool & in_base_library,TRAPS)342 address NativeLookup::lookup_entry(const methodHandle& method, bool& in_base_library, TRAPS) {
343   address entry = NULL;
344   in_base_library = false;
345   // Compute pure name
346   char* pure_name = pure_jni_name(method);
347   if (pure_name == NULL) {
348     // JNI name mapping rejected this method so return
349     // NULL to indicate UnsatisfiedLinkError should be thrown.
350     return NULL;
351   }
352 
353   // Compute argument size
354   int args_size = 1                             // JNIEnv
355                 + (method->is_static() ? 1 : 0) // class for static methods
356                 + method->size_of_parameters(); // actual parameters
357 
358   // 1) Try JNI short style
359   entry = lookup_style(method, pure_name, "",        args_size, true,  in_base_library, CHECK_NULL);
360   if (entry != NULL) return entry;
361 
362   // Compute long name
363   char* long_name = long_jni_name(method);
364   if (long_name == NULL) {
365     // JNI name mapping rejected this method so return
366     // NULL to indicate UnsatisfiedLinkError should be thrown.
367     return NULL;
368   }
369 
370   // 2) Try JNI long style
371   entry = lookup_style(method, pure_name, long_name, args_size, true,  in_base_library, CHECK_NULL);
372   if (entry != NULL) return entry;
373 
374   // 3) Try JNI short style without os prefix/suffix
375   entry = lookup_style(method, pure_name, "",        args_size, false, in_base_library, CHECK_NULL);
376   if (entry != NULL) return entry;
377 
378   // 4) Try JNI long style without os prefix/suffix
379   entry = lookup_style(method, pure_name, long_name, args_size, false, in_base_library, CHECK_NULL);
380 
381   return entry; // NULL indicates not found
382 }
383 
384 // Check all the formats of native implementation name to see if there is one
385 // for the specified method.
lookup_critical_entry(const methodHandle & method)386 address NativeLookup::lookup_critical_entry(const methodHandle& method) {
387   assert(CriticalJNINatives, "or should not be here");
388 
389   if (method->is_synchronized() ||
390       !method->is_static()) {
391     // Only static non-synchronized methods are allowed
392     return NULL;
393   }
394 
395   ResourceMark rm;
396 
397   Symbol* signature = method->signature();
398   for (int end = 0; end < signature->utf8_length(); end++) {
399     if (signature->char_at(end) == 'L') {
400       // Don't allow object types
401       return NULL;
402     }
403   }
404 
405   // Compute argument size
406   int args_size = method->size_of_parameters();
407   for (SignatureStream ss(signature); !ss.at_return_type(); ss.next()) {
408     if (ss.is_array()) {
409       args_size += T_INT_size; // array length parameter
410     }
411   }
412 
413   // dll handling requires I/O. Don't do that while in _thread_in_vm (safepoint may get requested).
414   ThreadToNativeFromVM thread_in_native(JavaThread::current());
415 
416   void* dll = dll_load(method);
417   address entry = NULL;
418 
419   if (dll != NULL) {
420     entry = lookup_critical_style(dll, method, args_size);
421     // Close the handle to avoid keeping the library alive if the native method holder is unloaded.
422     // This is fine because the library is still kept alive by JNI (see JVM_LoadLibrary). As soon
423     // as the holder class and the library are unloaded (see JVM_UnloadLibrary), the native wrapper
424     // that calls 'critical_entry' becomes unreachable and is unloaded as well.
425     os::dll_unload(dll);
426   }
427 
428   return entry; // NULL indicates not found
429 }
430 
dll_load(const methodHandle & method)431 void* NativeLookup::dll_load(const methodHandle& method) {
432   if (method->has_native_function()) {
433 
434     address current_entry = method->native_function();
435 
436     char dll_name[JVM_MAXPATHLEN];
437     int offset;
438     if (os::dll_address_to_library_name(current_entry, dll_name, sizeof(dll_name), &offset)) {
439       char ebuf[32];
440       return os::dll_load(dll_name, ebuf, sizeof(ebuf));
441     }
442   }
443 
444   return NULL;
445 }
446 
lookup_critical_style(void * dll,const methodHandle & method,int args_size)447 address NativeLookup::lookup_critical_style(void* dll, const methodHandle& method, int args_size) {
448   address entry = NULL;
449   const char* critical_name = critical_jni_name(method);
450   if (critical_name == NULL) {
451     // JNI name mapping rejected this method so return
452     // NULL to indicate UnsatisfiedLinkError should be thrown.
453     return NULL;
454   }
455 
456   // 1) Try JNI short style
457   entry = lookup_critical_style(dll, critical_name, "",        args_size, true);
458   if (entry != NULL) {
459     return entry;
460   }
461 
462   const char* long_name = long_jni_name(method);
463   if (long_name == NULL) {
464     // JNI name mapping rejected this method so return
465     // NULL to indicate UnsatisfiedLinkError should be thrown.
466     return NULL;
467   }
468 
469   // 2) Try JNI long style
470   entry = lookup_critical_style(dll, critical_name, long_name, args_size, true);
471   if (entry != NULL) {
472     return entry;
473   }
474 
475   // 3) Try JNI short style without os prefix/suffix
476   entry = lookup_critical_style(dll, critical_name, "",        args_size, false);
477   if (entry != NULL) {
478     return entry;
479   }
480 
481   // 4) Try JNI long style without os prefix/suffix
482   return lookup_critical_style(dll, critical_name, long_name, args_size, false);
483 }
484 
485 // Check if there are any JVM TI prefixes which have been applied to the native method name.
486 // If any are found, remove them before attemping the look up of the
487 // native implementation again.
488 // See SetNativeMethodPrefix in the JVM TI Spec for more details.
lookup_entry_prefixed(const methodHandle & method,bool & in_base_library,TRAPS)489 address NativeLookup::lookup_entry_prefixed(const methodHandle& method, bool& in_base_library, TRAPS) {
490 #if INCLUDE_JVMTI
491   ResourceMark rm(THREAD);
492 
493   int prefix_count;
494   char** prefixes = JvmtiExport::get_all_native_method_prefixes(&prefix_count);
495   char* in_name = method->name()->as_C_string();
496   char* wrapper_name = in_name;
497   // last applied prefix will be first -- go backwards
498   for (int i = prefix_count-1; i >= 0; i--) {
499     char* prefix = prefixes[i];
500     size_t prefix_len = strlen(prefix);
501     if (strncmp(prefix, wrapper_name, prefix_len) == 0) {
502       // has this prefix remove it
503       wrapper_name += prefix_len;
504     }
505   }
506   if (wrapper_name != in_name) {
507     // we have a name for a wrapping method
508     int wrapper_name_len = (int)strlen(wrapper_name);
509     TempNewSymbol wrapper_symbol = SymbolTable::probe(wrapper_name, wrapper_name_len);
510     if (wrapper_symbol != NULL) {
511       Klass* k = method->method_holder();
512       Method* wrapper_method = k->lookup_method(wrapper_symbol, method->signature());
513       if (wrapper_method != NULL && !wrapper_method->is_native()) {
514         // we found a wrapper method, use its native entry
515         method->set_is_prefixed_native();
516         return lookup_entry(methodHandle(THREAD, wrapper_method), in_base_library, THREAD);
517       }
518     }
519   }
520 #endif // INCLUDE_JVMTI
521   return NULL;
522 }
523 
lookup_base(const methodHandle & method,bool & in_base_library,TRAPS)524 address NativeLookup::lookup_base(const methodHandle& method, bool& in_base_library, TRAPS) {
525   address entry = NULL;
526   ResourceMark rm(THREAD);
527 
528   entry = lookup_entry(method, in_base_library, THREAD);
529   if (entry != NULL) return entry;
530 
531   // standard native method resolution has failed.  Check if there are any
532   // JVM TI prefixes which have been applied to the native method name.
533   entry = lookup_entry_prefixed(method, in_base_library, THREAD);
534   if (entry != NULL) return entry;
535 
536   // Native function not found, throw UnsatisfiedLinkError
537   stringStream ss;
538   ss.print("'");
539   method->print_external_name(&ss);
540   ss.print("'");
541   THROW_MSG_0(vmSymbols::java_lang_UnsatisfiedLinkError(), ss.as_string());
542 }
543 
544 
lookup(const methodHandle & method,bool & in_base_library,TRAPS)545 address NativeLookup::lookup(const methodHandle& method, bool& in_base_library, TRAPS) {
546   if (!method->has_native_function()) {
547     address entry = lookup_base(method, in_base_library, CHECK_NULL);
548     method->set_native_function(entry,
549       Method::native_bind_event_is_interesting);
550     // -verbose:jni printing
551     if (log_is_enabled(Debug, jni, resolve)) {
552       ResourceMark rm(THREAD);
553       log_debug(jni, resolve)("[Dynamic-linking native method %s.%s ... JNI]",
554                               method->method_holder()->external_name(),
555                               method->name()->as_C_string());
556     }
557   }
558   return method->native_function();
559 }
560 
base_library_lookup(const char * class_name,const char * method_name,const char * signature)561 address NativeLookup::base_library_lookup(const char* class_name, const char* method_name, const char* signature) {
562   EXCEPTION_MARK;
563   bool in_base_library = true;  // SharedRuntime inits some math methods.
564   TempNewSymbol c_name = SymbolTable::new_symbol(class_name);
565   TempNewSymbol m_name = SymbolTable::new_symbol(method_name);
566   TempNewSymbol s_name = SymbolTable::new_symbol(signature);
567 
568   // Find the class
569   Klass* k = SystemDictionary::resolve_or_fail(c_name, true, CATCH);
570   InstanceKlass* klass  = InstanceKlass::cast(k);
571 
572   // Find method and invoke standard lookup
573   methodHandle method (THREAD,
574                        klass->uncached_lookup_method(m_name, s_name, Klass::OverpassLookupMode::find));
575   address result = lookup(method, in_base_library, CATCH);
576   assert(in_base_library, "must be in basic library");
577   guarantee(result != NULL, "must be non NULL");
578   return result;
579 }
580