显然,应用层的classLoader绝对不仅仅是一个systemclassloader那么简单。那么他一定是与PackageInfo连接起来的。而这个连接的纽带就是ContextImpl。ContextImpl又与apk一一对应。
@Override
public ClassLoader getClassLoader() {
return mPackageInfo != null ?
mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader();
}
public ClassLoader getClassLoader() {
synchronized (this) {
if (mClassLoader != null) {
return mClassLoader;
}
if (mIncludeCode && !mPackageName.equals("android")) {
String zip = mAppDir;
/*
* The following is a bit of a hack to inject
* instrumentation into the system: If the app
* being started matches one of the instrumentation names,
* then we combine both the "instrumentation" and
* "instrumented" app into the path, along with the
* concatenation of both apps' shared library lists.
*/
String instrumentationAppDir =
mActivityThread.mInstrumentationAppDir;
String instrumentationAppPackage =
mActivityThread.mInstrumentationAppPackage;
String instrumentedAppDir =
mActivityThread.mInstrumentedAppDir;
String[] instrumentationLibs = null;
if (mAppDir.equals(instrumentationAppDir)
|| mAppDir.equals(instrumentedAppDir)) {
zip = instrumentationAppDir + ":" + instrumentedAppDir;
if (! instrumentedAppDir.equals(instrumentationAppDir)) {
instrumentationLibs =
getLibrariesFor(instrumentationAppPackage);
}
}
if ((mSharedLibraries != null) ||
(instrumentationLibs != null)) {
zip =
combineLibs(mSharedLibraries, instrumentationLibs)
+ ':' + zip;
}
/*
* With all the combination done (if necessary, actually
* create the class loader.
*/
if (ActivityThread.localLOGV)
Slog.v(ActivityThread.TAG, "Class path: " + zip + ", JNI path: " + mLibDir);
// Temporarily disable logging of disk reads on the Looper thread
// as this is early and necessary.
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
mClassLoader =
ApplicationLoaders.getDefault().getClassLoader(
zip, mLibDir, mBaseClassLoader);
initializeJavaContextClassLoader();
StrictMode.setThreadPolicy(oldPolicy);
} else {
if (mBaseClassLoader == null) {
mClassLoader = ClassLoader.getSystemClassLoader();
} else {
mClassLoader = mBaseClassLoader;
}
}
return mClassLoader;
}
}
mClassLoader =
ApplicationLoaders.getDefault().getClassLoader(
zip, mLibDir, mBaseClassLoader);
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.app;
import dalvik.system.PathClassLoader;
import java.util.HashMap;
import java.util.Map;
class ApplicationLoaders
{
public static ApplicationLoaders getDefault()
{
return gApplicationLoaders;
}
public ClassLoader getClassLoader(String zip, String libPath, ClassLoader parent)
{
/*
* This is the parent we use if they pass "null" in. In theory
* this should be the "system" class loader; in practice we
* don't use that and can happily (and more efficiently) use the
* bootstrap class loader.
*/
ClassLoader baseParent = ClassLoader.getSystemClassLoader().getParent();
synchronized (mLoaders) {
if (parent == null) {
parent = baseParent;
}
/*
* If we're one step up from the base class loader, find
* something in our cache. Otherwise, we create a whole
* new ClassLoader for the zip archive.
*/
if (parent == baseParent) {
ClassLoader loader = mLoaders.get(zip);
if (loader != null) {
return loader;
}
PathClassLoader pathClassloader =
new PathClassLoader(zip, libPath, parent);
mLoaders.put(zip, pathClassloader);
return pathClassloader;
}
return new PathClassLoader(zip, parent);
}
}
private final Map<String, ClassLoader> mLoaders = new HashMap<String, ClassLoader>();
private static final ApplicationLoaders gApplicationLoaders
= new ApplicationLoaders();
}
所有的东西都在这里。具体不多说了。看了就明白。
还有一个活动当前调用的classLoader。如下:
static void Dalvik_dalvik_system_VMStack_getCallingClassLoader(const u4* args,
JValue* pResult)
{
ClassObject* clazz =
dvmGetCaller2Class(dvmThreadSelf()->interpSave.curFrame);
UNUSED_PARAMETER(args);
if (clazz == NULL)
RETURN_PTR(NULL);
RETURN_PTR(clazz->classLoader);
}
java层为VMStack.java
native public static ClassLoader getCallingClassLoader();
可以直接认为是加载当前类的classLoader。如果是BootClassLoader,那么就返回null