安卓高手之路之ClassLoader(四)

安卓高手之路之ClassLoader(四) - 修补C++ - ITeye技术网站

显然,应用层的classLoader绝对不仅仅是一个systemclassloader那么简单。那么他一定是与PackageInfo连接起来的。而这个连接的纽带就是ContextImpl。ContextImpl又与apk一一对应。

Java代码  收藏代码
  1. @Override  
  2. public ClassLoader getClassLoader() {  
  3.     return mPackageInfo != null ?  
  4.             mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader();  
  5. }  
    @Override
    public ClassLoader getClassLoader() {
        return mPackageInfo != null ?
                mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader();
    }
Java代码  收藏代码
  1. public ClassLoader getClassLoader() {  
  2.     synchronized (this) {  
  3.         if (mClassLoader != null) {  
  4.             return mClassLoader;  
  5.         }  
  6.   
  7.         if (mIncludeCode && !mPackageName.equals("android")) {  
  8.             String zip = mAppDir;  
  9.   
  10.             /* 
  11.              * The following is a bit of a hack to inject 
  12.              * instrumentation into the system: If the app 
  13.              * being started matches one of the instrumentation names, 
  14.              * then we combine both the "instrumentation" and 
  15.              * "instrumented" app into the path, along with the 
  16.              * concatenation of both apps' shared library lists. 
  17.              */  
  18.   
  19.             String instrumentationAppDir =  
  20.                     mActivityThread.mInstrumentationAppDir;  
  21.             String instrumentationAppPackage =  
  22.                     mActivityThread.mInstrumentationAppPackage;  
  23.             String instrumentedAppDir =  
  24.                     mActivityThread.mInstrumentedAppDir;  
  25.             String[] instrumentationLibs = null;  
  26.   
  27.             if (mAppDir.equals(instrumentationAppDir)  
  28.                     || mAppDir.equals(instrumentedAppDir)) {  
  29.                 zip = instrumentationAppDir + ":" + instrumentedAppDir;  
  30.                 if (! instrumentedAppDir.equals(instrumentationAppDir)) {  
  31.                     instrumentationLibs =  
  32.                         getLibrariesFor(instrumentationAppPackage);  
  33.                 }  
  34.             }  
  35.   
  36.             if ((mSharedLibraries != null) ||  
  37.                     (instrumentationLibs != null)) {  
  38.                 zip =  
  39.                     combineLibs(mSharedLibraries, instrumentationLibs)  
  40.                     + ':' + zip;  
  41.             }  
  42.   
  43.             /* 
  44.              * With all the combination done (if necessary, actually 
  45.              * create the class loader. 
  46.              */  
  47.   
  48.             if (ActivityThread.localLOGV)  
  49.                 Slog.v(ActivityThread.TAG, "Class path: " + zip + ", JNI path: " + mLibDir);  
  50.   
  51.             // Temporarily disable logging of disk reads on the Looper thread  
  52.             // as this is early and necessary.  
  53.             StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();  
  54.   
  55.             mClassLoader =  
  56.                 ApplicationLoaders.getDefault().getClassLoader(  
  57.                     zip, mLibDir, mBaseClassLoader);  
  58.             initializeJavaContextClassLoader();  
  59.   
  60.             StrictMode.setThreadPolicy(oldPolicy);  
  61.         } else {  
  62.             if (mBaseClassLoader == null) {  
  63.                 mClassLoader = ClassLoader.getSystemClassLoader();  
  64.             } else {  
  65.                 mClassLoader = mBaseClassLoader;  
  66.             }  
  67.         }  
  68.         return mClassLoader;  
  69.     }  
  70. }  
    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;
        }
    }
Java代码  收藏代码
  1. mClassLoader =  
  2.                    ApplicationLoaders.getDefault().getClassLoader(  
  3.                        zip, mLibDir, mBaseClassLoader);  
 mClassLoader =
                    ApplicationLoaders.getDefault().getClassLoader(
                        zip, mLibDir, mBaseClassLoader);
Java代码  收藏代码
  1.  /* 
  2.  * Copyright (C) 2006 The Android Open Source Project 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16.   
  17.   
  18. package android.app;  
  19.   
  20. import dalvik.system.PathClassLoader;  
  21.   
  22. import java.util.HashMap;  
  23. import java.util.Map;  
  24.   
  25. class ApplicationLoaders  
  26. {  
  27.     public static ApplicationLoaders getDefault()  
  28.     {  
  29.         return gApplicationLoaders;  
  30.     }  
  31.   
  32.     public ClassLoader getClassLoader(String zip, String libPath, ClassLoader parent)  
  33.     {  
  34.         /* 
  35.          * This is the parent we use if they pass "null" in.  In theory 
  36.          * this should be the "system" class loader; in practice we 
  37.          * don't use that and can happily (and more efficiently) use the 
  38.          * bootstrap class loader. 
  39.          */  
  40.         ClassLoader baseParent = ClassLoader.getSystemClassLoader().getParent();  
  41.   
  42.         synchronized (mLoaders) {  
  43.             if (parent == null) {  
  44.                 parent = baseParent;  
  45.             }  
  46.   
  47.             /* 
  48.              * If we're one step up from the base class loader, find 
  49.              * something in our cache.  Otherwise, we create a whole 
  50.              * new ClassLoader for the zip archive. 
  51.              */  
  52.             if (parent == baseParent) {  
  53.                 ClassLoader loader = mLoaders.get(zip);  
  54.                 if (loader != null) {  
  55.                     return loader;  
  56.                 }  
  57.       
  58.                 PathClassLoader pathClassloader =  
  59.                     new PathClassLoader(zip, libPath, parent);  
  60.                   
  61.                 mLoaders.put(zip, pathClassloader);  
  62.                 return pathClassloader;  
  63.             }  
  64.   
  65.             return new PathClassLoader(zip, parent);  
  66.         }  
  67.     }  
  68.   
  69.     private final Map<String, ClassLoader> mLoaders = new HashMap<String, ClassLoader>();  
  70.   
  71.     private static final ApplicationLoaders gApplicationLoaders  
  72.         = new ApplicationLoaders();  
  73. }  
 /*
 * 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。如下:

Java代码  收藏代码
  1. static void Dalvik_dalvik_system_VMStack_getCallingClassLoader(const u4* args,  
  2.     JValue* pResult)  
  3. {  
  4.     ClassObject* clazz =  
  5.         dvmGetCaller2Class(dvmThreadSelf()->interpSave.curFrame);  
  6.   
  7.     UNUSED_PARAMETER(args);  
  8.   
  9.     if (clazz == NULL)  
  10.         RETURN_PTR(NULL);  
  11.     RETURN_PTR(clazz->classLoader);  
  12. }  
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

Java代码  收藏代码
  1. native public static ClassLoader getCallingClassLoader();  
  native public static ClassLoader getCallingClassLoader();

 可以直接认为是加载当前类的classLoader。如果是BootClassLoader,那么就返回null

原文地址:https://www.cnblogs.com/seven1979/p/4369602.html