作业内容
通过观察两个条件判断语句的运行结果,来思考 Java 语言和 Java 虚拟机看待 boolean 类型的方式是否不同。
下载 asmtools.jar,并在命令行中运行下述指令(不包含提示符 $):
$ echo '
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!");
}
}' > Foo.java
$ javac Foo.java
$ java Foo
$ java -cp /path/to/asmtools.jar org.openjdk.asmtools.jdis.Main Foo.class > Foo.jasm.1
$ awk 'NR==1,/iconst_1/{sub(/iconst_1/, "iconst_2")} 1' Foo.jasm.1 > Foo.jasm
$ java -cp /path/to/asmtools.jar org.openjdk.asmtools.jasm.Main Foo.jasm
$ java Foo
实践过程
环境准备
Ubuntu 16.04 虚拟机,方便 Linux 命令的使用;
根据链接中的指引,准备好 asmtools.jar:
- 在 Linux 中安装了 JDK8、ANT、hg;
- 通过
hg clone http://hg.openjdk.java.net/code-tools/asmtools
获取代码; - 编译
cd asmtools/build && ant
。
理解各命令的含义(用途)
- javac:将 .java 文件编译为 .class 文件;
- java:执行 .class 文件;
- java -cp:指定解释器找 .class 文件的路径;
- 此处的 awk 命令对于文件中匹配的字符串进行了替换操作。
关于 awk 的理解,参考了文章 实践中学习 awk
执行结果
对于第一次 java Foo
命令,结果是:
Hello,Java
Hello,JVM
对于第二次 java Foo
命令,结果是:
Hello,Java
为啥会是这个结果呢,这里直接拿留言中点赞最多的一位朋友的答案
jvm把boolean当做int来处理
flag = iconst_1 = true
awk把stackframe中的flag改为iconst_2
if(flag)比较时ifeq指令做是否为零判断,常数2仍为true,打印输出
if(true == flag)比较时if_cmpne做整数比较,iconst_1是否等于flag,比较失败,不再打印输出
总结
本次作业中,主要收获有两点:
- 学习了 awk 的其他用法:内部变量,内部函数;
- 发现了 asmtools 这个很有意思的项目。