Dalvik切换到ART时内存地址对齐问题的分析(1)

AVD启动时打印详细日志信息需要取消 art/runtime/runtime.cc 文件中的374至384行(gLogVerbosity...)的注释。

在之前追踪的函数调用过程中,在文件 art/compiler/driver/compiler_driver.cc 中函数 void CompilerDriver::InitializeClasses(...) 内添加打印dex文件的总数及当前正在初始化第几个dex文件的信息:
2217 ALOGD ("dex_files.size:%d",(int)dex_files.size()); //dex文件的总数
2218 for (size_t i = 0; i != dex_files.size(); ++i) {
2219 const DexFile* dex_file = dex_files[i];
2220 CHECK (dex_file != NULL);
2221 ALOGD ("-27\ti:%d\tLineNum:%d\tFuncName:%s\tFileName:%s",(int)i,__LINE__,__FUNCTION__,__FILE__);//当前正在初始化第 i 个dex文件
2222 InitializeClasses(class_loader, *dex_file, thread_pool, timings);
打印结果:
dex_file.size:15
.......
-27 i:6 LineNum:2221 FuncName:InitializeClasses FileName:art/compiler/driver/compiler_driver.cc
则共有15个dex文件,与启动日志中GenerateImage: /system/bin/dex2oat...这一行中的参数 --dex-file 的个数一致。
根据启动日志可知,出错时正在初始化第6个dex文件(从0开始),可知是初始化第六个--dex-file 参数 --dex-file=/system/framework/framework.jar 指定的jar包时出错。

在文件 art/compiler/driver/compiler_driver.cc 中函数 static void InitializeClass(...) 内添加打印当前正在加载的类的信息:
2121 if(4993 (int)class_def_index) //先用ALOGD打印出来class_def_index的值就是4993,用if语句只是为了方便打印日志。
2122 { 
2123 ALOGD ( "\ndescriptor:%s" , descriptor ); //类描述符descriptor表示类class_def的名字
2124 ALOGD ( "class_def_index:%d\tclass_idx_:%d\n" , class_def_index,class_def.class_idx_ ); //class_def_index表示类class_def在类资源区的索引号,class_idx_ 表示类的类型在类型资源区的索引
2125 }

打印结果:

descriptor:Landroid/widget/OverScroller$SplineOverScroller;
class_def_index:4993 class_idx_:4983
发现是在加载类android/widget/OverScroller$SplineOverScroller时出错。

继续在文件 art/runtime/class_linker.cc 中函数 bool ClassLinker::InitializeClass(...) 内的函数 klass->FindDeclaredDirectMethod("<clinit>", "()V") 中(位于文件runtime/mirror/class.cc中)添加打印类加载过程中当前正在执行的方法及其所属的java源文件名和类的信息:
379 if (name mh.GetName() && signature == mh.GetSignature()) {
380 ALOGD ( "i:%d\tname:%s\tnameasstring:%s",i,mh.GetName() ,(char *)(mh.GetNameAsString())); //name表示方法名
381 ALOGD ( "sourcefile:%s\nclassdescriptor:%s\n",mh.GetDeclaringClassSourceFile() , mh.GetDeclaringClassDescriptor());//方法所在的java源文件及所在类
382 return method;
383 } 
打印结果:
i:0 name:<clinit> nameasstring:<90><84>ðp
sourcefile:OverScroller.java
classdescriptor:Landroid/widget/OverScroller$SplineOverScroller;
发现方法clinit(类初始化方法)对应于java源文件 frameworks/base/core/java/android/widget/OverScroller.java 中静态类static class SplineOverScroller的初始化。
OverScroller.java对应的.class文件在 out/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/classes/android/widget下,对.class文件用javap -c -p OverScroller$SplineOverScroller反汇编发现生成的文件中没有静态类static class SplineOverScroller对应的java字节码。

经分析,内存地址对齐问题是Zygote进程启动时在加载framework层的类和资源的过程中,执行 dex2oat 时将 OverScroller$SplineOverScroller.class 所对应的jar包 /system/framework/framework.jar 编译成oat文件时出现问题。
对framework.jar文件用dexdump -d framework.jar > framework.txt 反汇编,在 framework.txt 中搜索 "Class #4993" ,即为类 android/widget/OverScroller$SplineOverScroller 对应的dalvik字节码。在其下边的 “Direct Methods" 中找到方法 "<clinit>" 对应的dalvik字节码,在其中可以找到 "div-double/2addr" 这条指令。

JAVA相关知识:
JAVA的静态变量、静态方法、静态类: http://blog.csdn.net/zhandoushi1982/article/details/8453522
JVM指令详解(上): http://blog.csdn.net/hudashi/article/details/7062675
JVM指令详解(下): http://blog.csdn.net/hudashi/article/details/7062781
javap(反汇编命令)详解: http://blog.csdn.net/hudashi/article/details/7062668
<init>与<clinit>的区别: http://blog.csdn.net/sunmenggmail/article/details/10211395
java编译生成字节码产生 <init>()与<clinit>()的方法疑问: http://hllvm.group.iteye.com/group/topic/35224


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值