这是一篇修改class文件的文章。注释并不完全,要抓住这次练习的目的:

boolean在虚拟机中是以何种方式解读的

好的,开始我的表演

1.安装asmtools.jar(本文尾部有步骤)

2.编写一个java文件,并编译,执行
 2.1 Foo.java
 public class Foo {
public static void main(String[] args) {
boolean flag = true;
if (flag) {
System.out.println("Hello, Java!");
}
if (flag == true) {
System.out.println("Hello, JVM!");
}
}
}

2.2 编译并运行

[root@localhost tmp]# javac Foo.java
[root@localhost tmp]# java Foo
Hello, Java!
Hello, JVM!

3.查看编译后的java文件,class (注意看黄色部分的变化)

[root@localhost tmp]# javap -verbose Foo
Classfile /usr/local/asmtools-7.0-build/binaries/lib/tmp/Foo.class
Last modified Aug 12, 2019; size 493 bytes
MD5 checksum d51944604c5b4e45cb895501910347ea
Compiled from "Foo.java"
public class Foo
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #7.#17 // java/lang/Object."<init>":()V
#2 = Fieldref #18.#19 // java/lang/System.out:Ljava/io/PrintStream;
#3 = String #20 // Hello, Java!
#4 = Methodref #21.#22 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = String #23 // Hello, JVM!
#6 = Class #24 // Foo
#7 = Class #25 // java/lang/Object
#8 = Utf8 <init>
#9 = Utf8 ()V
#10 = Utf8 Code
#11 = Utf8 LineNumberTable
#12 = Utf8 main
#13 = Utf8 ([Ljava/lang/String;)V
#14 = Utf8 StackMapTable
#15 = Utf8 SourceFile
#16 = Utf8 Foo.java
#17 = NameAndType #8:#9 // "<init>":()V
#18 = Class #26 // java/lang/System
#19 = NameAndType #27:#28 // out:Ljava/io/PrintStream;
#20 = Utf8 Hello, Java!
#21 = Class #29 // java/io/PrintStream
#22 = NameAndType #30:#31 // println:(Ljava/lang/String;)V
#23 = Utf8 Hello, JVM!
#24 = Utf8 Foo
#25 = Utf8 java/lang/Object
#26 = Utf8 java/lang/System
#27 = Utf8 out
#28 = Utf8 Ljava/io/PrintStream;
#29 = Utf8 java/io/PrintStream
#30 = Utf8 println
#31 = Utf8 (Ljava/lang/String;)V
{
public Foo();
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 1: 0 public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: iconst_1 //常量1入栈
1: istore_1 //把栈顶值存储到局部变量表下标为1的位置,即flag =1;
2: iload_1 //取局部变量表中下标为1的变量压栈
3: ifeq 14 //(jump if i == 0) 将栈顶值与0比较,如果相等,则跳入14步骤。
6: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
9: ldc #3 // String Hello, Java!
11: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
14: iload_1 //取局部变量表中下标为1的变量压栈
15: iconst_1 //常量1入栈
16: if_icmpne 27 //比较栈顶两个值,如果不相等,则跳转到27
19: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
22: ldc #5 // String Hello, JVM!
24: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
27: return
LineNumberTable:
line 3: 0
line 4: 2
line 5: 6
line 7: 14
line 8: 19
line 10: 27
StackMapTable: number_of_entries = 2
frame_type = 252 /* append */
offset_delta = 14
locals = [ int ]
frame_type = 12 /* same */
}
SourceFile: "Foo.java"

4.使用asmtools.jar修改class文件

[root@localhost tmp]# java -jar ../asmtools.jar jdis Foo.class > Foo.jasm.1
[root@localhost tmp]# ls
Foo.class Foo.jasm.1 Foo.java
[root@localhost tmp]# java -cp ../asmtools.jar org.openjdk.asmtools.jdis.Main Foo.class > Foo.jasm.1
[root@localhost tmp]# awk 'NR==1,/iconst_1/{sub(/iconst_1/,"iconst_2")} 1' Foo.jasm.1 > Foo.jasm
[root@localhost tmp]# ls
Foo.class Foo.jasm Foo.jasm.1 Foo.java
[root@localhost tmp]# java Foo
Hello, Java!
Hello, JVM!

5.再次编译,执行

[root@localhost tmp]# java -jar  ../asmtools.jar jasm Foo.jasm
[root@localhost tmp]# java Foo
Hello, Java!
[root@localhost tmp]# ls
Foo.class Foo.jasm Foo.jasm.1 Foo.java

6.查看修改后的class文件

[root@localhost tmp]# javap -verbose Foo
Classfile /usr/local/asmtools-7.0-build/binaries/lib/tmp/Foo.class
Last modified Aug 12, 2019; size 431 bytes
MD5 checksum 18cfb8b8b7d9d49e9ffce213e70c8898
Compiled from "Foo.jasm"
public class Foo
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = String #10 // Hello, Java!
#2 = String #11 // Hello, JVM!
#3 = Fieldref #27.#12 // java/lang/System.out:Ljava/io/PrintStream;
#4 = Methodref #8.#17 // java/lang/Object."<init>":()V
#5 = Methodref #13.#30 // java/io/PrintStream.println:(Ljava/lang/String;)V
#6 = Utf8 (Ljava/lang/String;)V
#7 = Utf8 out
#8 = Class #9 // java/lang/Object
#9 = Utf8 java/lang/Object
#10 = Utf8 Hello, Java!
#11 = Utf8 Hello, JVM!
#12 = NameAndType #7:#23 // out:Ljava/io/PrintStream;
#13 = Class #15 // java/io/PrintStream
#14 = Utf8 ([Ljava/lang/String;)V
#15 = Utf8 java/io/PrintStream
#16 = Utf8 main
#17 = NameAndType #29:#20 // "<init>":()V
#18 = Utf8 SourceFile
#19 = Utf8 println
#20 = Utf8 ()V
#21 = Utf8 StackMapTable
#22 = Utf8 Foo.jasm
#23 = Utf8 Ljava/io/PrintStream;
#24 = Utf8 Code
#25 = Class #26 // Foo
#26 = Utf8 Foo
#27 = Class #28 // java/lang/System
#28 = Utf8 java/lang/System
#29 = Utf8 <init>
#30 = NameAndType #19:#6 // println:(Ljava/lang/String;)V
{
public Foo();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #4 // Method java/lang/Object."<init>":()V
4: return public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: iconst_2 //载入常量2入栈
1: istore_1 //把栈顶值存储到局部变量表下标为1的位置,即flag =2;
2: iload_1 //取局部变量表中下标为1的变量压栈
3: ifeq 14
6: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
9: ldc #1 // String Hello, Java!
11: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
14: iload_1 //取局部变量表中下标为1的变量压栈
15: iconst_1 //常量1入栈
16: if_icmpne 27 //比较栈顶两个值,如果不相等,则跳转到27
19: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
22: ldc #2 // String Hello, JVM!
24: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
27: return
StackMapTable: number_of_entries = 2
frame_type = 252 /* append */
offset_delta = 14
locals = [ int ]
frame_type = 12 /* same */
}
SourceFile: "Foo.jasm"

  

 

附:asmtools.jar的安装(centos 6/7)

0.先cd进入需要安装到的目录地址
 1. Mercurial是一种轻量级分布式版本控制系统,采用Python语言实现。
yum install hg

2. 版本是2.6.2,发现不是最新版,去官方下载centos 7最新版3.9.2

wget https://www.mercurial-scm.org/release/centos7/RPMS/x86_64/mercurial-3.9.2-1.x86_64.rpm

3.升级2.6.2 到3.9.2 (centos 6 我就没有用这一步。。)

rpm -Uvh mercurial-3.9.2-1.x86_64.rpm

4.安装ASMTOOLS.jar

hg clone http://hg.openjdk.java.net/code-tools/asmtools/ asmtools
cd asmtools/build/
yum install ant
ant //编译生成asmtools.jar

5.生成的jar位置:

[root@localhost lib]# ls
asmtools.jar
[root@localhost lib]# pwd
/usr/local/asmtools-7.0-build/binaries/lib

  

  

  

  

 

《深入理解Java虚拟机》-(实战)练习修改class文件的更多相关文章

  1. 深入理解Java虚拟机--上

    深入理解Java虚拟机--上 第2章 Java内存区域和内存溢出异常 2.2 运行时数据区域 图 2-1 Java虚拟机运行时数据区 2.2.1 程序计数器 程序计数器可以看作是当前线程所执行的字节码 ...

  2. 《深入理解Java虚拟机》第 3 版里面到底多了哪些知识点?本文竟然得到了本书作者的认可!

    这是why的第 47 篇原创文章 荒腔走板 大家好,我是 why.老规矩,先是简短的荒腔走板聊聊生活. 上面的图是前几天拍的,那天晚上下班后,刚刚走进小区就看到了这一轮弯月和旁边那一颗特别特别亮的星星 ...

  3. 深入理解Java虚拟机第三版,总结笔记【随时更新】

    最近一直在看<深入理解Java虚拟机>第三版,无意中发现了第三版是最近才发行的,听说讲解的JDK版本升级,新增了近50%的内容. 这种神书,看懂了,看进去了,真的看的很快,并没有想象中的晦 ...

  4. 深入理解Java虚拟机之自己编译JDK

    题外话 最近在阅读<深入理解Java虚拟机>,其中有一小节实战是自己编译JDK,实际操作下来后遇到问题不少,为此特地记录,也希望可以给大家带来一些参考! 前置准备 平台及工具:Window ...

  5. 《深入理解Java虚拟机》虚拟机性能监控与故障处理工具

    上节学习回顾 从课本章节划分,<垃圾收集器>和<内存分配策略>这两篇随笔同属一章节,主要是从理论+实验的手段来讲解JVM的内存处理机制.好让我们对JVM运行机制有一个良好的概念 ...

  6. 《深入理解 java虚拟机》学习笔记

    java内存区域详解 以下内容参考自<深入理解 java虚拟机 JVM高级特性与最佳实践>,其中图片大多取自网络与本书,以供学习和参考.

  7. (1) 深入理解Java虚拟机到底是什么?

    好文转载:http://blog.csdn.net/zhangjg_blog/article/details/20380971 什么是Java虚拟机   作为一个Java程序员,我们每天都在写Java ...

  8. 深入理解java虚拟机(6)---内存模型与线程 & Volatile

    其实关于线程的使用,之前已经写过博客讲解过这部分的内容: http://www.cnblogs.com/deman/category/621531.html JVM里面关于多线程的部分,主要是多线程是 ...

  9. 深入理解Java虚拟机--下

    深入理解Java虚拟机--下 参考:https://www.zybuluo.com/jewes/note/57352 第10章 早期(编译期)优化 10.1 概述 Java语言的"编译期&q ...

  10. 《深入理解Java虚拟机:JVM高级特性与最佳实践》【PDF】下载

    <深入理解Java虚拟机:JVM高级特性与最佳实践>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230062566 内容简介 作为一位 ...

随机推荐

  1. ElasticStack学习(五):ElasticSearch索引与分词

    一.正排索引与倒排索引 1.什么是正排索引呢? 以一本书为例,一般在书的开始都会有书的目录,目录里面列举了一本书有哪些章节,大概有哪些内容,以及所对应的页码数.这样,我们在查找一些内容时,就可以通过目 ...

  2. synchronized与ReentrantLock实现共享资源的消费

    主方法 public class synchronizedTest { public static void main(String[] args) { long startTime = System ...

  3. c++学习书籍推荐《Exceptional C++ Style》下载

    百度云及其他网盘下载地址:点我 编辑推荐 软件“风格”所要讨论的主题是如何在开销与功能之间.优雅与可维护性之间.灵活.性与过分灵活之间寻找完美的平街点.在本书中,著名的C++大师Herb Sutter ...

  4. Centos7:yum安装MySQL5.7后如何设置root密码

    Centos下安装软件的方式很简单,只需要通过yum install xxx命令即可.第一步当然检查是否有mysql的yum源,命令:yum list|grep mysql-community[主要还 ...

  5. k8s学习 - 概念 - ReplicationController

    k8s学习 - 概念 - ReplicationController 我们有了 pod,那么就需要对 pod 进行控制,就是同一个服务的 podv我需要启动几个?如果需要扩容了,怎么办?这里就有个控制 ...

  6. Redis HyperLogLog用法简介

    (1)HyperLogLog简介 在Redis 在 2.8.9 版本才添加了 HyperLogLog,HyperLogLog算法是用于基数统计的算法,每个 HyperLogLog 键只需要花费 12 ...

  7. 【最小生成树之Kruskal算法】

    看完之后推荐再看一看[最小生成树之Prim算法]-C++ 定义:一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边.最小生成树可以用kr ...

  8. SQLite的一些体会

    SQLite遵循sql语法,所以如果接触过数据库,使用它进行增删改查几乎没障碍.在.net中,它与Mysql.sql server的类也相似,比如连接类名字是SQLiteConnection,不过它S ...

  9. [Windows无法连接到 System Event Notification Service服务]解决方案

    我之前使用Windows的过程的有出现过以下问题,之前因为比较急就匆忙解决了没来得及把解决方法写下来. 正好今天有个朋友电脑也出现此问题过来找我寻求解决方法,便把解决方法写了下来. 电脑出现的问题,如 ...

  10. 个人永久性免费-Excel催化剂功能第90波-xml与json数据结构转换表格结构

    在网络时代,大量的数据交互以xml和json格式提供,特别是系统间的数据交互和网络WebAPI.WebService接口的数据提供,都是通过结构化的xml或json提供给其他应用调用返回数据.若能提供 ...