Android虚拟机与类加载机制
什么是Android虚拟机
Android虚拟机是为了在计算机上模拟Android系统环境,方便开发者开发和测试安卓应用程序的工具。目前Android系统所用的虚拟机主要是Dalvik和ART两种。
Dalvik虚拟机
Dalvik虚拟机是Google在Android系统中使用的Java虚拟机,它使用了一种叫做DEX的字节码文件格式。
在Android应用程序启动时,Dalvik虚拟机会按照Android的类加载机制,载入应用程序的主类,然后从该类开始解析和装载所有的类,构建出完整的类结构。在类解析和装载的过程中,Dalvik虚拟机会开辟出一个单独的内存空间,称作“堆(heap)”,用于存储所有的对象实例和数组。
类的装载过程主要分为:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)和初始化(Initialization)五个阶段。其中,验证和解析是Dalvik虚拟机独有的步骤。
ART虚拟机
ART虚拟机是在Android 5.0系统中引入的一种新的虚拟机,它使用了一种叫做ART的字节码文件格式。
和Dalvik虚拟机不同的是,ART在应用程序安装的时候就会把字节码文件预先编译为机器码,并保存到设备的存储空间中。这样,在应用程序启动时,ART直接加载机器码,而不需要在运行过程中再进行解释和编译。
这样一来,ART虚拟机虽然需要更多的存储空间,但是却可以在应用程序启动时更快地响应,并且由于避免了解释和编译字节码的过程,还可以减少应用程序运行时的功耗,从而延长设备的电池寿命。
类加载机制
Android应用程序中的类以及所有的依赖库都是通过类加载器进行加载的。
在Android系统中,类加载器主要有BootClassLoader、PathClassLoader、DexClassLoader、InMemoryDexClassLoader等几种。它们的主要区别在于它们所负责加载类的范围不同。
- BootClassLoader
BootClassLoader是Android系统中最高级别的类加载器,用于加载Android系统核心库(如Java核心类库、C标准库等)以及一些重要的类(如ClassLoader类、String类等)。
- PathClassLoader
PathClassLoader也是一个很重要的类加载器,它主要用于加载那些已经安装到设备中的应用程序及其依赖库。具体来说,当一个应用程序被安装到设备中时,它的apk文件会被解压,并在设备的存储空间中生成一个odex文件。在运行时,PathClassLoader会加载该应用程序的odex文件,并从中动态地解析和装载应用程序中的所有类。
- DexClassLoader
DexClassLoader是一个动态加载类的类加载器,它可以从设备文件系统或者网络中加载一个已经存在的dex文件,并根据dex文件中的内容动态地生成对应的类。
- InMemoryDexClassLoader
InMemoryDexClassLoader是一个加载内存中Dex文件的类加载器,它可以从内存中加载一个Dex文件,并动态地生成对应的类。和DexClassLoader类似,InMemoryDexClassLoader能够动态地加载dex文件中的类对象,但是它从内存中加载dex文件,从而避免了读写文件的性能消耗。
示例说明
下面我们来看一个示例,演示DexClassLoader的使用方法,加载设备文件系统中指定的已有dex文件。
public class MyActivity extends Activity {
private static final String DEX_PATH = "/sdcard/MyApp/classes.dex"; // dex文件的存放路径
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 创建DexClassLoader对象
DexClassLoader dexClassLoader = new DexClassLoader(DEX_PATH, // dex文件的路径
getDir("dex", Context.MODE_PRIVATE).getAbsolutePath(), // dex文件解包后存放的目录
null, // 父级类加载器,可以为null,此处没有父级类加载器
getClassLoader()); // 指定该类加载器作为父级类加载器,以便在加载类的时候优先使用该类加载器加载
try {
// 加载指定类
Class<?> cls = dexClassLoader.loadClass("com.example.MyClass");
// 创建类的实例
Object obj = cls.newInstance();
// 调用类的方法
Method method = cls.getMethod("helloWorld");
method.invoke(obj);
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
上述示例中,我们通过DexClassLoader来动态加载sdcard中的classes.dex文件,并且调用其中包含的指定方法。
另外,还可以使用PathClassLoader来加载设备存储中的指定类文件,下面是一个示例:
public class MyActivity extends Activity {
private static final String CLASS_FILE_PATH = "/sdcard/MyApp/MyClass.class"; // class文件的存放路径
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 创建PathClassLoader对象
PathClassLoader pathClassLoader = new PathClassLoader(CLASS_FILE_PATH, getClassLoader());
try {
// 加载指定类
Class<?> cls = pathClassLoader.loadClass("com.example.MyClass");
// 创建类的实例
Object obj = cls.newInstance();
// 调用类的方法
Method method = cls.getMethod("helloWorld");
method.invoke(obj);
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
上述示例中,我们通过PathClassLoader来动态加载设备存储中的MyClass.class文件,并且调用其中包含的指定方法。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Android虚拟机与类加载机制详情 - Python技术站