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 | |