编译
- 前端编译:依靠 jdk 的编译工具把 java 文件编译成 class 文件,
javac
命令 - 后端编译:class 文件编译成机器指令
- 逐行读取 class 文件内同,并解释成机器指令
- 引入
jit
技术提高解释效率,比如某些类中共有的内容,这些内容解释次数过多就直接缓存起来
- 反编译:把 class 文件反编译为汇编代码
- 依靠的是 jdk 的
javap
命令 - 比如分析
synchronized
锁的时候,从汇编代码能看到monitorenter
、monitorexit
指令
- 依靠的是 jdk 的
字节码文件长啥样
public class Main {
private int m;
public int inc() {
return m + 1;
}
}
javac 之后生成的字节码文件如下
cafe babe 0000 0034 0013 0a00 0400 0f09
0003 0010 0700 1107 0012 0100 016d 0100
0149 0100 063c 696e 6974 3e01 0003 2829
5601 0004 436f 6465 0100 0f4c 696e 654e
756d 6265 7254 6162 6c65 0100 0369 6e63
0100 0328 2949 0100 0a53 6f75 7263 6546
696c 6501 0009 4d61 696e 2e6a 6176 610c
0007 0008 0c00 0500 0601 0010 636f 6d2f
7268 7974 686d 372f 4d61 696e 0100 106a
6176 612f 6c61 6e67 2f4f 626a 6563 7400
2100 0300 0400 0000 0100 0200 0500 0600
0000 0200 0100 0700 0800 0100 0900 0000
1d00 0100 0100 0000 052a b700 01b1 0000
0001 000a 0000 0006 0001 0000 0003 0001
000b 000c 0001 0009 0000 001f 0002 0001
0000 0007 2ab4 0002 0460 ac00 0000 0100
0a00 0000 0600 0100 0000 0800 0100 0d00
0000 0200 0e
字节码文件内容
是根据 java 文件生成来的,所以里面的内容和 java 文件肯定是一致的,只不过有归纳终结的意味在里面
- 常量池 Constant pool
- 本字符串,final常量
- 类和接口的全限定名
- 字段的名称和描述符号
- 方法的名称和描述符
- 方法表(方法的具体类容)
- stack: 最大操作数栈,JVM运行时会根据这个值来分配栈帧(Frame)中的操作栈深度
- 参数个数、局部变量、方法体 等等