loadLibrary主要是在Runtime.java中实现,各个版本之间差异比较大,所以做个笔记来整理这些区别。
4.4 版本
源码:
Cross Reference: /libcore/luni/src/main/java/java/lang/Runtime.java
主要是这一块:
http://androidxref.com/4.4.4_r1/xref/libcore/luni/src/main/java/java/lang/Runtime.java#354
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| void loadLibrary(String libraryName, ClassLoader loader) { 355 if (loader != null) { 356 String filename = loader.findLibrary(libraryName); 357 if (filename == null) { 358 throw new UnsatisfiedLinkError("Couldn't load " + libraryName + 359 " from loader " + loader + 360 ": findLibrary returned null"); 361 } 362 String error = doLoad(filename, loader); 363 if (error != null) { 364 throw new UnsatisfiedLinkError(error); 365 } 366 return; 367 } 368 369 String filename = System.mapLibraryName(libraryName); 370 List<String> candidates = new ArrayList<String>(); 371 String lastError = null; 372 for (String directory : mLibPaths) { 373 String candidate = directory + filename; 374 candidates.add(candidate); 375 376 if (IoUtils.canOpenReadOnly(candidate)) { 377 String error = doLoad(candidate, loader); 378 if (error == null) { 379 return; 380 } 381 lastError = error; 382 } 383 } 384 385 if (lastError != null) { 386 throw new UnsatisfiedLinkError(lastError); 387 } 388 throw new UnsatisfiedLinkError("Library " + libraryName + " not found; tried " + candidates); 389 }
|
其中关键的一部分代码是这个:
1 2 3 4 5 6
| String filename = loader.findLibrary(libraryName); 357 if (filename == null) { 358 throw new UnsatisfiedLinkError("Couldn't load " + libraryName + 359 " from loader " + loader + 360 ": findLibrary returned null"); 361 }
|
接着去寻找findLibrary。
http://androidxref.com/4.4.4_r1/xref/libcore/dalvik/src/main/java/dalvik/system/DexPathList.java#380
1 2 3 4 5 6 7 8 9 10
| 380 public String findLibrary(String libraryName) { 381 String fileName = System.mapLibraryName(libraryName); 382 for (File directory : nativeLibraryDirectories) { 383 String path = new File(directory, fileName).getPath(); 384 if (IoUtils.canOpenReadOnly(path)) { 385 return path; 386 } 387 } 388 return null; 389 }
|
就是将nativeLibraryDirectories变量遍历里面是否包含了要加载的so文件。
来看下nativeLibraryDirectories是怎么得到的。
1 2
| /** List of native library directories. */ private final File[]nativeLibraryDirectories;
|
是一个File[]数组呢,而且是final的。
但是接着看的话,在DexPathList初始化的时候将这个变量进行赋值:
- this.nativeLibraryDirectories = splitLibraryPath(libraryPath);
5.0版本
源码:
http://androidxref.com/5.0.0_r2/xref/libcore/luni/src/main/java/java/lang/Runtime.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| 358 void loadLibrary(String libraryName, ClassLoader loader) { 359 if (loader != null) { 360 String filename = loader.findLibrary(libraryName); 361 if (filename == null) { 362 363 364 365 366 throw new UnsatisfiedLinkError(loader + " couldn't find \\"" + 367 System.mapLibraryName(libraryName) + "\\""); 368 } 369 String error = doLoad(filename, loader); 370 if (error != null) { 371 throw new UnsatisfiedLinkError(error); 372 } 373 return; 374 } 375 376 String filename = System.mapLibraryName(libraryName); 377 List<String> candidates = new ArrayList<String>(); 378 String lastError = null; 379 for (String directory : mLibPaths) { 380 String candidate = directory + filename; 381 candidates.add(candidate); 382 383 if (IoUtils.canOpenReadOnly(candidate)) { 384 String error = doLoad(candidate, loader); 385 if (error == null) { 386 return; 387 } 388 lastError = error; 389 } 390 } 391 392 if (lastError != null) { 393 throw new UnsatisfiedLinkError(lastError); 394 } 395 throw new UnsatisfiedLinkError("Library " + libraryName + " not found; tried " + candidates); 396 }
|
findLibrary:
1 2 3 4 5 6 7 8 9 10
| 379 public String findLibrary(String libraryName) { 380 String fileName = System.mapLibraryName(libraryName); 381 for (File directory : nativeLibraryDirectories) { 382 String path = new File(directory, fileName).getPath(); 383 if (IoUtils.canOpenReadOnly(path)) { 384 return path; 385 } 386 } 387 return null; 388 }
|
nativeLibraryDirectories:
1 2
| /** List of native library directories. */ private final File[]nativeLibraryDirectories;
|
也还是File数组且为final。
最后赋值也是跟4.4一样:
- this.nativeLibraryDirectories = splitLibraryPath(libraryPath);
5.1版本
源码:
http://androidxref.com/5.1.1_r6/xref/libcore/luni/src/main/java/java/lang/Runtime.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| 358 void loadLibrary(String libraryName, ClassLoader loader) { 359 if (loader != null) { 360 String filename = loader.findLibrary(libraryName); 361 if (filename == null) { 362 363 364 365 366 throw new UnsatisfiedLinkError(loader + " couldn't find \\"" + 367 System.mapLibraryName(libraryName) + "\\""); 368 } 369 String error = doLoad(filename, loader); 370 if (error != null) { 371 throw new UnsatisfiedLinkError(error); 372 } 373 return; 374 } 375 376 String filename = System.mapLibraryName(libraryName); 377 List<String> candidates = new ArrayList<String>(); 378 String lastError = null; 379 for (String directory : mLibPaths) { 380 String candidate = directory + filename; 381 candidates.add(candidate); 382 383 if (IoUtils.canOpenReadOnly(candidate)) { 384 String error = doLoad(candidate, loader); 385 if (error == null) { 386 return; 387 } 388 lastError = error; 389 } 390 } 391 392 if (lastError != null) { 393 throw new UnsatisfiedLinkError(lastError); 394 } 395 throw new UnsatisfiedLinkError("Library " + libraryName + " not found; tried " + candidates); 396 }
|
findLibrary:
1 2 3 4 5 6 7 8 9 10
| 379 public String findLibrary(String libraryName) { 380 String fileName = System.mapLibraryName(libraryName); 381 for (File directory : nativeLibraryDirectories) { 382 String path = new File(directory, fileName).getPath(); 383 if (IoUtils.canOpenReadOnly(path)) { 384 return path; 385 } 386 } 387 return null; 388 }
|
nativeLibraryDirectories:
1 2
| /** List of native library directories. */ private final File[] nativeLibraryDirectories;
|
- this.nativeLibraryDirectories = splitLibraryPath(libraryPath);
- private static File[] splitLibraryPath(String path)
6.0版本
源码:
http://androidxref.com/6.0.1_r10/xref/libcore/luni/src/main/java/java/lang/Runtime.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| 359 void loadLibrary(String libraryName, ClassLoader loader) { 360 if (loader != null) { 361 String filename = loader.findLibrary(libraryName); 362 if (filename == null) { 363 364 365 366 367 throw new UnsatisfiedLinkError(loader + " couldn't find \\"" + 368 System.mapLibraryName(libraryName) + "\\""); 369 } 370 String error = doLoad(filename, loader); 371 if (error != null) { 372 throw new UnsatisfiedLinkError(error); 373 } 374 return; 375 } 376 377 String filename = System.mapLibraryName(libraryName); 378 List<String> candidates = new ArrayList<String>(); 379 String lastError = null; 380 for (String directory : mLibPaths) { 381 String candidate = directory + filename; 382 candidates.add(candidate); 383 384 if (IoUtils.canOpenReadOnly(candidate)) { 385 String error = doLoad(candidate, loader); 386 if (error == null) { 387 return; 388 } 389 lastError = error; 390 } 391 } 392 393 if (lastError != null) { 394 throw new UnsatisfiedLinkError(lastError); 395 } 396 throw new UnsatisfiedLinkError("Library " + libraryName + " not found; tried " + candidates); 397 }
|
findLibrary:
1 2 3 4 5 6 7 8 9 10 11 12 13
| 396 public String findLibrary(String libraryName) { 397 String fileName = System.mapLibraryName(libraryName); 398 399 for (Element element : nativeLibraryPathElements) { 400 String path = element.findNativeLibrary(fileName); 401 402 if (path != null) { 403 return path; 404 } 405 } 406 407 return null; 408 }
|
nativeLibraryPathElements,从6.0开始好像就有了nativeLibraryPathElements这个属性。
1 2
| /** List of native library path elements. */ private final Element[] nativeLibraryPathElements;
|
从这里开始复制
1 2
| this.nativeLibraryPathElements = makePathElements(allNativeLibraryDirectories, null, suppressedExceptions);
|
然后makePathElements:
1
| private static Element[] makePathElements(List<File>files,File optimizedDirectory,List<IOException>suppressedExceptions)
|
属性就可以了。
7.0版本
源码:
http://androidxref.com/7.0.0_r1/xref/libcore/ojluni/src/main/java/java/lang/Runtime.java
从7.0开始增加了loadLibrary0这个函数,其实就是将之前的loadLibrary改成了这个,其实都一个作用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| 959 synchronized void loadLibrary0(ClassLoader loader, String libname) { 960 if (libname.indexOf((int)File.separatorChar) != -1) { 961 throw new UnsatisfiedLinkError( 962 "Directory separator should not appear in library name: " + libname); 963 } 964 String libraryName = libname; 965 if (loader != null) { 966 String filename = loader.findLibrary(libraryName); 967 if (filename == null) { 968 969 970 971 972 throw new UnsatisfiedLinkError(loader + " couldn't find \\"" + 973 System.mapLibraryName(libraryName) + "\\""); 974 } 975 String error = doLoad(filename, loader); 976 if (error != null) { 977 throw new UnsatisfiedLinkError(error); 978 } 979 return; 980 } 981 982 String filename = System.mapLibraryName(libraryName); 983 List<String> candidates = new ArrayList<String>(); 984 String lastError = null; 985 for (String directory : getLibPaths()) { 986 String candidate = directory + filename; 987 candidates.add(candidate); 988 989 if (IoUtils.canOpenReadOnly(candidate)) { 990 String error = doLoad(candidate, loader); 991 if (error == null) { 992 return; 993 } 994 lastError = error; 995 } 996 } 997 998 if (lastError != null) { 999 throw new UnsatisfiedLinkError(lastError); 1000 } 1001 throw new UnsatisfiedLinkError("Library " + libraryName + " not found; tried " + candidates); 1002 }
|
findLibrary:
1 2 3 4 5 6 7 8 9 10 11 12 13
| 476 public String findLibrary(String libraryName) { 477 String fileName = System.mapLibraryName(libraryName); 478 479 for (Element element : nativeLibraryPathElements) { 480 String path = element.findNativeLibrary(fileName); 481 482 if (path != null) { 483 return path; 484 } 485 } 486 487 return null; 488 }
|
nativeLibraryPathElements:
1 2
| /** List of native library path elements. */ private final Element[]nativeLibraryPathElements;
|
怎么赋值的呢:
1 2 3
| 145 this.nativeLibraryPathElements = makePathElements(allNativeLibraryDirectories, 146 suppressedExceptions, 147 definingContext);
|
又进行了改变
1 2 3
| 269 private static Element[] makePathElements(List<File> files, 270 List<IOException> suppressedExceptions, 271 ClassLoader loader)
|
之前6.0的两个list和一个file,又改成了两个list和一个classloader
7.1跟7.0一样不赘述。
8.0
源码:
http://androidxref.com/8.1.0_r33/xref/libcore/ojluni/src/main/java/java/lang/Runtime.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| 998 synchronized void loadLibrary0(ClassLoader loader, String libname) { 999 if (libname.indexOf((int)File.separatorChar) != -1) { 1000 throw new UnsatisfiedLinkError( 1001 "Directory separator should not appear in library name: " + libname); 1002 } 1003 String libraryName = libname; 1004 if (loader != null) { 1005 String filename = loader.findLibrary(libraryName); 1006 if (filename == null) { 1007 1008 1009 1010 1011 throw new UnsatisfiedLinkError(loader + " couldn't find \\"" + 1012 System.mapLibraryName(libraryName) + "\\""); 1013 } 1014 String error = doLoad(filename, loader); 1015 if (error != null) { 1016 throw new UnsatisfiedLinkError(error); 1017 } 1018 return; 1019 } 1020 1021 String filename = System.mapLibraryName(libraryName); 1022 List<String> candidates = new ArrayList<String>(); 1023 String lastError = null; 1024 for (String directory : getLibPaths()) { 1025 String candidate = directory + filename; 1026 candidates.add(candidate); 1027 1028 if (IoUtils.canOpenReadOnly(candidate)) { 1029 String error = doLoad(candidate, loader); 1030 if (error == null) { 1031 return; 1032 } 1033 lastError = error; 1034 } 1035 } 1036 1037 if (lastError != null) { 1038 throw new UnsatisfiedLinkError(lastError); 1039 } 1040 throw new UnsatisfiedLinkError("Library " + libraryName + " not found; tried " + candidates); 1041 }
|
findLibrary:
1 2 3 4 5 6 7 8 9 10 11 12 13
| 524 public String findLibrary(String libraryName) { 525 String fileName = System.mapLibraryName(libraryName); 526 527 for (NativeLibraryElement element : nativeLibraryPathElements) { 528 String path = element.findNativeLibrary(fileName); 529 530 if (path != null) { 531 return path; 532 } 533 } 534 535 return null; 536 }
|
怎么赋值的呢
- this.nativeLibraryPathElements = makePathElements(this.systemNativeLibraryDirectories);
然后makePathElements:
- private static NativeLibraryElement[] makePathElements(List files)
返回值改了,参数也改了。
就很纳闷,google这帮人不干实事整天改这个干嘛,有漏洞?
总结
4.4 ~5.1
都是使用的
this.nativeLibraryDirectories = splitLibraryPath(libraryPath);
private static File[] splitLibraryPath(String path)
6.0
this.nativeLibraryPathElements = makePathElements(allNativeLibraryDirectories, null,suppressedExceptions);
private static Element[] makePathElements(ListFile files, File optimizedDirectory,ListIOException suppressedExceptions)
7.0 ~ 7.1
this.nativeLibraryPathElements = makePathElements(allNativeLibraryDirectories, suppressedExceptions, definingContext);
private static Element[] makePathElements(List files, List suppressedExceptions, ClassLoader loader)
8.0 ~ 8.1
this.nativeLibraryPathElements = makePathElements(this.systemNativeLibraryDirectories);
private static NativeLibraryElement[] makePathElements(List files)