android字节码,Android学习笔记 手动执行Java字节码

Android学习笔记 手动执行Java字节码

@[Android, 字节码]

背景

这一次是玩安卓知识星球的第二期作业(分析每一行字节码执行过程中的本地变量数组和操作数栈的状态),完成第一期作业的过程中需要需要操作字节码,但借助Javassist的帮助也没有去学习字节码的相关知识,现在不得不好好的看看Java的字节码究竟是怎样执行的。

JVM的内存模型

首先复习一下JVM的内存模型 ,JVM的内存模型分为几个区域,如下图:

127704749ae1

JVM的内存模型.jpg

程序计数器:这是线程私有的数据区,用来表示当前执行的是哪一行的指令

虚拟机栈:一个栈结构,存储的元素被称为栈帧,每个栈帧包含了一个方法的数据和部分过程结果的区域,同时包含动态连接的信息和方法返回值

局部变量表:用来保存方法局部变量的数组结构

操作数栈:JVM是基于栈结构,操作数栈就是具体用辅助执行指令的栈,栈深度在编译期就写入到class文件中

动态链接:作用是将对方法符号引用转换为直接引用

返回地址:方法执行完成后返回的位置,即调用自己的位置

本地方法栈:跟虚拟机栈类似的为本地方法服务的栈结构

方法区:线程共享的区域,存储运行时常量池,方法的字节码数据,类的字段等

堆:也是线程共享的区域,存储的是Java动态生成的对象数据,垃圾回收器管理的也是这的区域

class文件

对JVM内存模型有了个简单的回顾,我们继续看看class文件的结构是怎么样的。

127704749ae1

1986868-5b44e95ff7e30847.jpeg

魔数和版本号都是对文件本身的描述

常量池:存储的是字面量和符号引用,除了对一些基本类型的操作,像是类名、方法名、常量等都在这里有定义

访问标记:标记class是表示一个类还是一个接口,是否公开,是否是abstract等信息

类索引:引用常量池中的类的全限定类名

父类索引:引用常量池中的父类的全限定类名

接口索引:接口数量和引用常量池中的接口的全限定接口名

字段表集合:定义类所有字段的各种属性

方法:包含每个方法的各种属性,其中就包括上面说到的操作数栈的深度

属性:定义了class文件的属性,比如源代码文件名

手动执行字节码指令

接下来结合代码,我们来手动执行字节码指令:

public class Hello {

public static void main(String[] args) {

int a = 1;

int b = 10;

String c = "abc";

System.out.println(a + b + c + get3());

}

private static int get3() {

int result = 0;

for (int i = 0; i < 3; i++) {

result ++;

}

return result;

}

}

// 生成的字节码指令

// main()

0 iconst_1

1 istore_1

2 bipush 10

4 istore_2

5 ldc #2

7 astore_3

8 getstatic #3

11 new #4

14 dup

15 invokespecial #5 >

18 iload_1

19 iload_2

20 iadd

21 invokevirtual #6

24 aload_3

25 invokevirtual #7

28 invokestatic #8

31 invokevirtual #6

34 invokevirtual #9

37 invokevirtual #10

40 return

// get3()

0 iconst_0

1 istore_0

2 iconst_0

3 istore_1

4 iload_1

5 iconst_3

6 if_icmpge 18 (+12)

9 iinc 0 by 1

12 iinc 1 by 1

15 goto 4 (-11)

18 iload_0

19 ireturn

代码很简单,我们先来看以下各部分在虚拟机中的存储情况

127704749ae1

Java字节码总览 | center

代码加载到方法区,正在被执行的方法作为栈帧被初始化到虚拟机栈,执行第一条指令,常量1被压入栈

127704749ae1

1576237431800.png

new对象时,在堆生成该对象,并将对象的地址压入栈

127704749ae1

1576237550745.png

执行方法时,调用方法生成新的栈帧并压入虚拟机栈,然后将返回值设为方法调用处的下一条指令

127704749ae1

1576237607977.png

退出方法时从返回地址返回,如果有返回值则将栈顶的值压入调用处的操作数栈

127704749ae1

1576237726715.png

以上只是部分分析过程,具体可以下载我做的ppt查看全部的过程会更清楚

127704749ae1

class执行过程.gif

ppt的地址:

总结

将学习的结果写出来真的花时间花精力,但是我相信通过这样的方式我会对所学的内容理解更加深刻。现在希望能继续坚持下去。可以参考项目地址

参考:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值