前言

本节就来记录下我安装asmtools的过程,以及第一次使用awk的笔记。一开始我是觉得不太需要写博客记录的,无奈网上的教程都不太完整,结果只能自己看文档,并记录整个过程了。

顺便介绍一下asmtools,它可以强制修改Java编译后的.class文件,这样就极大地方便我们做某些实验了。

另外,本文不会再提及Jdk的安装步骤,相信这种基础中的基础应该不需要我多言了。


实验环境

  • 操作系统:Centos 7.4(64位)
  • Java version:1.8.0_111
  • Apache Ant version:1.9.14
  • asmtools-7.0(GNU Awk 4.0.2)

除了jdk和操作系统,剩下的两都会记录详细步骤。


安装Apache-ant

安装asmtools需要有ant作为基础环境,下面就来安装ant。

官网下载地址:https://ant.apache.org/bindownload.cgi

我下载的是1.9.14版本的zip包,如下图:
下载页.png

你也可以选择你喜欢的包下载。

下载解压过程略,最终目录结构如下:
ant目录结构.png

接下来就是要配置ant的环境变量了,下面我就贴出我环境变量的一部分,具体目录和写法你可以自己发挥:

> vi /etc/profile

...(略)
export PATH=$PATH:/usr/local/nginx/sbin

JAVA_HOME=/usr/local/jdk1.8.0_111;
ZOOKEEPER_HOME=/opt/softwares/zookeeper-3.4.5-cdh5.3.6;
ANT_HOME=/root/asmtools/apache-ant-1.9.14;

export PATH=$PATH:$JAVA_HOME/bin
export PATH=$PATH:/usr/local/node/bin
export PATH=$PATH:$ZOOKEEPER_HOME/bin
export PATH=$PATH:$ANT_HOME/bin
export PATH=$PATH:

保存退出后,不要忘了刷新环境变量:

> source /etc/profile

到这里,正常来说已经安装完成了,验证方法如下:

> ant -version
Apache Ant(TM) version 1.9.14 compiled on March 12 2019

当上面这条命令返回版本号,就证明安装成功了。

有了ant的基础环境后,接下来就可以开始安装asmtools了。


安装asmtools

官网下载地址:http://hg.openjdk.java.net/code-tools/asmtools/

选择你喜欢的包下载:
下载页.png

下载、解压过程略,看看解压后目录结构:
image.png

再看看上级目录:
上级目录.png

进入build目录:

> cd (你的目录)/asmtools-版本号/build

在build目录里面执行ant

> ant

然后控制台就balabala的输出日志,看到如下日志输出BUILD SUCCESSFUL就证明安装完成了:
控制台输出.png


此时返回到asmtools的同级目录,就能看见构建后的代码了:
构建后.png

构建完成之后,我们还得记住asmtools.jar的位置:

> cd (你的目录)/asmtools-7.0-build/binaries/lib

进入lib后,就能看到asmtools.jar了,记住它现在的位置,后面执行awk的时候会用上:
lib目录.png

OK,现在ant和asmtools都安装好了,接下来就可以用awk命令做个简单的实验了。


使用awk

先创建实验代码:
Hello.java

public class Hello {
        public static void main(String[] args){
                boolean flag = true;
                if (flag) System.out.println("Hello, Java!");
                if (flag == true) System.out.println("Hello, JVM!");
        }
}

先原始编译,然后执行:

> javac Hello.java
> java Hello


输出结果:
Hello, Java!
Hello, JVM!

在java虚拟机规范,以及java编译器中,true编译后只能是整数1,false编译后只能是整数0。而现在,我们需要用awk强制改变编译后的.class文件。继续执行如下命令:

> java -cp /root/asmtools-7.0-build/binaries/lib/asmtools.jar org.openjdk.asmtools.jdis.Main Hello.class > Hello.jasm.1
  • asmtools.jar请改成你自己的路径。

执行完上述命令后,会发现当前代码的目录多个个Hello.jasm.1文件,这个文件你可以当做是反编译后的一种格式,awk就是按照格式约定去修改这个文件的。有兴趣的可以看看文件内容长什么样,由于比较长我就不贴出来了。

下面使用awk去修改上面生成的文件,把原本flag转换成的1改成2:

> awk 'NR==1,/iconst_1/{sub(/iconst_1/, "iconst_2")} 1' Hello.jasm.1 > Hello.jasm

再执行如下命令完成修改.class文件:

> java -cp /root/asmtools-7.0-build/binaries/lib/asmtools.jar org.openjdk.asmtools.jasm.Main Hello.jasm

现在尝试再次执行Hello:

> java Hello


输出结果:
Hello, Java!

因为flag已经被我们强制改成2了,所以flag == true就相当于0 == 1,返回结果当然是fasle,最终导致不会再输出第二段结果。

2怎么变成0了?因为2转为二进制就是10,而HotSpot中存储boolean只用一字节,只取最后一位,即取到0。不信的话你可以改成iconst_3,会发现flag == true返回true,因为3的二进制是11



参考资料: