现在的位置: 首页 > 综合 > 正文

Android 启动加载jar包 init.rc BOOTCLASSPATH

2013年03月08日 ⁄ 综合 ⁄ 共 1704字 ⁄ 字号 评论关闭

转自:http://blog.csdn.net/tomken_zhang/article/details/6927423

一直在研究 Dalvik 的实现,今天突然想起一件事情,我们默认可以用 java.lang.Object 等系统类,他是在什么时候被加载进来了呢,我们自己的类是否可以这样预先加载进去呢?

 

顺着这个思路,再回顾一下原来对 Zygote 启动时的流程,探索一番!

 

Zygote 启动流程(网上有很多的分析不太详诉):

>>>  Kernel 启动

>>>  启动 init 程序,此程序解析 init.rc 进行执行

>>>  在 init.rc 中有启动 zygote 代码

>>>  zygote 启动后最后 fork 出 system_server 进行系统服务

>>>  zygote 等待 socket 事件准备孵化用户进程

 

在 Zygote 的启动中有如下关键调用:

AppRuntime.start 启动 com.android.internal.os.ZygoteInit 类处理

 

既然这时能够调用 java 类处理了,哪么系统基础类肯定在这之前准备好了,顺着这个向里面看

AppRuntime 继承 AndroidRuntime

AndroidRuntime 的 start 函数,调用了 JNI_CreateJavaVM 函数生成虚拟机

JNI_CreateJavaVM 是 jni.c 中,也就是 libdvm.so 中的一个函数

JNI_CreateJavaVM 中调用了 dvmStartup 函数启动一个虚拟机

dvmStartup 调用了setCommandLineDefaults 实现参数默认值。里面有最为重要的获取环境变理 BOOTCLASSPATH 方法。

回头看一下 init.rc 中

 

  1. export BOOTCLASSPATH /system/framework/core.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/android.policy.jar:/system/framework/services.jar:/system/framework/core-junit.jar  


原来是在这里指定了一些基础类的 jar 包

 

继续看代码

dvmStartup 中调用了 setCommandLineDefaults 设置默认  BOOTCLASSPATH

dvmStartup 中调用了dvmClassStartup 加载默认启动类

dvmClassStartup 中调用了 processClassPath 处理类路径,其实就是 BOOTCLASSPATH 中的值。

processClassPath 中建立结构体 ClassPathEntry 来存储一个路径信息

processClassPath 中调用了 prepareCpe 准备类路径节点

prepareCpe 中调用了dvmJarFileOpen 打开一个 jar 包

所有被加载的 Jar 包类都放到全局对像 gDvm.bootClassPath 中存储。

gDvm.bootClassPath 对像的结尾都是用一个特殊的结构体来表示的,这里是 kind = kCpeLastEntry 表示是最后一个类路径节点,因些不用另外一个变量表示大小。

 

大概清楚了!

 

-------------------------------------- 无聊的分割线 --------------------------------------

 

哪么我们想增加一个基础包给系统使用,大概有几种方法:

  1. 改 init.rc 的 BOOTCLASSPATH 环境变量初始值
  2. 在 zygote 启动前改动 BOOTCLASSPATH 环境变量
  3. 在 zygote 启动后想办法让他加载一个 jar 包

 

到此发现,系统启动前后环环相扣,并助实现的都是可扩展化,轻易不硬编码到代码中。

 

以后会继续深入研究一下其它东西的加载,比如:很有意思的一个 apk (ramework-res.apk)  这个包是系统皮肤实现的一个包

抱歉!评论已关闭.