`
daojin
  • 浏览: 697294 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

安卓高手之路之ClassLoader(总结篇)

阅读更多

安卓系统对ClassLoader的设计可谓别有用心。前面分析过,赋值的地方如下:

  const char* envStr = getenv("CLASSPATH");
    if (envStr != NULL) {
        gDvm.classPathStr = strdup(envStr);
    } else {
        gDvm.classPathStr = strdup(".");
    }
    envStr = getenv("BOOTCLASSPATH");
    if (envStr != NULL) {
        gDvm.bootClassPathStr = strdup(envStr);
    } else {
        gDvm.bootClassPathStr = strdup(".");
    }

 

分为三级: 

Boot      与BOOTCLASSPATH对应

System  与CLASSPATH对应。

App       与应用程序包对应。

在应用程序里面,Context控制着一个ClassLoader,通过建立不同的ClassLoader,对外界控制着对APK包的访问权限。

主要有如下几种:

 

    /**
     * Flag for use with {@link #createPackageContext}: include the application
     * code with the context.  This means loading code into the caller's
     * process, so that {@link #getClassLoader()} can be used to instantiate
     * the application's classes.  Setting this flags imposes security
     * restrictions on what application context you can access; if the
     * requested application can not be safely loaded into your process,
     * java.lang.SecurityException will be thrown.  If this flag is not set,
     * there will be no restrictions on the packages that can be loaded,
     * but {@link #getClassLoader} will always return the default system
     * class loader.
     */
    public static final int CONTEXT_INCLUDE_CODE = 0x00000001;

    /**
     * Flag for use with {@link #createPackageContext}: ignore any security
     * restrictions on the Context being requested, allowing it to always
     * be loaded.  For use with {@link #CONTEXT_INCLUDE_CODE} to allow code
     * to be loaded into a process even when it isn't safe to do so.  Use
     * with extreme care!
     */
    public static final int CONTEXT_IGNORE_SECURITY = 0x00000002;

    /**
     * Flag for use with {@link #createPackageContext}: a restricted context may
     * disable specific features. For instance, a View associated with a restricted
     * context would ignore particular XML attributes.
     */
    public static final int CONTEXT_RESTRICTED = 0x00000004;

 

 

1.ClassLoader如其名,就是加载class用的。 

2.一开始的时候,是通过dalvik/vm/Jni.cpp中的FindClass函数来找类的。

NativeStart是一个假类,里面的main是java堆栈的root。

第一。系统启动

因为这段代码是C++的代码,那么可以肯定一定是java(或者NativeStart这个假main函数)调用过来的。

具体谁调用过来的,这里做了个判断:

 

如果是NativeStart.main:

  这个时候要进行初始化判断,有可能vm还没有进行初始化。

如果是System.nativeload

   这个时候,就用classLoaderOverride

如果是其他:

   就是 thisMethod->clazz->classLoader 也就是 加载这段代码的classloader

分别进入了三个不同的分支。

 

static jclass FindClass(JNIEnv* env, const char* name) {
    ScopedJniThreadState ts(env);

    const Method* thisMethod = dvmGetCurrentJNIMethod();
    assert(thisMethod != NULL);

    Object* loader;
    Object* trackedLoader = NULL;
    if (ts.self()->classLoaderOverride != NULL) {
        /* hack for JNI_OnLoad */
        assert(strcmp(thisMethod->name, "nativeLoad") == 0);
        loader = ts.self()->classLoaderOverride;
    } else if (thisMethod == gDvm.methDalvikSystemNativeStart_main ||
               thisMethod == gDvm.methDalvikSystemNativeStart_run) {
        /* start point of invocation interface */
        if (!gDvm.initializing) {
            loader = trackedLoader = dvmGetSystemClassLoader();
        } else {
            loader = NULL;
        }
    } else {
        loader = thisMethod->clazz->classLoader;
    }

    char* descriptor = dvmNameToDescriptor(name);
    if (descriptor == NULL) {
        return NULL;
    }
    ClassObject* clazz = dvmFindClassNoInit(descriptor, loader);
    free(descriptor);

    jclass jclazz = (jclass) addLocalReference(ts.self(), (Object*) clazz);
    dvmReleaseTrackedAlloc(trackedLoader, ts.self());
    return jclazz;
}

   这种classLoade是BootClassLoader.

 

第二 app启动。

         app启动 通过socket完成。通过fork来创建一个子进程。这个时候ClassLoader是与Context有关的。

不同的Context对应不同的ClassLoader。这个ClassLoader是一个PathClassLoader

       

  @Override
    public ClassLoader getClassLoader() {
        return mPackageInfo != null ?
                mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader();
    }

 

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.getSystemClassLoader() 返回的是一个PathClassLoader,而

ClassLoader.getSystemClassLoader().getParent() 返回的是一个BootClassLoader。

 如果LoadedApk这个类在构造的时候,传入了个BootClassLoader或者null,那么就会执行
                PathClassLoader pathClassloader =
                    new PathClassLoader(zip, libPath, parent);
               
                mLoaders.put(zip, pathClassloader);
                return pathClassloader;
也就是说 把libPath进行了传入。

 

否则用如下构造函数执行

                    return new PathClassLoader(zip, parent);
可以看到,少了一个参数libPath,libPath是libjni。那么这个是什么意思呢?

 

经过看代码,默认LoadedAPK传入的loader是个null, 因此,会使用libPath进行构造。并且它的父Loader是BootClassLoader。那么什么时候传入的loader不是nul呢。用instrument的时候传入的不是null。

 

分享到:
评论

相关推荐

    Java ClassLoader学习总结

    Java ClassLoader学习总结 Java 类加载机制是 Java 中一个非常重要的机制,它负责加载 Class 文件到 JVM,以供程序使用。ClassLoader 是 Java 中的一个抽象类,它的主要作用是加载 Class 文件到 JVM 中。...

    ClassLoader总结

    在Java编程语言中,ClassLoader是核心组件之一,它负责加载类到JVM(Java虚拟机)中执行。这篇博文深入探讨了ClassLoader的工作原理及其在实际应用中的重要性。以下是ClassLoader的相关知识点: 1. 类加载机制: ...

    classloader

    这篇文章将深入探讨Android中的类加载器如何实现动态加载其他工程类的过程。 首先,我们需要了解类加载器的基本概念。在Java中,类加载器负责把字节码文件(.class文件)转换为运行时的Class对象。这个过程包括加载...

    Android Classloader测试demo

    在Android系统中,Classloader(类加载器)是至关重要的组件,它负责查找并加载Java类到Dalvik或ART运行时环境。这个测试demo是为了帮助开发者深入理解Android中两种主要的类加载器:DexClassLoader和...

    Java ClassLoader定制实例

    本篇文章将深入探讨Java ClassLoader的内部工作,并通过一个具体的实例来展示如何定制自己的ClassLoader。 首先,我们来看ClassLoader的基本工作流程。当JVM启动时,它会有一个初始的Bootstrap ClassLoader,用于...

    ClassLoader

    #### 六、Android中的ClassLoader 在Android环境中,主要使用的`ClassLoader`有`PathClassLoader`和`DexClassLoader`。 1. **`PathClassLoader`**: - 继承自`BaseDexClassLoader`。 - 主要用于应用程序本身的类...

    安卓原生热更新 classloader

    总结来说,安卓原生热更新是通过动态替换`ClassLoader`来加载新的`.dex`文件,进而实现应用的热更新。这一过程涉及到应用的编译、传输、存储以及运行时的类加载机制。理解并熟练掌握这些步骤,开发者能够在不打扰...

    classloader 总结

    这篇博文主要总结了关于Java类加载器的一些核心概念、工作原理以及常见应用场景。 1. 类加载器层次结构 Java类加载器形成了一个树形的层次结构,其中Bootstrap ClassLoader(引导类加载器)位于顶层,负责加载JRE...

    自定义classloader的使用

    在Java中,Classloader是加载类的关键组件,它负责查找、加载和初始化字节码文件。自定义Classloader允许开发者根据特定需求定制类的加载逻辑,例如加密类文件、隔离不同版本的库或者动态加载代码。本文将深入探讨...

    ClassLoader小例子

    在Java编程语言中,ClassLoader是一个至关重要的组成部分,它负责加载类到JVM(Java虚拟机)中,使得程序能够执行。本示例"ClassLoader小例子"将深入探讨这个概念,并通过一个具体的程序来演示其工作原理。下面我们...

    ClassLoader运行机制 自己写的

    在Java虚拟机(JVM)中,类加载器(ClassLoader)是至关重要的组成部分,它负责查找和加载类的字节码文件。理解ClassLoader的工作机制对于深入掌握Java应用程序的运行至关重要。这里我们将详细讨论ClassLoader的运行...

    java ClassLoader机制及其在OSGi中的应用

    总结来说,Java ClassLoader机制是Java平台的基础,它使得程序能够动态地加载和管理类。而在OSGi这样的模块化环境中,ClassLoader机制得到了进一步的发展,实现了更加精细的类加载控制和更好的模块隔离。理解并掌握...

    深入理解ClassLoader工作机制.docx

    《深入理解ClassLoader工作机制》 Java虚拟机(JVM)中的ClassLoader是负责加载类到内存中的核心组件。它不仅承担着将字节码转换为可执行对象的重任,还参与了类生命周期的各个阶段,包括加载、验证、准备、解析、...

    JVM ClassLoader简析

    首先,ClassLoader可以分为三种基本类型:Bootstrap ClassLoader、Extension ClassLoader和Application ClassLoader。Bootstrap ClassLoader是JVM启动时的第一个ClassLoader,负责加载JDK的`&lt;JAVA_HOME&gt;\lib`目录下...

    Android 使用classloader原理进行热更新

    热更新通常依赖于类加载器(Classloader)的工作原理来实现,本篇文章将深入探讨如何利用Android的类加载器实现热更新的机制。 首先,我们需要理解什么是类加载器。在Java和Android中,类加载器是负责查找、加载和...

    ClassLoader 案例

    在Java编程语言中,ClassLoader是核心组件之一,它负责加载类到JVM(Java虚拟机)中。自定义ClassLoader允许开发者根据特定需求加载类,比如动态加载或更新类文件,这在某些高级应用场景中非常有用,如插件系统、热...

    理解Java ClassLoader机制

    Java ClassLoader机制是Java运行时环境中的核心组件之一,它负责加载类到JVM(Java虚拟机)中,使得程序能够执行。理解ClassLoader的工作原理对于优化应用性能、处理类加载问题以及实现自定义加载器至关重要。 首先...

Global site tag (gtag.js) - Google Analytics