src/share/vm/prims/nativeLookup.cpp

Tue, 08 Aug 2017 15:57:29 +0800

author
aoqi
date
Tue, 08 Aug 2017 15:57:29 +0800
changeset 6876
710a3c8b516e
parent 6632
386dd1c71858
parent 0
f90c822e73f8
child 8856
ac27a9c85bea
permissions
-rw-r--r--

merge

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

mercurial