一、为什么要获取jvm字节码
1.一些代码的执行在源码层面是看不出来的,因为jvm执行的是字节码,只有通过字节码才能清除的知道代码的执行。
二、javap
1.javap是jdk自带的一款工具,可以通过该命令获取字节码
三、实战
1.java源代码
package com.jvm;
public class Test2 {
public static void main(String[] args) {
int a=1;
int b=2;
int c=a+b;
System.out.println(c);
}
}
2.获取jvm字节码
通过javac命令将Test2.java编译过后获取.class文件
通过javap命令获取Test2的jvm字节码
3.字节码文件
//最后修改时间,大小408bytes
Last modified 2019-9-10; size 408 bytes
MD5 checksum 31369d53bfd4e15c9dcfda94450c431d
Compiled from "Test2.java"
//包名和类名
public class com.jvm.Test2
//jdk版本52为jdk1.8
minor version: 0
major version: 52
//类的访问修饰符public
flags: ACC_PUBLIC, ACC_SUPER
//常量池
Constant pool:
//Methodref(方法的引用) 引用了#5.#14;#5引用了#20,#20=java/lang/Object;
//#14=#6:#7;即=<init>:()V ,所以#1=java/lang/Object.<init>:()V
//Object为对象,init构造方法,()表示无参,V代表返回值,V=void,即返回值为void
#1 = Methodref #5.#14 // java/lang/Object."<init>":()V
#2 = Fieldref #15.#16 // java/lang/System.out:Ljava/io/PrintStream;
#3 = Methodref #17.#18 // java/io/PrintStream.println:(I)V
#4 = Class #19 // com/jvm/Test2
#5 = Class #20 // java/lang/Object
//utf8位字符串,<init>为构造方法
#6 = Utf8 <init>
#7 = Utf8 ()V
#8 = Utf8 Code
#9 = Utf8 LineNumberTable
#10 = Utf8 main
#11 = Utf8 ([Ljava/lang/String;)V
#12 = Utf8 SourceFile
#13 = Utf8 Test2.java
#14 = NameAndType #6:#7 // "<init>":()V
#15 = Class #21 // java/lang/System
#16 = NameAndType #22:#23 // out:Ljava/io/PrintStream;
#17 = Class #24 // java/io/PrintStream
#18 = NameAndType #25:#26 // println:(I)V
#19 = Utf8 com/jvm/Test2
#20 = Utf8 java/lang/Object
#21 = Utf8 java/lang/System
#22 = Utf8 out
#23 = Utf8 Ljava/io/PrintStream;
#24 = Utf8 java/io/PrintStream
#25 = Utf8 println
#26 = Utf8 (I)V
{
public com.jvm.Test2();
//方法描述符无参,无返回值
descriptor: ()V
//方法访问修饰符为public
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 3: 0
//main函数
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
//stack代表操作数栈的一个深度,一个方法代表一个栈帧,
//locals本地变量表的最大长度,如果是static方法,索引从0开始,如果是非static,则0表示this
Code:
stack=2, locals=4, args_size=1
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: iadd
7: istore_3
8: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
11: iload_3
12: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
15: return
LineNumberTable:
line 6: 0
line 7: 2
line 8: 4
line 9: 8
line 10: 15
}
SourceFile: "Test2.java"
4.常量池的类型有很多,具体可以看官网https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.1
#1=utf8 #6
#2=class #5
这些都是符号引用,初始化之后,都会转换为直接引用。
5.jvm中Field description
6.
java里面,参数为int, double,Thread。返回则值为Object
则jvm字节码为I,D,L java/lang/Thread; 返回值为L java/lang/Object;
获取更多学习资料,面试题以及视频,关注微信公众号: