Android中文API(140) —— DexFile

本文详细介绍了Android系统中用于操作DEX文件的DexFile类,包括其构造函数、方法和作用机制。重点阐述了如何通过指定文件打开DEX文件,以及类的加载与关闭流程。此外,还讨论了DexFile类如何在虚拟机内部工作,以及其与类装载器的关系。最后,提供了实用示例和相关资源链接,以助于开发者深入理解并运用这一核心概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

前言

  本章内容dalvik.system.DexFile章节,版本为Android 4.0 r1,翻译来自:"阿年",欢迎访问他的博客:"http://blog.youkuaiyun.com/mtding",再次感谢"阿年" !期待你一起参与翻译Android的相关资料,联系我over140@gmail.com。

 

声明

  欢迎转载,但请保留文章原始出处:) 

    博客园:http://www.cnblogs.com/

    Android中文翻译组: http://androidbox.sinaapp.com/

 

 

DexFile

译者署名:阿年

译者链接:http://blog.youkuaiyun.com/mtding

版本:Android 4.0 r1

 

结构

继承关系

public final class DexFile extends Object

        

java.lang.Object

dalvik.system.DexFile

 

类概述

操作DEX文件。这个类原理上和ZipFile相似。主要在类装载器里被使用。

注意,我们不直接打开和读取DEX文件。它们被虚拟机以只读方式映射到内存了。

 

构造函数

public DexFile (File file)

通过指定的File对象打开DEX文件。指定的文件通常是一个ZIP/JAR文件,里面包含一个”classes.dex”。虚拟机将在目录/data/dalvik-cache下生成对应的文件名字并打开它,如果系统权限允许的话会首先创建或更新它。不要传目录/data/dalvik-cache下的文件名给它,因为这个文件被认为处于初始状态(DEX被优化之前)。

参数

File            引用实际DEX文件的File对象

异常

IOException 发生I/O异常,例如文件不存在或者没有权限访问。

 

public DexFile (String fileName)

打开指定文件名的DEX文件。指定的文件通常是一个ZIP/JAR文件,里面包含一个”classes.dex”。虚拟机将在目录/data/dalvik-cache下生成对应的文件名字并打开它,如果系统权限允许的话会首先创建或更新它。不要传目录/data/dalvik-cache下的文件名给它,因为这个文件被认为处于初始状态(DEX被优化之前)。

参数

fileName           DEX文件名。

异常

IOException     发生I/O异常,例如文件不存在或者没有权限访问。

        

公共方法

public void close ()

关闭DEX文件。

有可能无法释放任何资源。如果来自DEX文件的类还存活着的话,DEX文件不能被取消映射。

异常

IOException     在关闭文件的过程中可能发生I/O异常,一般不会发生。

        

public Enumeration<String> entries ()

枚举DEX文件里面的类名。

返回值

DEX文件所包含类名的枚举,类名的类型是一般内部格式(像java/lang/String)。

        

public String getName ()

获取(已打开)DEX文件名。

返回值

文件名

 

public static boolean isDexOptNeeded (String fileName)

如果虚拟机认为apk/jar文件已经过期返回true,并且应该再次通过”dexopt”传递。(译者注:dexoptapk优化工具)

参数

fileName 被检查apk/jar文件的绝对路径名。

返回值

如果应该调用dexopt处理文件返回true;否则false

异常

FileNotFoundException    文件不可读、不是一个文件或者文件不存在。

IOException     fileName不是有效的apk/jar文件,或者在解析文件时出现问题。

NullPointerException       fileName是空的。

StaleDexCacheError         优化过的DEX文件已过期且位于只读分区。

 

public Class loadClass (String name, ClassLoader loader)

装载一个类。返回成功装载的类,失败返回空。

如果在类装载器之外调用它,往往不会得到你想要的结果,这时请使用forName(String)

该方法不会在找不到类的时候抛出ClassNotFoundException异常,因为每次在我们看到的第一个DEX文件里找不到类就粗暴地抛出异常是不合理的。

参数

name        类名,应该是一个"java/lang/String"

loader       试图装载类的类装载器(大多数情况下就是该方法的调用者)

返回值

类名对应的对象,装载失败时返回空。

        

public static DexFile loadDex (String sourcePathName, String outputPathName, int flags)

打开一个DEX文件,并提供一个文件来保存优化过的DEX数据。如果优化过的格式已存在并且是最新的,就直接使用它。如果不是,虚拟机将试图重新创建一个。该方法主要用于应用希望在通常的应用安装机制之外下载和执行DEX文件。不能在应用里直接调用该方法,而应该通过一个类装载器例如dalvik.system.DexClassLoader.

参数

sourcePathName     包含”classes.dex”Jar或者APK文件。(将来可能会扩展支持"raw DEX")

outputPathName     保存优化过的DEX数据的文件。

flags        打开可选功能(目前什么也没定义)

返回值

一个新的,或者先前已经打开的DexFile

异常

IOException     无法打开输入或输出文件。

 

受保护方法

protected void finalize ()

类结束时调用。确保DEX文件被关闭。

异常

IOException 关闭文件时发生I/O异常,一般不会发生。

 

补充

         文章精选

                   Dalvik 分析 - Class加载篇

                   启用另一个程序某些方法

                   Android类动态加载技术

<think>嗯,我需要回答用户的问题:Android打包过程中,API对应的JAR包是否会自动被打包进APK文件中?先梳理下用户的问题核心。用户看到三个引用文档:引用[1]讲Buildozer打包流程,引用[2]展示aapt打包命令,引用[3]涉及ProGuard配置。但其实用户真正想问的是编译时依赖的AndroidSDK中的JAR包(比如android.jar)会不会进入最终APK。这里的关键在于区分编译依赖和运行时依赖。回顾Android打包机制:android.jar在编译阶段提供API引用(比如Activity.class),但实际设备上已有这些类在系统框架层。所以打包时Gradle/AndroidStudio会自动排除它,避免APK冗余。这点可以从引用[2][3]侧面印证——它们提到的android.jar都是作为编译依赖路径,而非打包对象。用户可能存在的误区是认为所有JAR都会打进APK。需要澄清两点:一是android.jar仅在编译时有效;二是开发者自定义的第三方JAR(如Gson.jar)会被打包。可以举例说明差异。最后要提醒检查方法。用户可能想验证结论,可以建议解压APK查看lib/和classes.dex,或者用build.gradle配置观察打包日志。这样回答会更实用。</think> 在Android打包过程中,API相关的JAR包(如`android.jar`)**不会被打包进最终APK文件**,这是由Android打包机制的本质决定的: ### 核心原理 1. **编译期依赖** `android.jar`在编译阶段提供Android框架API的引用(如`Activity`、`View`等),但仅包含**方法签名和空实现**(Stub),不含真实代码[^2][^3]。 2. **运行时行为** 设备系统已内置相同的API实现(位于`/system/framework/`)。打包工具会自动排除`android.jar`,避免冗余占用空间。真实调用会动态链接到设备上的系统库[^2]。 3. **验证方法** 解压APK后可见: - `/lib/`目录:仅含第三方原生库(.so文件) - `/dex/`文件:包含应用自身代码 - **无`android.jar`踪迹** ### 对比说明 | **JAR包类型** | 是否打包进APK | 原因 | |----------------------|---------------|--------------------------| | `android.jar`(SDK) | ❌ 否 | 由设备系统提供 | | 第三方库(如Gson.jar)| ✅ 是 | 需随应用部署 | ### 技术验证 通过构建日志可观察排除过程: ```gradle // build.gradle配置查看依赖树 dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) compileOnly files('path/to/android.jar') // 标记仅编译使用 } ``` 运行`./gradlew app:dependencies`可见`android.jar`被标记为`compileOnly`,不会进入APK[^3]。 ### 总结 Android打包时,**SDK中的API相关JAR包不会进入APK**。开发者只需确保: 1. 正确声明第三方库依赖(`implementation`) 2. 目标设备API级别 ≥ 应用最低要求版本 这种做法既避免了APK体积膨胀,也保证了运行时调用设备原生API的高效性[^1][^2][^3]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值