DexClassLoder解析

Android类装载器DexClassLoader的简单使用

DexClassLoader 可以加载外部的 apk、jar 或 dex文件,

在java中,有个概念叫做“类加载器”(ClassLoader),它的作用就是动态的装载Class文件。

1. ClassLoader 的基础知识

ClassLoader主要对类的请求提供服务,当JVM需要某类时,它根据名称向ClassLoader要求这个类,然后由ClassLoader返回这个类的class对象。

无论是 JVM 还是 Dalvik 都是通过 ClassLoader 去加载所需要的类,而 ClassLoader 加载类的方式常称为双亲委托,

JVM 及 Dalvik 对类唯一的识别是 ClassLoader id + PackageName + ClassName,

2.Android平台的ClassLoader

Android中类加载器有BootClassLoader,URLClassLoader,
PathClassLoader,DexClassLoader,BaseDexClassLoader,等都最终继承自java.lang.ClassLoader。
image

1.java.lang.ClassLoader是所有ClassLoader的最终父类。
2.BootClassLoader
和java虚拟机中不同的是BootClassLoader是ClassLoader内部类,由java代码实现而不是c++实现,是Android平台上所有ClassLoader的最终parent,这个内部类是包内可见,所以我们没法使用。
3.URLClassLoader
只能用于加载jar文件,但是由于 dalvik 不能直接识别jar,所以在 Android 中无法使用这个加载器。
4.BaseDexClassLoader
PathClassLoader和DexClassLoader都继承自BaseDexClassLoader,其中的主要逻辑都是在BaseDexClassLoader完成的。这些源码在java/dalvik/system中。

BaseDexClassLoader的构造函数包含四个参数,分别为:
dexPath,指目标类所在的APK或jar文件的路径,类装载器将从该路径中寻找指定的目标类,该类必须是APK或jar的全路径.如果要包含多个路径,路径之间必须使用特定的分割符分隔,特定的分割符可以使用System.getProperty(“path.separtor”)获得。上面”支持加载APK、DEX和JAR,也可以从SD卡进行加载”指的就是这个路径,最终做的是将dexPath路径上的文件ODEX优化到内部位置optimizedDirectory,然后,再进行加载的。

File optimizedDirectory,由于dex文件被包含在APK或者Jar文件中,因此在装载目标类之前需要先从APK或Jar文件中解压出dex文件,该参数就是制定解压出的dex 文件存放的路径。这也是对apk中dex根据平台进行ODEX优化的过程。其实APK是一个程序压缩包,里面包含dex文件,ODEX优化就是把包里面的执行程序提取出来,就变成ODEX文件,因为你提取出来了,系统第一次启动的时候就不用去解压程序压缩包的程序,少了一个解压的过程。这样的话系统启动就加快了。为什么说是第一次呢?是因为DEX版本的也只有第一次会解压执行程序到 /data/dalvik-cache(针对PathClassLoader)或者optimizedDirectory(针对DexClassLoader)目录,之后也是直接读取目录下的的dex文件,所以第二次启动就和正常的差不多了。当然这只是简单的理解,实际生成的ODEX还有一定的优化作用。ClassLoader只能加载内部存储路径中的dex文件,所以这个路径必须为内部路径。

libPath,指目标类中所使用的C/C++库存放的路径

classload,是指该装载器的父装载器,一般为当前执行类的装载器,例如在Android中以context.getClassLoader()作为父装载器。

5.DexClassLoader
image

DexClassLoader支持加载APK、DEX和JAR,也可以从SD卡进行加载。
上面说dalvik不能直接识别jar,DexClassLoader却可以加载jar文件,这难道不矛盾吗?其实在BaseDexClassLoader里对”.jar”,”.zip”,”.apk”,”.dex”后缀的文件最后都会生成一个对应的dex文件,所以最终处理的还是dex文件,而URLClassLoader并没有做类似的处理。
一般我们都是用这个DexClassLoader来作为动态加载的加载器。

6.PathClassLoader

image

PathClassLoader没有将optimizedDirectory置为Null,也就是没设置优化后的存放路径。其实optimizedDirectory为null时的默认路径就是/data/dalvik-cache 目录。
PathClassLoader是用来加载Android系统类和应用的类,并且不建议开发者使用。
很多博客里说PathClassLoader只能加载已安装的apk的dex,其实这说的应该是在dalvik虚拟机上,在art虚拟机上PathClassLoader可以加载未安装的apk的dex(在art平台上已验证),然而在/data/dalvik-cache 确未找到相应的dex文件,怀疑是art虚拟机判断apk未安装,所以只是将apk优化后的odex放在内存中,之后进行释放,这只是个猜想,希望有知道的可以告知一下。因为dalvik上无法使用,所以我们也没法使用。

ClassLoder源码:

1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17/*
18 * Copyright (C) 2008 The Android Open Source Project
19 *
20 * Licensed under the Apache License, Version 2.0 (the "License");
21 * you may not use this file except in compliance with the License.
22 * You may obtain a copy of the License at
23 *
24 * http://www.apache.org/licenses/LICENSE-2.0
25 *
26 * Unless required by applicable law or agreed to in writing, software
27 * distributed under the License is distributed on an "AS IS" BASIS,
28 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29 * See the License for the specific language governing permissions and
30 * limitations under the License.
31 */
32
33package java.lang;
34
35import dalvik.system.PathClassLoader;
36import java.io.IOException;
37import java.io.InputStream;
38import java.net.URL;
39import java.nio.ByteBuffer;
40import java.security.ProtectionDomain;
41import java.util.Collection;
42import java.util.Collections;
43import java.util.Enumeration;
44import java.util.HashMap;
45import java.util.Map;
46import java.util.Set;
47
48/**
49 * Loads classes and resources from a repository. One or more class loaders are       
50 * installed at runtime. These are consulted whenever the runtime system needs a
51 * specific class that is not yet available in-memory. Typically, class loaders
52 * are grouped into a tree where child class loaders delegate all requests to
53 * parent class loaders. Only if the parent class loader cannot satisfy the
54 * request, the child class loader itself tries to handle it.
55 * <p>
56 * {@code ClassLoader} is an abstract class that implements the common
57 * infrastructure required by all class loaders. Android provides several
58 * concrete implementations of the class, with
59 * {@link dalvik.system.PathClassLoader} being the one typically used. Other
60 * applications may implement subclasses of {@code ClassLoader} to provide
61 * special ways for loading classes.
62 * </p>
63 * @see Class
64 */
    /*从一个仓库中加载资源文件或者类,许多类加载器通常在运行时被安装,子类加载器将所有请求委托给父类装载器,只有当父类装载器不能满足处理请求时,子装载器会尝试处理
65public abstract class ClassLoader {
66
67    /**
68     * The 'System' ClassLoader - the one that is responsible for loading
69     * classes from the classpath. It is not equal to the bootstrap class loader -
70     * that one handles the built-in classes.
71     *
72     * Because of a potential class initialization race between ClassLoader and
73     * java.lang.System, reproducible when using JDWP with "suspend=y", we defer
74     * creation of the system class loader until first use. We use a static
75     * inner class to get synchronization at init time without having to sync on
76     * every access.
77     *
78     * @see #getSystemClassLoader()
79     */
        /*系统加载类,不同于启动加载类,它负责从类路径加载类,第一次使用时初始化
80    static private class SystemClassLoader {
81        public static ClassLoader loader = ClassLoader.createSystemClassLoader();
82    }
83
84    /**
85     * The parent ClassLoader.
86     */
87    private ClassLoader parent;
88
89    /**
90     * The packages known to the class loader.
91     */
92    private Map<String, Package> packages = new HashMap<String, Package>();
93
94    /**
95     * To avoid unloading individual classes, {@link java.lang.reflect.Proxy}
96     * only generates one class for each set of interfaces. This maps sets of
97     * interfaces to the proxy class that implements all of them. It is declared
98     * here so that these generated classes can be unloaded with their class
99     * loader.
100     *
101     * @hide
102     */
103    public final Map<Set<Class<?>>, Class<?>> proxyCache
104            = Collections.synchronizedMap(new HashMap<Set<Class<?>>, Class<?>>());
105
106    /**
107     * Create the system class loader. Note this is NOT the bootstrap class
108     * loader (which is managed by the VM). We use a null value for the parent
109     * to indicate that the bootstrap loader is our parent.
110     */
111    private static ClassLoader createSystemClassLoader() {
112        String classPath = System.getProperty("java.class.path", ".");
113
114        // String[] paths = classPath.split(":");
115        // URL[] urls = new URL[paths.length];
116        // for (int i = 0; i < paths.length; i++) {
   
117        // try {
   
118        // urls[i] = new URL("file://" + paths[i]);
119        // }
120        // catch (Exception ex) {
   
121        // ex.printStackTrace();
122        // }
123        // }
124        //
125        // return new java.net.URLClassLoader(urls, null);
126
127        // TODO Make this a java.net.URLClassLoader once we have those?
128        return new PathClassLoader(classPath, BootClassLoader.getInstance());
129    }
130
131    /**
132     * Returns the system class loader. This is the parent for new
133     * {@code ClassLoader} instances and is typically the class loader used to
134     * start the application.
135     */
136    public static ClassLoader getSystemClassLoader() {
137        return SystemClassLoader.loader;
138    }
139
140    /**
141     * Finds the URL of the resource with the specified name. The system class
142     * loader's resource lookup algorithm is used to find the resource.
143     *
144     * @return the {@code URL} object for the requested resource or {@code null}
145     *         if the resource can not be found.
146     * @param resName
147     *            the name of the resource to find.
148     * @see
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值