深入拆解Java虚拟机
郑雨迪
Oracle 高级研究员,计算机博士
立即订阅
27940 人已学习
课程目录
已完结 39 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 为什么我们要学习Java虚拟机?
免费
模块一:Java虚拟机基本原理 (12讲)
01 | Java代码是怎么运行的?
02 | Java的基本类型
03 | Java虚拟机是如何加载Java类的?
04 | JVM是如何执行方法调用的?(上)
05 | JVM是如何执行方法调用的?(下)
06 | JVM是如何处理异常的?
07 | JVM是如何实现反射的?
08 | JVM是怎么实现invokedynamic的?(上)
09 | JVM是怎么实现invokedynamic的?(下)
10 | Java对象的内存布局
11 | 垃圾回收(上)
12 | 垃圾回收(下)
模块二:高效编译 (12讲)
【工具篇】 常用工具介绍
13 | Java内存模型
14 | Java虚拟机是怎么实现synchronized的?
15 | Java语法糖与Java编译器
16 | 即时编译(上)
17 | 即时编译(下)
18 | 即时编译器的中间表达形式
19 | Java字节码(基础篇)
20 | 方法内联(上)
21 | 方法内联(下)
22 | HotSpot虚拟机的intrinsic
23 | 逃逸分析
模块三:代码优化 (10讲)
24 | 字段访问相关优化
25 | 循环优化
26 | 向量化
27 | 注解处理器
28 | 基准测试框架JMH(上)
29 | 基准测试框架JMH(下)
30 | Java虚拟机的监控及诊断工具(命令行篇)
31 | Java虚拟机的监控及诊断工具(GUI篇)
32 | JNI的运行机制
33 | Java Agent与字节码注入
模块四:黑科技 (3讲)
34 | Graal:用Java编译Java
35 | Truffle:语言实现框架
36 | SubstrateVM:AOT编译框架
尾声 (1讲)
尾声 | 道阻且长,努力加餐
深入拆解Java虚拟机
登录|注册

【工具篇】 常用工具介绍

郑雨迪 2018-08-03
在前面的文章中,我曾使用了不少工具来辅助讲解,也收到了不少同学留言,说不了解这些工具,不知道都有什么用,应该怎么用。那么今天我便统一做一次具体的介绍。本篇代码较多,你可以点击文稿查看。

javap:查阅 Java 字节码

javap 是一个能够将 class 文件反汇编成人类可读格式的工具。在本专栏中,我们经常借助这个工具来查阅 Java 字节码。
举个例子,在讲解异常处理那一篇中,我曾经展示过这么一段代码。
public class Foo {
private int tryBlock;
private int catchBlock;
private int finallyBlock;
private int methodExit;
public void test() {
try {
tryBlock = 0;
} catch (Exception e) {
catchBlock = 1;
} finally {
finallyBlock = 2;
}
methodExit = 3;
}
}
编译过后,我们便可以使用 javap 来查阅 Foo.test 方法的字节码。
$ javac Foo.java$ javap -p -v FooClassfile ../Foo.class Last modified ..; size 541 bytes MD5 checksum 3828cdfbba56fea1da6c8d94fd13b20d Compiled from "Foo.java"public class Foo minor version: 0 major version: 54 flags: (0x0021) ACC_PUBLIC, ACC_SUPER this_class: #7 // Foo super_class: #8 // java/lang/Object interfaces: 0, fields: 4, methods: 2, attributes: 1Constant pool: #1 = Methodref #8.#23 // java/lang/Object."<init>":()V #2 = Fieldref #7.#24 // Foo.tryBlock:I #3 = Fieldref #7.#25 // Foo.finallyBlock:I #4 = Class #26 // java/lang/Exception #5 = Fieldref #7.#27 // Foo.catchBlock:I #6 = Fieldref #7.#28 // Foo.methodExit:I #7 = Class #29 // Foo #8 = Class #30 // java/lang/Object #9 = Utf8 tryBlock #10 = Utf8 I #11 = Utf8 catchBlock #12 = Utf8 finallyBlock #13 = Utf8 methodExit #14 = Utf8 <init> #15 = Utf8 ()V #16 = Utf8 Code #17 = Utf8 LineNumberTable #18 = Utf8 test #19 = Utf8 StackMapTable #20 = Class #31 // java/lang/Throwable #21 = Utf8 SourceFile #22 = Utf8 Foo.java #23 = NameAndType #14:#15 // "<init>":()V #24 = NameAndType #9:#10 // tryBlock:I #25 = NameAndType #12:#10 // finallyBlock:I #26 = Utf8 java/lang/Exception #27 = NameAndType #11:#10 // catchBlock:I #28 = NameAndType #13:#10 // methodExit:I #29 = Utf8 Foo #30 = Utf8 java/lang/Object #31 = Utf8 java/lang/Throwable{ private int tryBlock; descriptor: I flags: (0x0002) ACC_PRIVATE private int catchBlock; descriptor: I flags: (0x0002) ACC_PRIVATE private int finallyBlock; descriptor: I flags: (0x0002) ACC_PRIVATE private int methodExit; descriptor: I flags: (0x0002) ACC_PRIVATE public Foo(); descriptor: ()V flags: (0x0001) 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 1: 0 public void test(); descriptor: ()V flags: (0x0001) ACC_PUBLIC Code: stack=2, locals=3, args_size=1 0: aload_0 1: iconst_0 2: putfield #2 // Field tryBlock:I 5: aload_0 6: iconst_2 7: putfield #3 // Field finallyBlock:I 10: goto 35 13: astore_1 14: aload_0 15: iconst_1 16: putfield #5 // Field catchBlock:I 19: aload_0 20: iconst_2 21: putfield #3 // Field finallyBlock:I 24: goto 35 27: astore_2 28: aload_0 29: iconst_2 30: putfield #3 // Field finallyBlock:I 33: aload_2 34: athrow 35: aload_0 36: iconst_3 37: putfield #6 // Field methodExit:I 40: return Exception table: from to target type 0 5 13 Class java/lang
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《深入拆解Java虚拟机》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(27)

  • 刹那间的永恒
    果然还是一点都看不懂,老师,什么阶段适合接触虚拟机?
    2018-08-04
    40
  • xiaobang
    能系统的介绍下Java字节码吗,每次看到都是靠猜
    2018-08-20
    7
  • Thomas
    老师后面讲下反射跟动态代理~很期待专门写一篇JAVA特性的原理。
    2018-08-03
    6
  • 雨亦奇
    666
    2018-08-03
    3
  • xiaobang
    能系统介绍下Java字节码吗?每次都是靠猜
    2018-08-20
    2
  • hey,吕布
    老师,文中代码格式异常了,早上打开还好的

    作者回复: 这么诡异,我反馈一下

    2018-08-03
    2
  • 王浩
    看了一遍没看没白,建议多讲些细节,比如如何使用javap查看字节码,说详细些,各种工具的特点是什么,最常用的工具是哪个,在什么场景下使用。
    2019-02-14
    1
  • 东方
    ClassWriter继承并实现了虚基类ClassVisitor,实现了一系列的vist*方法(读取class信息至内存)


    MyClassVisitor继承ClassWriter,只复写(Override)了visitMethod方法,当且仅当方法名称等于main时,才替换用自定义内容替换


    整个逻辑等于说,读Foo.class到内存中,重新写一个Foo.class文件,main方法替换为"新内容",其他保持不变



    2018-08-19
    1
  • 郑童文
    我不太明白 用ASM反汇编class 文件 之后不就改得到java源文件吗?为什么还有java 之外的关键字?
    2018-08-08
    1
  • 倔强
    为什么我允许F oo Dump报无法加载主类?是因为没有main方法?

    作者回复: 多谢指出!应该是Wrapper,而且cp也需要添加当前目录,即-cp /path/to/ASM.jar:. Wrapper

    2018-08-03
    1
  • 男朋友
    描述符的那个表我怎么看不见
    2019-11-05
  • 随心而至
    java -cp /PATH/TO/asm-all-6.0_BETA.jar:. Wrapper
    在windows需要将冒号换为分号,虽然很基础,我给忘了。。。
    https://www.programcreek.com/2014/01/compile-and-run-java-in-command-line-with-external-jars/
    2019-10-14
  • 随心而至
    我觉得看完周志明老师的深入理解Java虚拟机,再来看郑老师的专栏是比较合适的。
    2019-10-14
  • 我家门前有只猪
    请问一下老师学这个需要先回Linus系统吗?
    2019-06-09
  • capo
    你好,代码ASMHelper.java中 MethodVisitor ClassVIsitor 应该都是Interface吧?super.visitMethod怎么调用的?
    2019-04-25
  • QQ怪
    这里有点隐晦难懂
    2019-03-17
  • xuery
    仔细看了下教程[10], 更加深刻的理解了如何通过修改字节码文件来达到修改类的效果,感谢,坚持深挖下去
    2018-11-27
  • bgmall
    javap 查看class文件

    基础md5 jdk版本

    常量池

    字段描述 访问权限

    方法代码栈

    异常表(有异常捕获的才有)
    2018-11-02
  • sgl
    为什么方法里用的指令只有入栈,没有出栈?难道putfield这类指令,用了操作数栈上的数据以后,会自己调用出栈指令?

    作者回复: putfield 可以想成 出栈再消耗数据

    2018-10-20
  • 猎羽
    写的不错,支持一下
    2018-09-12
收起评论
27
返回
顶部