When I was studying android source code, I noticed that the general class loader in app is an instance of PathClassLoader
, and there is two constructors in this class. One is like:
public PathClassLoader(String dexPath, ClassLoader parent) {
super(dexPath, null, null, parent);
}
and the other is like:
public PathClassLoader(String dexPath, String libraryPath,
ClassLoader parent) {
super(dexPath, null, libraryPath, parent);
}
But I cannot find the call of the second constructor in the source code during the procedure of app launching. So where does the value of libraryPath param come from? As it is known that libraryPath refers to the list of directories containing native libraries, and is used for initializing the value of nativeLibraryDirectories
, which is a field of DexPathList object. So if there is no call of the second constructor with three params, how can the value of nativeLibraryDirectories
be initialized? Therefore how can an app find its native libraries?
Actually, I am wondering who determines the value of nativeLibraryDirectories?
Hope some one can guide me in this. Thanks a lot.
So where does the value of libraryPath param come from?
You can use Android Studio search to find it out. Perform "Find in Path", specifying the "Scope" parameter to directory of Android sources. As a text to find paste following regex expression:
new PathClassLoader\(\w+, \w+, \w+\)\;
This matches a call of the constructor with three params. Also, do not forget to check "Regular expression" checkbox:
Then in the preview tab you'll be able to see the results:
With the same technique you can find out who is calling PathClassLoaderFactory#createClassLoader()
function:
In ZygoneInit.java
you'll be able to locate following piece of code:
/**
* Creates a PathClassLoader for the system server. It also creates
* a shared namespace associated with the classloader to let it access
* platform-private native libraries.
*/
private static PathClassLoader createSystemServerClassLoader(String systemServerClasspath,
int targetSdkVersion) {
String librarySearchPath = System.getProperty("java.library.path");
return PathClassLoaderFactory.createClassLoader(systemServerClasspath,
librarySearchPath,
null /* libraryPermittedPath */,
ClassLoader.getSystemClassLoader(),
targetSdkVersion,
true /* isNamespaceShared */);
}
Now, back to your questions.
So if there is no call of the second constructor with three params...
There is, ZygoteInit#handleSystemServerProcess()
calls createSystemServerClassLoader()
, which would eventually call 3 args constructor of PathClassLoader
.
Actually, I am wondering who determines the value of nativeLibraryDirectories?
As you can see from the code above, it defaults to system property "java.library.path"
.