字节码
将.java源文件编译成.class二进制字节码文件,运行该字节码文件
将class字节码文件内容输出到文本文件当中
javap -v xxx.class > xxx.txt
第一个部分:
显示生成class的java源文件的基本信息
Classfile /D:/Y3/0311/mckz/src/main/java/com/mckz/ClassTest.class
Last modified 2020-3-11; size 418 bytes
MD5 checksum 0f3d5500af1d5036324fe505691a235d
Compiled from "ClassTest.java"
public class com.mckz.ClassTest
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
第二个部分
显示该类所涉及到的常量池,共有35个常量
Constant pool:
#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/mckz/ClassTest
#5 = Class #20 // java/lang/Object
#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 ClassTest.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/mckz/ClassTest
#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.mckz.ClassTest();
descriptor: ()V
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
Code:
stack=2, locals=4, args_size=1
0: iconst_2
1: istore_1
2: bipush 7
4: istore_2
5: iload_1
6: iload_2
7: iadd
8: istore_3
9: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
12: iload_3
13: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
16: return
LineNumberTable:
line 5: 0
line 6: 2
line 7: 5
line 8: 9
line 9: 16
}
SourceFile: "ClassTest.java"
二.动态字节技术
在程序运行或者编译时期,通过动态字节码技术对类新增,删除,修改类的内部结构,包括字段和方法
动态字节码技术应用场景:AOP,Lombok,动态修改class文件等等
字节码操作类库:
·BCEL
·ASM:轻量级的Java字节码操作框架,SpringAOP底层基于ASM字节码技术
·CGLIB 基于ASM
·javassist
ASM 是它们中最强大的一个,使用它可以动态修改类、方法,甚至可以重新定义类,连 CGLib 底层都是用 ASM 实现的
ASM 的代码实现里,最明显的就是访问者模式,ASM 将对代码的读取和操作都包装成一个访问者,在解析 JVM 加载到的字节码时调用
instrument 是 JVM 提供的一个可以修改已加载类文件的类库
1.6以前instrument 只能在 JVM 刚启动开始加载类时生效,之后,instrument 更是支持了在运行时对类定义的修改
要使用 instrument 的类修改功能,我们需要实现它的 ClassFileTransformer
接口定义一个类文件转换器
它唯一的一个 transform()
方法会在类文件被加载时调用,在 transform 方法里我们可以对传入的二进制字节码进行改写或替换
生成新的字节码数组后返回,JVM 会使用 transform 方法返回的字节码数据进行类的加载
JVM TI
JVM TI(JVM Tool Interface)JVM 工具接口是 JVM 提供的一个非常强大的对 JVM 操作的工具接口,通过这个接口
我们可以实现对 JVM 多种组件的操作,从JVMTM Tool Interface 这里我们认识到 JVM TI 的强大,它包括了对虚拟机堆内存、类、线程等各个方面的管理接口。
JVM TI 通过事件机制,通过接口注册各种事件勾子,在 JVM 事件触发时同时触发预定义的勾子,以实现对各个 JVM 事件的感知和反应