查看java编译过程的JAD工具

今天带来一个好玩的工具——JAD,他是干什么的呢,这个工具可以把java的类文件反编译成java的源代码,用过android反编译的肯定玩过JD_GUI这个工具,他可以查看.jar文件里面的类信息,虽然JAD没有JD_GUI那么的强势(JAD看不了jar文件),但是,对于学java的一些执行过程来说,还是很有帮助的,关键是十分的有趣。

使用必备工具:JAD.exe下载链接,我们下载下来最好放在配置了java环境的jdk的bin目录下面,这样可以随意jad的去玩,再来一个JAD的命令使用大全

ok,准备完毕,接下来带来一个好玩的东西,也是无意之中发现的,在jdk1.7之后,switch语句已经支持使用String去作为判断类型了,下面就针对这个例子玩一下。

java源代码

class A{
 public static void main(String args[]){
      String a="hello";
      String b="";
      switch(a){
         case "word":
           b="word";
           break;
         case "hello":
           b="hello";
           break;
      }
   System.out.println(b);
  }
}

java代码没什么,接下来我们编译一下这个类文件,会生成A.class文件

javac A.java

然后我们输入jad的反编译命令,下面这句话的意思是,-P是输出到哪里,A.class是被反编译的类文件,>是输出到哪里,B.java指定输出的文件

jad -p A.class>B.java

然后我们打开B.java查看一下这个被反编译后的代码

// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) 
// Source File Name:   A.java
import java.io.PrintStream;
class A
{
    A(){ }
    public static void main(String args[])
    {
        String s = "hello";
        String s1 = "";
        String s2 = s;
        byte byte0 = -1;
        switch(s2.hashCode())
        {
        case 3655434: 
            if(s2.equals("word"))
                byte0 = 0;
            break;
        case 99162322: 
            if(s2.equals("hello"))
                byte0 = 1;
            break;
        }
        switch(byte0)
        {
        case 0: // '\0'
            s1 = "word";
            break;

        case 1: // '\001'
            s1 = "hello";
            break;
        }
        System.out.println(s1);
    }
}

再来一张对比的照片

这里写图片描述

这个代码很有特点,也让我们知道了java是怎么去处理switch的字符串,接下来我们分析分析。

首先我们可以看到最上部分的注释信息,这个信息似乎是去不掉的,很有特点,哈哈。

上面还有一个import的导包,我们明明在java代码中是没有导过包的,怎么这里出现这个包呢,要知道,System.out.println这个语句中的println,是io操作的,虽然我们java文件没有导包,因为我们使用的是默认的lang包,所以,明白的吧。

接下来继续,类的初始化会触发默认的构造函数,虽然我们在java代码中没有写,但是,反编译的时候,我们却清晰可见,构造方法A被调用过了。

接下来看main方法,这个地方是勾起我最有趣的地方,在jdk1.7之前,switch是不支持String类型的判断的,但是在1.7后开始支持了,后来在想,他是怎么支持字符串的呢,在编译java代码的时候,jvm只支持8种基本类型,没有String的身影啊,然后通过jad编译之后,发现了这个好玩的地方。
我们看switch判断部分,他将字符串进行了hash计算,最终,还是通过数值进行的判断,我们知道,同一个字符串的Hash值肯定是相同的,但是呢,反过来一样吗?那当然肯定不一样,那是小概率事件,不过,通过这个编译的源码可以看出,还是对这些小概率做了处理,那就是在case语句中,进行equals的判断,如果出现小概率事件了,不要紧,我们再判断一下值是否一样,如果这两个都满足了,我们就给个flag值,也就是byte0。
这编译代码真好玩,又来一个switch继续判断,哈哈,还是挺奇妙的,代码不难,大家自己看看,反正,我觉得是非常的有趣。

猜你喜欢

转载自blog.csdn.net/u013000152/article/details/72872080