- 源码
public class Math {
public static final int CONSTANT = 666;
public int math() {
int a = 1;
int b = 2;
int c = (a + b) * 10;
return c;
}
public static void main(String[] args) {
Math math = new Math();
math.math();
}
}
- javap -c 类名: 反编译
guchunchaodeMacBook-Air:javacode guchunchao$ javap -c Math
Compiled from "Math.java"
public class Math {
public static final int CONSTANT;
public Math();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public int math();
Code:
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: iadd
7: bipush 10
9: imul
10: istore_3
11: iload_3
12: ireturn
public static void main(java.lang.String[]);
Code:
0: new #2 // class Math
3: dup
4: invokespecial #3 // Method "<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #4 // Method math:()I
12: pop
13: return
}
第一步:数据1放入操作数栈中
步骤二:在局部变量表中为变量a开辟一块内存区域,并将第一步中操作数栈中的1出栈赋值给变量a
第三步:在操作数栈中开辟一块儿内存空间存放数字2,再将局部变量表中开辟一块儿内存空间存放变量b
第四步:将操作数栈中的数字:2出栈并赋值到局部变量表中的b变量中
第五步:将局部变量表中的【a的值】,【b的值】装载到操作数栈中
第六步:从操作数栈中弹出2,再弹出1,由CPU运算完成后的结果:3,再次压入到操作数栈
每个方法都有自己的栈帧,栈帧里都有
- 局部变量表:
- 操作数栈:程序在操作过程中一些临时的中间操作会借助此区域做中转,存放数据
- 动态链接
- 方法出口
- 程序计数器:记录的是线程马上要执行的下一行代码的内存指针
- 方法区Metaspace:JDK1.8之前还算是JVM内存模型中的一块,但是1.8开始是直接用的物理内存。因为:程序在启动过程中类装载子系统要把很多代码装载到【类方法区】,很多字节码大小是没法预估的,包括如果程序有大量的反射代码,反射生成的类元信息都是放在方法区,很容易导致方法区内存溢出,所以JVM做了一个优化,让其分配在直接(物理)内存里。
- 堆里的对象中会有一个指针指向方法区的类的类元信息,所以同类的不同的对象可以执行相同的程序逻辑。
minor-GC 新生代的Eden区的GC
full-GC 老年代的GC
局部变量表
操作数栈
动态链接
返回值地址
一个方法一个栈帧:one method one frame
IDE jclasslib 插件安装
view --> show bytecode with jclasslib
总有一个开始,不妨从今天开始
知耻而后勇
你现在感到压力是因为你欠了很多债,现在开始还不晚,麻烦你花点时间把这些债都补上。
网友评论