// /libcore/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java public String getLdLibraryPath() { StringBuilderresult=newStringBuilder(); for (File directory : pathList.getNativeLibraryDirectories()) { if (result.length() > 0) { result.append(':'); } result.append(directory); }
return result.toString(); }
1 2 3 4
// /libcore/dalvik/src/main/java/dalvik/system/DexPathList.java public List<File> getNativeLibraryDirectories() { return nativeLibraryDirectories; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// /libcore/dalvik/src/main/java/dalvik/system/DexPathList.java 160// Native libraries may exist in both the system and 161// application library paths, and we use this search order: 162// 163// 1. This class loader's library path for application libraries (librarySearchPath): 164// 1.1. Native library directories 165// 1.2. Path to libraries in apk-files 166// 2. The VM's library path from the system property for system libraries 167// also known as java.library.path 168// 169// This order was reversed prior to Gingerbread; see http://b/2933456. 170this.nativeLibraryDirectories = splitPaths(librarySearchPath, false); 171this.systemNativeLibraryDirectories = 172 splitPaths(System.getProperty("java.library.path"), true); 173 List<File> allNativeLibraryDirectories = newArrayList<>(nativeLibraryDirectories); 174 allNativeLibraryDirectories.addAll(systemNativeLibraryDirectories); 175 176this.nativeLibraryPathElements = makePathElements(allNativeLibraryDirectories);
// /art/runtime/java_vm_ext.cc 796bool JavaVMExt::LoadNativeLibrary(JNIEnv* env, 797conststd::string& path, 798 jobject class_loader, 799 jstring library_path, 800std::string* error_msg) { 801 error_msg->clear(); 802 803// See if we've already loaded this library. If we have, and the class loader 804// matches, return successfully without doing anything. 805// TODO: for better results we should canonicalize the pathname (or even compare 806// inodes). This implementation is fine if everybody is using System.loadLibrary. 807 SharedLibrary* library; 808 Thread* self = Thread::Current(); 809 { 810// TODO: move the locking (and more of this logic) into Libraries. 811 MutexLock mu(self, *Locks::jni_libraries_lock_); 812 library = libraries_->Get(path); 813 } 814void* class_loader_allocator = nullptr; 815 { 816 ScopedObjectAccess soa(env); 817// As the incoming class loader is reachable/alive during the call of this function, 818// it's okay to decode it without worrying about unexpectedly marking it alive. 819 ObjPtr<mirror::ClassLoader> loader = soa.Decode<mirror::ClassLoader>(class_loader); 820 821 ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 822if (class_linker->IsBootClassLoader(soa, loader.Ptr())) { 823 loader = nullptr; 824 class_loader = nullptr; 825 } 826 827 class_loader_allocator = class_linker->GetAllocatorForClassLoader(loader.Ptr()); 828 CHECK(class_loader_allocator != nullptr); 829 } 830if (library != nullptr) { 831// Use the allocator pointers for class loader equality to avoid unnecessary weak root decode. 832if (library->GetClassLoaderAllocator() != class_loader_allocator) { 833// The library will be associated with class_loader. The JNI 834// spec says we can't load the same library into more than one 835// class loader. 836 StringAppendF(error_msg, "Shared library \"%s\" already opened by " 837"ClassLoader %p; can't open in ClassLoader %p", 838 path.c_str(), library->GetClassLoader(), class_loader); 839 LOG(WARNING) << error_msg; 840returnfalse; 841 } 842 VLOG(jni) << "[Shared library \"" << path << "\" already loaded in " 843 << " ClassLoader " << class_loader << "]"; 844if (!library->CheckOnLoadResult()) { 845 StringAppendF(error_msg, "JNI_OnLoad failed on a previous attempt " 846"to load \"%s\"", path.c_str()); 847returnfalse; 848 } 849returntrue; 850 } 851 852// Open the shared library. Because we're using a full path, the system 853// doesn't have to search through LD_LIBRARY_PATH. (It may do so to 854// resolve this library's dependencies though.) 855 856// Failures here are expected when java.library.path has several entries 857// and we have to hunt for the lib. 858 859// Below we dlopen but there is no paired dlclose, this would be necessary if we supported 860// class unloading. Libraries will only be unloaded when the reference count (incremented by 861// dlopen) becomes zero from dlclose. 862 863 Locks::mutator_lock_->AssertNotHeld(self); 864constchar* path_str = path.empty() ? nullptr : path.c_str(); 865bool needs_native_bridge = false; 866void* handle = android::OpenNativeLibrary(env, 867 runtime_->GetTargetSdkVersion(), 868 path_str, 869 class_loader, 870 library_path, 871 &needs_native_bridge, 872 error_msg); 873 874 VLOG(jni) << "[Call to dlopen(\"" << path << "\", RTLD_NOW) returned " << handle << "]"; 875 876if (handle == nullptr) { 877 VLOG(jni) << "dlopen(\"" << path << "\", RTLD_NOW) failed: " << *error_msg; 878returnfalse; 879 } 880 881if (env->ExceptionCheck() == JNI_TRUE) { 882 LOG(ERROR) << "Unexpected exception:"; 883 env->ExceptionDescribe(); 884 env->ExceptionClear(); 885 } 886// Create a new entry. 887// TODO: move the locking (and more of this logic) into Libraries. 888bool created_library = false; 889 { 890// Create SharedLibrary ahead of taking the libraries lock to maintain lock ordering. 891std::unique_ptr<SharedLibrary> new_library( 892 new SharedLibrary(env, 893 self, 894 path, 895 handle, 896 needs_native_bridge, 897 class_loader, 898 class_loader_allocator)); 899 900 MutexLock mu(self, *Locks::jni_libraries_lock_); 901 library = libraries_->Get(path); 902if (library == nullptr) { // We won race to get libraries_lock. 903 library = new_library.release(); 904 libraries_->Put(path, library); 905 created_library = true; 906 } 907 } 908if (!created_library) { 909 LOG(INFO) << "WOW: we lost a race to add shared library: " 910 << "\"" << path << "\" ClassLoader=" << class_loader; 911return library->CheckOnLoadResult(); 912 } 913 VLOG(jni) << "[Added shared library \"" << path << "\" for ClassLoader " << class_loader << "]"; 914 915bool was_successful = false; 916void* sym = library->FindSymbol("JNI_OnLoad", nullptr); 917if (sym == nullptr) { 918 VLOG(jni) << "[No JNI_OnLoad found in \"" << path << "\"]"; 919 was_successful = true; 920 } else { 921// Call JNI_OnLoad. We have to override the current class 922// loader, which will always be "null" since the stuff at the 923// top of the stack is around Runtime.loadLibrary(). (See 924// the comments in the JNI FindClass function.) 925 ScopedLocalRef<jobject> old_class_loader(env, env->NewLocalRef(self->GetClassLoaderOverride())); 926 self->SetClassLoaderOverride(class_loader); 927 928 VLOG(jni) << "[Calling JNI_OnLoad in \"" << path << "\"]"; 929typedefint(*JNI_OnLoadFn)(JavaVM*, void*); 930 JNI_OnLoadFn jni_on_load = reinterpret_cast<JNI_OnLoadFn>(sym); 931int version = (*jni_on_load)(this, nullptr); 932 933if (runtime_->GetTargetSdkVersion() != 0 && runtime_->GetTargetSdkVersion() <= 21) { 934// Make sure that sigchain owns SIGSEGV. 935 EnsureFrontOfChain(SIGSEGV); 936 } 937 938 self->SetClassLoaderOverride(old_class_loader.get()); 939 940if (version == JNI_ERR) { 941 StringAppendF(error_msg, "JNI_ERR returned from JNI_OnLoad in \"%s\"", path.c_str()); 942 } elseif (JavaVMExt::IsBadJniVersion(version)) { 943 StringAppendF(error_msg, "Bad JNI version returned from JNI_OnLoad in \"%s\": %d", 944 path.c_str(), version); 945// It's unwise to call dlclose() here, but we can mark it 946// as bad and ensure that future load attempts will fail. 947// We don't know how far JNI_OnLoad got, so there could 948// be some partially-initialized stuff accessible through 949// newly-registered native method calls. We could try to 950// unregister them, but that doesn't seem worthwhile. 951 } else { 952 was_successful = true; 953 } 954 VLOG(jni) << "[Returned " << (was_successful ? "successfully" : "failure") 955 << " from JNI_OnLoad in \"" << path << "\"]"; 956 } 957 958 library->SetResult(was_successful); 959return was_successful; 960}
23// These functions are exported by the loader 24// TODO(dimitry): replace these with reference to libc.so 25 26 __attribute__((__weak__, visibility("default"))) 27void* __loader_dlopen(constchar* filename, int flags, constvoid* caller_addr);
// /bionic/linker/linker.cpp 1431staticboolfind_library_internal(android_namespace_t* ns, 1432 LoadTask* task, 1433 ZipArchiveCache* zip_archive_cache, 1434 LoadTaskList* load_tasks, 1435int rtld_flags, 1436bool search_linked_namespaces) { 1437 soinfo* candidate; 1438 1439if (find_loaded_library_by_soname(ns, task->get_name(), search_linked_namespaces, &candidate)) {//根据so的名称查找在soInfo的链表中查找是否已经存在 1440 task->set_soinfo(candidate); 1441returntrue; 1442 } 1443 1444// Library might still be loaded, the accurate detection 1445// of this fact is done by load_library. 1446 TRACE("[ \"%s\" find_loaded_library_by_soname failed (*candidate=%s@%p). Trying harder...]", 1447 task->get_name(), candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate); 1448 1449if (load_library(ns, task, zip_archive_cache, load_tasks, rtld_flags, search_linked_namespaces)) {//如果不存在,说明还没加载,继续调用load_library 加载so 1450returntrue; 1451 } 1452 1453if (search_linked_namespaces) { 1454// if a library was not found - look into linked namespaces 1455for (auto& linked_namespace : ns->linked_namespaces()) { 1456if (find_library_in_linked_namespace(linked_namespace, 1457 task)) { 1458if (task->get_soinfo() == nullptr) { 1459// try to load the library - once namespace boundary is crossed 1460// we need to load a library within separate load_group 1461// to avoid using symbols from foreign namespace while. 1462// 1463// However, actual linking is deferred until when the global group 1464// is fully identified and is applied to all namespaces. 1465// Otherwise, the libs in the linked namespace won't get symbols from 1466// the global group. 1467if (load_library(linked_namespace.linked_namespace(), task, zip_archive_cache, load_tasks, rtld_flags, false)) { 1468returntrue; 1469 } 1470// lib was not found in the namespace. Try next linked namespace. 1471 } else { 1472// lib is already loaded 1473returntrue; 1474 } 1475 } 1476 } 1477 } 1478 1479returnfalse; 1480 }
// /bionic/linker/linker_soinfo.cpp 388voidsoinfo::call_constructors() { 389if (constructors_called) { 390return; 391 } 392 393// We set constructors_called before actually calling the constructors, otherwise it doesn't 394// protect against recursive constructor calls. One simple example of constructor recursion 395// is the libc debug malloc, which is implemented in libc_malloc_debug_leak.so: 396// 1. The program depends on libc, so libc's constructor is called here. 397// 2. The libc constructor calls dlopen() to load libc_malloc_debug_leak.so. 398// 3. dlopen() calls the constructors on the newly created 399// soinfo for libc_malloc_debug_leak.so. 400// 4. The debug .so depends on libc, so CallConstructors is 401// called again with the libc soinfo. If it doesn't trigger the early- 402// out above, the libc constructor will be called again (recursively!). 403 constructors_called = true; 404 405if (!is_main_executable() && preinit_array_ != nullptr) { 406// The GNU dynamic linker silently ignores these, but we warn the developer. 407 PRINT("\"%s\": ignoring DT_PREINIT_ARRAY in shared library!", get_realpath()); 408 } 409 410 get_children().for_each([] (soinfo* si) { 411 si->call_constructors(); 412 }); 413 414if (!is_linker()) { 415 bionic_trace_begin((std::string("calling constructors: ") + get_realpath()).c_str()); 416 } 417 418// DT_INIT should be called before DT_INIT_ARRAY if both are present. 419 call_function("DT_INIT", init_func_, get_realpath()); 420 call_array("DT_INIT_ARRAY", init_array_, init_array_count_, false, get_realpath()); 421 422if (!is_linker()) { 423 bionic_trace_end(); 424 } 425 }