Dalvik虚拟机java方法执行流程和Method结构体分析
Method结构体是啥?
在Dalvik虚拟机内部,每个Java方法都有一个对应的Method结构体,虚拟机根据此结构体获取方法的所有信息.
Method结构体是怎样定义的?
此结构体在不同的android版本稍有变化,但是结构体前面比较重要的一部分(从clazz到nativeFunc)完全没有变化.以下是android4.4.2_r2的Method结构体定义(位于/dalvik/vm/oo/Object.h).
/*
* A method. We create one of these for every method in every class
* we load, so try to keep the size to a minimum.
*
* Much of this comes from and could be accessed in the data held in shared
* memory. We hold it all together here for speed. Everything but the
* pointers could be held in a shared table generated by the optimizer;
* if we're willing to convert them to offsets and take the performance
* hit (e.g. "meth->insns" becomes "baseAddr + meth->insnsOffset") we
* could move everything but "nativeFunc".
*/
struct Method {
/* the class we are a part of */
ClassObject*clazz; /* access flags; low 16 bits are defined by spec (could be u2?) */
u4 accessFlags; /*
* For concrete virtual methods, this is the offset of the method
* in "vtable".
*
* For abstract methods in an interface class, this is the offset
* of the method in "iftable[n]->methodIndexArray".
*/
u2 methodIndex; /*
* Method bounds; not needed for an abstract method.
*
* For a native method, we compute the size of the argument list, and
* set "insSize" and "registerSize" equal to it.
*/
u2 registersSize; /* ins + locals */
u2 outsSize;
u2 insSize; /* method name, e.g. "<init>" or "eatLunch" */
const char* name; /*
* Method prototype descriptor string (return and argument types).
*
* TODO: This currently must specify the DexFile as well as the proto_ids
* index, because generated Proxy classes don't have a DexFile. We can
* remove the DexFile* and reduce the size of this struct if we generate
* a DEX for proxies.
*/
DexProtoprototype; /* short-form method descriptor string */
const char* shorty; /*
* The remaining items are not used for abstract or native methods.
* (JNI is currently hijacking "insns" as a function pointer, set
* after the first call. For internal-native this stays null.)
*/ /* the actual code */
const u2* insns; /* instructions, in memory-mapped .dex */ /* JNI: cached argument and return-type hints */
int jniArgInfo; /*
* JNI: native method ptr; could be actual function or a JNI bridge. We
* don't currently discriminate between DalvikBridgeFunc and
* DalvikNativeFunc; the former takes an argument superset (i.e. two
* extra args) which will be ignored. If necessary we can use
* insns==NULL to detect JNI bridge vs. internal native.
*/
DalvikBridgeFunc nativeFunc; /*
* JNI: true if this static non-synchronized native method (that has no
* reference arguments) needs a JNIEnv* and jclass/jobject. Libcore
* uses this.
*/
bool fastJni; /*
* JNI: true if this method has no reference arguments. This lets the JNI
* bridge avoid scanning the shorty for direct pointers that need to be
* converted to local references.
*
* TODO: replace this with a list of indexes of the reference arguments.
*/
bool noRef; /*
* JNI: true if we should log entry and exit. This is the only way
* developers can log the local references that are passed into their code.
* Used for debugging JNI problems in third-party code.
*/
bool shouldTrace; /*
* Register map data, if available. This will point into the DEX file
* if the data was computed during pre-verification, or into the
* linear alloc area if not.
*/
const RegisterMap* registerMap; /* set if method was called during method profiling */
boolinProfile;
};
struct Method {
ClassObject* clazz;
u4 accessFlags;
u2 methodIndex;
u2 registersSize;
u2 outsSize;
u2 insSize;
const char* name;
DexProto prototype;
const char* shorty;
const u2* insns;
int jniArgInfo;
DalvikBridgeFunc nativeFunc;
bool fastJni;
bool noRef;
bool shouldTrace;
const RegisterMap* registerMap;
bool inProfile;
};
第二个图更容易看
native层的两种引用对象类型
一种是普通的JNI方式,特点是引用对象类型为jobject等样式.第二种就是Dalvik虚拟机内部使用的引用对象类型(Object*,ClassObject*等样式).在虚拟机内部有若干个表存储jobject与Object*的对应关系,因此两者在虚拟机内部可以相互转换.
Dalvik虚拟机眼中的java方法分类
在Dalvik虚拟机看来,java方法分为三类:
1.普通的java方法,即由java代码实现的方法.
2.通过JNI函数实现的native方法,典型的是声明为native的方法.特点是输入参数中的引用对象类型为jobject类型.
3.虚拟机内部实现的native方法.特点是输入参数中的引用对象类型为Object*,ClassObject*等类型.
Dalvik虚拟机是如何执行一个方法的?
以dvmCallMethod为例,其主要执行流程如下图
结论:Method结构体重要成员的意义
结合以上Dalvik虚拟机方法执行流程和对Android源码的分析,得到Method结构体中几个重要成员的意义如下
accessFlags 各个不同标志位表示此方法的多个属性,其中标志位0x00000100表明此方法是native的.
registersSize 该方法总共用到的寄存器个数,包含输入参数所用到的寄存器,还有方法内部另外使用到的寄存器,在调用方法时会为其申请栈内存.
outsSize 该方法调用其他方法时使用到的寄存器个数,注意:只有此方法为非native方法时,此值才有效.
insSize 该方法输入参数用到的寄存器个数(registersSize包含此值)
insns 若方法类型为1,这里指向实际的字节码首地址;若方法类型为2,这里指向实际的JNI函数首地址;若方法类型为3,这里为null.
jniArgInfo 当方法类型为2时有效,记录了一些预先计算好的信息(具体信息格式与实际CPU架构有关,但总是包含返回值类型),从而不需要在调用的时候再通过方法的参数和返回值实时计算了,提高了JNI调用的速度。如果第一位为1(即0x80000000),则Dalvik虚拟机会忽略后面的所有信息,强制在调用时实时计算.
nativeFunc 若方法类型为1,此值无效;若方法类型为2,这里指向dvmCallJNIMethod;若方法类型为3,这里指向实际的处理函数(DalvikBridgeFunc类型).
附录:其余执行方法的函数
void dvmCallMethodA(Thread* self, const Method* method, Object* obj, bool fromJni, JValue* pResult, const jvalue* args) 功能与dvmCallMethodV类似,只是参数格式不同而已.
Object* dvmInvokeMethod(Object* obj, const Method* method, ArrayObject* argList, ArrayObject* params, ClassObject* returnType, bool noAccessCheck) 特点在于会根据method的实际输入参数类型argList将输入参数params中的包装类型解包为实际需要的基本类型,并且如果实际返回类型为基本类型它会将结果打包为对应的包装类型返回
void dvmCallJNIMethod(const u4* args, JValue* pResult, const Method* method, Thread* self)
这里其实就是一个普通的DalvikBridgeFunc函数,当某个方法为JNI实现的native方法时,该方法对应的Method结构体中的nativeFun就指向此函数
它的主要功能就是将Object*样式的引用类型的输入参数转换为JNI格式的jobject样式的引用之后调用dvmPlatformInvokevoid dvmPlatformInvoke(void* pEnv, ClassObject* clazz, int argInfo, int argc,
const u4* argv, const char* shorty, void* func, JValue* pReturn)执行时取决于具体的CPU架构,部分采用汇编实现.对于参数argInfo,有的实现确实能够加速方法调用速度(mips,new ARM),有的必须保证argInfo有效(386),有的会忽略(old ARM).
参考资料
Dalvik虚拟机java方法执行流程和Method结构体分析的更多相关文章
- java方法执行流程解析
Java程序运行时,必须经过编译和运行两个步骤.首先将后缀名为.java的源文件进行编译,最终生成后缀名为.class的字节码文件.然后Java虚拟机将编译好的字节码文件加载到内存(这个过程被称为类加 ...
- Dalvik虚拟机JNI方法的注册过程分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8923483 在前面一文中,我们分析了Dalvi ...
- Java 代码执行流程
Java 代码执行流程 类加载过程 加载 -> 验证 -> 准备 -> 解析 -> 初始化 -> 使用 -> 卸载 类加载时机:代码使用到这个类时 验证阶段 &qu ...
- 第一章 Java代码执行流程
说明:本文主要参考自<分布式Java应用:基础与实践> 1.Java代码执行流程 第一步:*.java-->*.class(编译期) 第二步:从*.class文件将其中的内容加载到内 ...
- 面试高频SpringMVC执行流程最优解(源码分析)
文章已托管到GitHub,大家可以去GitHub查看阅读,欢迎老板们前来Star! 搜索关注微信公众号 码出Offer 领取各种学习资料! SpringMVC执行流程 SpringMVC概述 Spri ...
- 深入理解Dalvik虚拟机- 解释器的执行机制
Dalvik的指令运行是解释器+JIT的方式,解释器就是虚拟机来对Javac编译出来的字节码,做译码.运行,而不是转化成CPU的指令集.由CPU来做译码,运行.可想而知.解释器的效率是相对较低的,所以 ...
- java控制执行流程
控制执行流程 欢迎转载,转载烦请注明出处,谢谢. https://www.cnblogs.com/sx-wuyj/p/11177257.html java当中涉及到的关键字包括if-else.whil ...
- IT兄弟连 Java语法教程 流程控制语句 分支结构语句1
不论哪一种编程语言,都会提供两种基本的流程控制结构:分支结构和循环结构.其中分支结构用于实现根据条件来选择性地执行某段代码,循环结构则用于实现根据循环条件重复执行某段代码.Java同样提供了这两种流程 ...
- IT兄弟连 Java语法教程 流程控制语句 循环结构语句4
do-while循环 Java还有一种循环是do-while.与for.while这些在循环顶部判断条件表达式的语句不同,do-while是在循环底部进行条件表达式的检查.这意味着do-while循环 ...
随机推荐
- 解决PL/SQL导出cvs文件中文显示乱码
方法 1 导出csv格式文件 新建excel文件 比如 a.xls excel软件打开 选择菜单数据 -导入外部数据 unicode默认下一步 选择 逗号分隔符 点击确定导入完成 方法 2 导出成h ...
- HTML CSS + DIV实现整体布局 part2
9.盒模型的层次关系 我们通过一个经典的盒模型3D立体结构图来理解,如图: 从上往下看,层次关系如下: 第1层:盒子的边框(border), 第2层:元素的内容(content).内边 ...
- ubuntu下安装.deb包的安装方法
ubuntu16.04的软件中心应该是有bug,安装不了第三方.deb文件,我们只有使用dpkg -i 或者gdebi的方式安装,我使用的是后者,因为后者功能更加强大.要使用gdebi命令先要安装它: ...
- 慕课网access_token的获取(下)
接口调用返回的结果是两个字段:access_token和expires_in,所以需要创建一个实体类封装这两个字段 运行测试类WeixinTest.java控制台打印出错误信息 重置开发者密钥试试看 ...
- ReportViewer工具栏功能扩展[手动设置打印/导出按钮]
ReportViewer在IE11后打印按钮就存在兼容问题,火狐,谷歌也存在打印按钮显示的兼容性问题,本资料就是解决ReportViewer打印按钮显示的问题, 通过自己写脚本添加到DOM里面让所有浏 ...
- Winform关于OpenFileDialog的使用方法
1.OpenFileDialog控件有以下基本属性InitialDirectory 对话框的初始目录Filter 要在对话框中显示的文件筛选器,例如,"文本文件(*.txt)|*.txt|所 ...
- VMware安装Windows注意
安装Windows通用步骤,分区,重建分区表,重写MBR引导.安装即可. VMware安装Windows 如果进不了CM/ROM,在.vmx文件里: 加入一行:bios.forceSetupOnce ...
- swift - 封装 GCDTimer 和 NSTimer
封装的类代码 import UIKit /// 控制定时器的类 class ZDTimerTool: NSObject { /// 定时器 // private var timer: Timer? / ...
- [leetcode]250. Count Univalue Subtrees统计节点值相同的子树
Given a binary tree, count the number of uni-value subtrees. A Uni-value subtree means all nodes of ...
- MongoDB的基本shell操作(三)
mongodb_server_ Installer.bat @echo offecho 正在安装服务MongoDB...start cmd /k "cd/d C:\Program Files ...