根据class取值_浅析 .class 文件

我们都知道 「.java」 文件要经过编译变为 「.class」 文件才能执行,那么问题来了,「.class」 文件里面究竟有些啥?

我做了一个小小的实验。

7cac7b383f4f03bd9f4cec9ab1063c7a.png 5bd87e4f07bdc586e1b60f5475239192.png

1. 随便写些简单语句

de96fb99e58b2d3128708477654cdfc7.png 672050b3b813df9bd4644b569ba5f770.png
public class Hello {    public void hello() {        int num1 = 1;        int num2 = 2;        int num3 = 64;        int num4 = num1+num2;        for (int i = 1; i <= 3; i++) {            if(num4                num3/=2;                num4*=2;            }        }    }}
7cac7b383f4f03bd9f4cec9ab1063c7a.png 5bd87e4f07bdc586e1b60f5475239192.png

2. 编译,查看字节码

de96fb99e58b2d3128708477654cdfc7.png 672050b3b813df9bd4644b569ba5f770.png
javac Hello.javajavap -c Hello.class

0bf01541b5f13c5d72296c7ffeddfb7d.png

7cac7b383f4f03bd9f4cec9ab1063c7a.png 5bd87e4f07bdc586e1b60f5475239192.png

3. 分析

de96fb99e58b2d3128708477654cdfc7.png 672050b3b813df9bd4644b569ba5f770.png

实际上,基本类型的运算要广泛使用到「栈」这个数据结构,下面我一条一条来分析,千言万语尽在注释中:

 0: iconst_1 //将值为int类型的常数1入栈 1: istore_1 //栈顶出栈,存在本地变量索引1处,即 num1=1 2: iconst_2 //将值为int类型的常数2入栈 3: istore_2 //栈顶出栈,存在本地变量索引2处,即 num2=2 4: bipush        64 //将值为int类型的64入栈 6: istore_3 //栈顶出栈,存在本地变量索引3处,即 num3=64 7: iload_1 //将本地变量索引1处的值入栈 8: iload_2 //将本地变量索引2处的值入栈 9: iadd //实现了一个形如“AB+”的后缀表达式计算,将结果入栈,即1+2=310: istore        4 //栈顶出栈,存在本地变量索引4处,即 num4=312: iconst_1 //将值为int类型的常数1入栈13: istore        5 //栈顶出栈,存在本地变量索引5处,即 i=115: iload         5 //循环开始17: iconst_3 //将值为int类型的常数3入栈,也就是循环终止条件18: if_icmpgt     43 //比较栈顶两个int类型数值的大小,大于的话(即i>3)跳到43行执行,21: iload         4 //将本地变量索引4处的值入栈23: iload_3 //将本地变量索引3处的值入栈24: if_icmpge     37 //比较栈顶两个int类型数值的大小,大于等于的话(即num4>=num3)跳到37行执行27: iload_3 //将本地变量索引3处的值入栈28: iconst_2 //将值为int类型的常数2入栈29: idiv //实现了一个形如“AB/”的后缀表达式计算,将结果入栈,即64/2=32(以第一次循环为例)30: istore_3 //栈顶出栈,存在本地变量索引3处,即 num3=3231: iload         4 //将本地变量索引4处的值入栈33: iconst_2 //将值为int类型的常数2入栈34: imul //实现了一个形如“AB*”的后缀表达式计算,将结果入栈,即3*2=6(以第一次循环为例)35: istore        4 //栈顶出栈,存在本地变量索引3处,即 num4=637: iinc          5, 1 //将本地变量索引5的值加上1,即 ++i40: goto          15 //回到15行重新循环43: return //循环结束

根据这段字节码的分析,总结如下:

  1. 当 int 类型取值 0~5 时,用 iconst_x 表示,特别地,当取 -1 时,用  iconst_m1 表示;当  int 类型取到 -128~127 其他的数时,用 bipush x 表示。

  2. 对于istore_x,当变量数量不大于3时只占用一位内存,后面的变量要占两位。

  3. 在不等式判断时,遇到i<=3,字节码实际上是按照 i>3 跳出 for 循环的思路执行;遇到 num4字节码实际上是按照 num4>=num3 跳出 if 判断的思路执行。

  4. for循环中的 i++ 和 ++i 其实转换成字节码后没有任何区别。

8db08f16cf25dd7a3820686f37936481.png

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值