
javaファイルをコンパイルするとclassファイルができます
このclassファイルからデコンパイル、つまりソースコードの復活ができるって知ってましたか?
デコンパイルできる2つのツールについて紹介します
>> [Java]文字列連結で、+演算子 or StringBuilder どちらを使うべき?
◆対象読者
- Javaの知識が少しはある人
 - バイトコードって聞いたことある人
 - 前回の記事を読んだ人
 - classファイルからのデコンパイルを知りたい人
 - 基本的なDOSコマンドやshellコマンドを使える人
 
◆解決できるかも知れないお悩み
- Jadの使い方
 - JD-GUIの使い方
 - JadとJD-GUIの違い
 
Contents
Javaのデコンパイルツール
僕が知ってるのはこの2つ
- Jad
 - JD-GUI
 
どちらもclassファイルからソースコードを起こしてくれます
JadとJD-GUIの違い
どっちもデコンパイルしてくれますが、出力されるソースコードは少し違います
classファイルの内容をそれぞれに解釈した上でソースコードにしてくれていますので、もちろん処理は同じです
Jadはバイトコードに、JD-GUIはソースコードに寄っている感じですね
使いやすいのはJD-GUIの方だと思いますが、バイトコードが想像し易いJadの方が僕は好きです
その辺はお好みに合わせて使い分ければ良いでしょう
Jadについて
ダウンロード
公式サイトはこちらなので、各自のプラットフォームに合わせてダウンロードしてください。
Windowsの場合はこれですね
Windows7でもこれで動きました
Jad 1.5.8g for Windows 9x/NT/2000 on Intel platform
Macならこれですね
Jad 1.5.8g for Mac OS X 10.4.6 on Intel platform
使い方
Windowsの場合はダウンロードファイルはzipなので解凍すれば即使えます
jad.exeが入っているフォルダにPATHを通すか、既にPATHの通っているフォルダにjad.exeを入れるかですね
PATHを通すのが面倒なら、classファイルと同じ場所にjad.exeを置けばいいでしょう
- コマンドプロンプト(Macならターミナル)起動
 - jad.exeの置いてあるディレクトリへ移動
豆知識
Windowsの場合、エクスプローラーのアドレスバーでcmd+Enterと打てば、そのフォルダがカレントとなっている状態でDOSプロンプトが起動します
 jad classname.classとかjad *.classと打てば、拡張子がjadのテキストファイルができます- このjadファイルにデコンパイルしたソースコードが書かれています
 
コマンドプション
> jad -help
と打てば、jadが持つオプションが沢山でてきますが…..、面倒なので、1個だけピックアップします
> jad -a classname.class
バイトコードをコメントとして表示してくれるので、ソースコードと併せて見たい時に使います
元のソースコード
public class SamplePlus {
    //===========================================================
    // ノーマル系
    //===========================================================
    //***********************************************************
    // 大分類:1行で連結
    // 中分類:String変数使用
    // 小分類:---
    //***********************************************************
    public static String Test11() {
        String  hoge = "aiueo";
        String  fuga = "kakikukeko";
        String  piyo = "sasisuseso";
        String  gabo;
        gabo = hoge + fuga + piyo;
        return gabo;
    }
    //***********************************************************
    // 大分類:1行で連結
    // 中分類:文字列使用
    // 小分類:---
    //***********************************************************
    public static String Test12() {
        String  gabo;
        gabo = "aiueo" + "kakikukeko" + "sasisuseso";
        return gabo;
    }
    //***********************************************************
    // 大分類:複数行で連結
    // 中分類:String変数使用
    // 小分類:---
    //***********************************************************
    public static String Test13() {
        String  hoge = "aiueo";
        String  fuga = "kakikukeko";
        String  piyo = "sasisuseso";
        String  gabo;
        gabo = "";
        gabo += hoge;
        gabo += fuga;
        gabo += piyo;
        return gabo;
    }
    //***********************************************************
    // 大分類:複数行で連結
    // 中分類:文字列使用
    // 小分類:---
    //***********************************************************
    public static String Test14() {
        String  hoge = "aiueo";
        String  fuga = "kakikukeko";
        String  piyo = "sasisuseso";
        String  gabo;
        gabo = "";
        gabo += "aiueo";
        gabo += "kakikukeko";
        gabo += "sasisuseso";
        return gabo;
    }
    //***********************************************************
    // 大分類:1行で連結
    // 中分類:String変数と文字列の混合使用
    // 小分類:---
    //***********************************************************
    public static String Test15() {
        String  hoge = "aiueo";
        String  piyo = "sasisuseso";
        String  gabo;
        gabo = hoge + "kakikukeko" + piyo + "tatituteto";
        return gabo;
    }
    //===========================================================
    // ループ系
    //===========================================================
    //***********************************************************
    // 大分類:ループ使用
    // 中分類:String変数使用
    // 小分類:ループの【外】でString変数定義
    //       :代入系
    //***********************************************************
    public static String Test21() {
        String  hoge = "aiueo";
        String  gabo = "";
        for(int i=0; i < 100; i++) {
            gabo = hoge;
        }
        return gabo;
    }
    //***********************************************************
    // 大分類:ループ使用
    // 中分類:String変数使用
    // 小分類:ループの【外】でString変数定義
    //       :足していく系
    //***********************************************************
    public static String Test22() {
        String  hoge = "aiueo";
        String  gabo = "";
        for(int i=0; i < 100; i++) {
            gabo += hoge;
        }
        return gabo;
    }
    //***********************************************************
    // 大分類:ループ使用
    // 中分類:String変数使用
    // 小分類:ループの【中】でString変数定義
    //       :代入系
    //***********************************************************
    public static String Test23() {
        String  gabo = "";
        for(int i=0; i < 100; i++) {
            String  hoge = "aiueo";
            gabo = hoge;
        }
        return gabo;
    }
    //***********************************************************
    // 大分類:ループ使用
    // 中分類:String変数使用
    // 小分類:ループの【中】でString変数定義
    //       :足していく系
    //***********************************************************
    public static String Test24() {
        String  gabo = "";
        for(int i=0; i < 100; i++) {
            String  hoge = "aiueo";
            gabo += hoge;
        }
        return gabo;
    }
    //***********************************************************
    // 大分類:ループ使用
    // 中分類:文字列使用
    // 小分類:---
    //       :代入系
    //***********************************************************
    public static String Test25() {
        String  gabo = "";
        for(int i=0; i < 100; i++) {
            gabo = "aiueo";
        }
        return gabo;
    }
    //***********************************************************
    // 大分類:ループ使用
    // 中分類:文字列使用
    // 小分類:---
    //       :足していく系
    //***********************************************************
    public static String Test26() {
        String  gabo = "";
        for(int i=0; i < 100; i++) {
            gabo += "aiueo";
        }
        return gabo;
    }
}
出力内容(ノーマル)
newのタイミングが分かるので、ループ文の中で毎回newしていないかとかが分かりやすいですね
> jad SamplePlus.class
// 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:   SamplePlus.java
public class SamplePlus
{
    public SamplePlus()
    {
    }
    public static String Test11()
    {
        String hoge = "aiueo";
        String fuga = "kakikukeko";
        String piyo = "sasisuseso";
        String gabo = (new StringBuilder()).append(hoge).append(fuga).append(piyo).toString();
        return gabo;
    }
    public static String Test12()
    {
        String gabo = "aiueokakikukekosasisuseso";
        return gabo;
    }
    public static String Test13()
    {
        String hoge = "aiueo";
        String fuga = "kakikukeko";
        String piyo = "sasisuseso";
        String gabo = "";
        gabo = (new StringBuilder()).append(gabo).append(hoge).toString();
        gabo = (new StringBuilder()).append(gabo).append(fuga).toString();
        gabo = (new StringBuilder()).append(gabo).append(piyo).toString();
        return gabo;
    }
    public static String Test14()
    {
        String hoge = "aiueo";
        String fuga = "kakikukeko";
        String piyo = "sasisuseso";
        String gabo = "";
        gabo = (new StringBuilder()).append(gabo).append("aiueo").toString();
        gabo = (new StringBuilder()).append(gabo).append("kakikukeko").toString();
        gabo = (new StringBuilder()).append(gabo).append("sasisuseso").toString();
        return gabo;
    }
    public static String Test15()
    {
        String hoge = "aiueo";
        String piyo = "sasisuseso";
        String gabo = (new StringBuilder()).append(hoge).append("kakikukeko").append(piyo).append("tatituteto").toString();
        return gabo;
    }
    public static String Test21()
    {
        String hoge = "aiueo";
        String gabo = "";
        for(int i = 0; i < 100; i++)
            gabo = hoge;
        return gabo;
    }
    public static String Test22()
    {
        String hoge = "aiueo";
        String gabo = "";
        for(int i = 0; i < 100; i++)
            gabo = (new StringBuilder()).append(gabo).append(hoge).toString();
        return gabo;
    }
    public static String Test23()
    {
        String gabo = "";
        for(int i = 0; i < 100; i++)
        {
            String hoge = "aiueo";
            gabo = hoge;
        }
        return gabo;
    }
    public static String Test24()
    {
        String gabo = "";
        for(int i = 0; i < 100; i++)
        {
            String hoge = "aiueo";
            gabo = (new StringBuilder()).append(gabo).append(hoge).toString();
        }
        return gabo;
    }
    public static String Test25()
    {
        String gabo = "";
        for(int i = 0; i < 100; i++)
            gabo = "aiueo";
        return gabo;
    }
    public static String Test26()
    {
        String gabo = "";
        for(int i = 0; i < 100; i++)
            gabo = (new StringBuilder()).append(gabo).append("aiueo").toString();
        return gabo;
    }
}
出力内容(-aオプション)
-aオプションを付けることにより、バイトコードとソースコードを併せて見ることができるので、細かい部分も分かりやすいですね
> jad -a SamplePlus.class
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) annotate 
// Source File Name:   SamplePlus.java
public class SamplePlus
{
    public SamplePlus()
    {
    //    0    0:aload_0         
    //    1    1:invokespecial   #1   
    //    2    4:return          
    }
    public static String Test11()
    {
        String hoge = "aiueo";
    //    0    0:ldc1            #2   
    //    1    2:astore_0        
        String fuga = "kakikukeko";
    //    2    3:ldc1            #3   
    //    3    5:astore_1        
        String piyo = "sasisuseso";
    //    4    6:ldc1            #4   
    //    5    8:astore_2        
        String gabo = (new StringBuilder()).append(hoge).append(fuga).append(piyo).toString();
    //    6    9:new             #5   
    //    7   12:dup             
    //    8   13:invokespecial   #6   
    //    9   16:aload_0         
    //   10   17:invokevirtual   #7   
    //   11   20:aload_1         
    //   12   21:invokevirtual   #7   
    //   13   24:aload_2         
    //   14   25:invokevirtual   #7   
    //   15   28:invokevirtual   #8   
    //   16   31:astore_3        
        return gabo;
    //   17   32:aload_3         
    //   18   33:areturn         
    }
    public static String Test12()
    {
        String gabo = "aiueokakikukekosasisuseso";
    //    0    0:ldc1            #9   
    //    1    2:astore_0        
        return gabo;
    //    2    3:aload_0         
    //    3    4:areturn         
    }
    public static String Test13()
    {
        String hoge = "aiueo";
    //    0    0:ldc1            #2   
    //    1    2:astore_0        
        String fuga = "kakikukeko";
    //    2    3:ldc1            #3   
    //    3    5:astore_1        
        String piyo = "sasisuseso";
    //    4    6:ldc1            #4   
    //    5    8:astore_2        
        String gabo = "";
    //    6    9:ldc1            #10  
    //    7   11:astore_3        
        gabo = (new StringBuilder()).append(gabo).append(hoge).toString();
    //    8   12:new             #5   
    //    9   15:dup             
    //   10   16:invokespecial   #6   
    //   11   19:aload_3         
    //   12   20:invokevirtual   #7   
    //   13   23:aload_0         
    //   14   24:invokevirtual   #7   
    //   15   27:invokevirtual   #8   
    //   16   30:astore_3        
        gabo = (new StringBuilder()).append(gabo).append(fuga).toString();
    //   17   31:new             #5   
    //   18   34:dup             
    //   19   35:invokespecial   #6   
    //   20   38:aload_3         
    //   21   39:invokevirtual   #7   
    //   22   42:aload_1         
    //   23   43:invokevirtual   #7   
    //   24   46:invokevirtual   #8   
    //   25   49:astore_3        
        gabo = (new StringBuilder()).append(gabo).append(piyo).toString();
    //   26   50:new             #5   
    //   27   53:dup             
    //   28   54:invokespecial   #6   
    //   29   57:aload_3         
    //   30   58:invokevirtual   #7   
    //   31   61:aload_2         
    //   32   62:invokevirtual   #7   
    //   33   65:invokevirtual   #8   
    //   34   68:astore_3        
        return gabo;
    //   35   69:aload_3         
    //   36   70:areturn         
    }
    public static String Test14()
    {
        String hoge = "aiueo";
    //    0    0:ldc1            #2   
    //    1    2:astore_0        
        String fuga = "kakikukeko";
    //    2    3:ldc1            #3   
    //    3    5:astore_1        
        String piyo = "sasisuseso";
    //    4    6:ldc1            #4   
    //    5    8:astore_2        
        String gabo = "";
    //    6    9:ldc1            #10  
    //    7   11:astore_3        
        gabo = (new StringBuilder()).append(gabo).append("aiueo").toString();
    //    8   12:new             #5   
    //    9   15:dup             
    //   10   16:invokespecial   #6   
    //   11   19:aload_3         
    //   12   20:invokevirtual   #7   
    //   13   23:ldc1            #2   
    //   14   25:invokevirtual   #7   
    //   15   28:invokevirtual   #8   
    //   16   31:astore_3        
        gabo = (new StringBuilder()).append(gabo).append("kakikukeko").toString();
    //   17   32:new             #5   
    //   18   35:dup             
    //   19   36:invokespecial   #6   
    //   20   39:aload_3         
    //   21   40:invokevirtual   #7   
    //   22   43:ldc1            #3   
    //   23   45:invokevirtual   #7   
    //   24   48:invokevirtual   #8   
    //   25   51:astore_3        
        gabo = (new StringBuilder()).append(gabo).append("sasisuseso").toString();
    //   26   52:new             #5   
    //   27   55:dup             
    //   28   56:invokespecial   #6   
    //   29   59:aload_3         
    //   30   60:invokevirtual   #7   
    //   31   63:ldc1            #4   
    //   32   65:invokevirtual   #7   
    //   33   68:invokevirtual   #8   
    //   34   71:astore_3        
        return gabo;
    //   35   72:aload_3         
    //   36   73:areturn         
    }
    public static String Test15()
    {
        String hoge = "aiueo";
    //    0    0:ldc1            #2   
    //    1    2:astore_0        
        String piyo = "sasisuseso";
    //    2    3:ldc1            #4   
    //    3    5:astore_1        
        String gabo = (new StringBuilder()).append(hoge).append("kakikukeko").append(piyo).append("tatituteto").toString();
    //    4    6:new             #5   
    //    5    9:dup             
    //    6   10:invokespecial   #6   
    //    7   13:aload_0         
    //    8   14:invokevirtual   #7   
    //    9   17:ldc1            #3   
    //   10   19:invokevirtual   #7   
    //   11   22:aload_1         
    //   12   23:invokevirtual   #7   
    //   13   26:ldc1            #11  
    //   14   28:invokevirtual   #7   
    //   15   31:invokevirtual   #8   
    //   16   34:astore_2        
        return gabo;
    //   17   35:aload_2         
    //   18   36:areturn         
    }
    public static String Test21()
    {
        String hoge = "aiueo";
    //    0    0:ldc1            #2   
    //    1    2:astore_0        
        String gabo = "";
    //    2    3:ldc1            #10  
    //    3    5:astore_1        
        for(int i = 0; i < 100; i++)
    //*   4    6:iconst_0        
    //*   5    7:istore_2        
    //*   6    8:iload_2         
    //*   7    9:bipush          100
    //*   8   11:icmpge          22
            gabo = hoge;
    //    9   14:aload_0         
    //   10   15:astore_1        
    //   11   16:iinc            2  1
    //*  12   19:goto            8
        return gabo;
    //   13   22:aload_1         
    //   14   23:areturn         
    }
    public static String Test22()
    {
        String hoge = "aiueo";
    //    0    0:ldc1            #2   
    //    1    2:astore_0        
        String gabo = "";
    //    2    3:ldc1            #10  
    //    3    5:astore_1        
        for(int i = 0; i < 100; i++)
    //*   4    6:iconst_0        
    //*   5    7:istore_2        
    //*   6    8:iload_2         
    //*   7    9:bipush          100
    //*   8   11:icmpge          39
            gabo = (new StringBuilder()).append(gabo).append(hoge).toString();
    //    9   14:new             #5   
    //   10   17:dup             
    //   11   18:invokespecial   #6   
    //   12   21:aload_1         
    //   13   22:invokevirtual   #7   
    //   14   25:aload_0         
    //   15   26:invokevirtual   #7   
    //   16   29:invokevirtual   #8   
    //   17   32:astore_1        
    //   18   33:iinc            2  1
    //*  19   36:goto            8
        return gabo;
    //   20   39:aload_1         
    //   21   40:areturn         
    }
    public static String Test23()
    {
        String gabo = "";
    //    0    0:ldc1            #10  
    //    1    2:astore_0        
        for(int i = 0; i < 100; i++)
    //*   2    3:iconst_0        
    //*   3    4:istore_1        
    //*   4    5:iload_1         
    //*   5    6:bipush          100
    //*   6    8:icmpge          22
        {
            String hoge = "aiueo";
    //    7   11:ldc1            #2   
    //    8   13:astore_2        
            gabo = hoge;
    //    9   14:aload_2         
    //   10   15:astore_0        
        }
    //   11   16:iinc            1  1
    //*  12   19:goto            5
        return gabo;
    //   13   22:aload_0         
    //   14   23:areturn         
    }
    public static String Test24()
    {
        String gabo = "";
    //    0    0:ldc1            #10  
    //    1    2:astore_0        
        for(int i = 0; i < 100; i++)
    //*   2    3:iconst_0        
    //*   3    4:istore_1        
    //*   4    5:iload_1         
    //*   5    6:bipush          100
    //*   6    8:icmpge          39
        {
            String hoge = "aiueo";
    //    7   11:ldc1            #2   
    //    8   13:astore_2        
            gabo = (new StringBuilder()).append(gabo).append(hoge).toString();
    //    9   14:new             #5   
    //   10   17:dup             
    //   11   18:invokespecial   #6   
    //   12   21:aload_0         
    //   13   22:invokevirtual   #7   
    //   14   25:aload_2         
    //   15   26:invokevirtual   #7   
    //   16   29:invokevirtual   #8   
    //   17   32:astore_0        
        }
    //   18   33:iinc            1  1
    //*  19   36:goto            5
        return gabo;
    //   20   39:aload_0         
    //   21   40:areturn         
    }
    public static String Test25()
    {
        String gabo = "";
    //    0    0:ldc1            #10  
    //    1    2:astore_0        
        for(int i = 0; i < 100; i++)
    //*   2    3:iconst_0        
    //*   3    4:istore_1        
    //*   4    5:iload_1         
    //*   5    6:bipush          100
    //*   6    8:icmpge          20
            gabo = "aiueo";
    //    7   11:ldc1            #2   
    //    8   13:astore_0        
    //    9   14:iinc            1  1
    //*  10   17:goto            5
        return gabo;
    //   11   20:aload_0         
    //   12   21:areturn         
    }
    public static String Test26()
    {
        String gabo = "";
    //    0    0:ldc1            #10  
    //    1    2:astore_0        
        for(int i = 0; i < 100; i++)
    //*   2    3:iconst_0        
    //*   3    4:istore_1        
    //*   4    5:iload_1         
    //*   5    6:bipush          100
    //*   6    8:icmpge          37
            gabo = (new StringBuilder()).append(gabo).append("aiueo").toString();
    //    7   11:new             #5   
    //    8   14:dup             
    //    9   15:invokespecial   #6   
    //   10   18:aload_0         
    //   11   19:invokevirtual   #7   
    //   12   22:ldc1            #2   
    //   13   24:invokevirtual   #7   
    //   14   27:invokevirtual   #8   
    //   15   30:astore_0        
    //   16   31:iinc            1  1
    //*  17   34:goto            5
        return gabo;
    //   18   37:aload_0         
    //   19   38:areturn         
    }
}
                                                                                          
JD-GUI
ダウンロード
公式サイトはこちらなので、各自のプラットフォームに合わせてダウンロードしてください。
Windowsの場合はこれですね
Windows7でもこれで動きました
jd-gui-windows-1.4.0.zip
Macならこれですね
jd-gui-osx-1.4.0.tar
使い方
Jadと違ってGUIですので使い方は簡単です
- jd-gui.exeをダブルクリックして起動
 - 起動したらウィンドウが開きます
 - classファイルをウィンドウへドラッグ&ドロップ
 - これで終わりです
保存やコピーができますので、必要に応じて操作してください 
元のソースコード
※Jadの場合と同じ
出力内容
Jadに比べると、普通のソースコードっぽいですね
public class SamplePlus
{
  public static String Test11()
  {
    String hoge = "aiueo";
    String fuga = "kakikukeko";
    String piyo = "sasisuseso";
    
    String gabo = hoge + fuga + piyo;
    
    return gabo;
  }
  
  public static String Test12()
  {
    String gabo = "aiueokakikukekosasisuseso";
    
    return gabo;
  }
  
  public static String Test13()
  {
    String hoge = "aiueo";
    String fuga = "kakikukeko";
    String piyo = "sasisuseso";
    
    String gabo = "";
    gabo = gabo + hoge;
    gabo = gabo + fuga;
    gabo = gabo + piyo;
    
    return gabo;
  }
  
  public static String Test14()
  {
    String hoge = "aiueo";
    String fuga = "kakikukeko";
    String piyo = "sasisuseso";
    
    String gabo = "";
    gabo = gabo + "aiueo";
    gabo = gabo + "kakikukeko";
    gabo = gabo + "sasisuseso";
    
    return gabo;
  }
  
  public static String Test15()
  {
    String hoge = "aiueo";
    String piyo = "sasisuseso";
    
    String gabo = hoge + "kakikukeko" + piyo + "tatituteto";
    
    return gabo;
  }
  
  public static String Test21()
  {
    String hoge = "aiueo";
    String gabo = "";
    for (int i = 0; i < 100; i++) {
      gabo = hoge;
    }
    return gabo;
  }
  
  public static String Test22()
  {
    String hoge = "aiueo";
    String gabo = "";
    for (int i = 0; i < 100; i++) {
      gabo = gabo + hoge;
    }
    return gabo;
  }
  
  public static String Test23()
  {
    String gabo = "";
    for (int i = 0; i < 100; i++)
    {
      String hoge = "aiueo";
      gabo = hoge;
    }
    return gabo;
  }
  
  public static String Test24()
  {
    String gabo = "";
    for (int i = 0; i < 100; i++)
    {
      String hoge = "aiueo";
      gabo = gabo + hoge;
    }
    return gabo;
  }
  
  public static String Test25()
  {
    String gabo = "";
    for (int i = 0; i < 100; i++) {
      gabo = "aiueo";
    }
    return gabo;
  }
  
  public static String Test26()
  {
    String gabo = "";
    for (int i = 0; i < 100; i++) {
      gabo = gabo + "aiueo";
    }
    return gabo;
  }
}
 
さいごに、

書いたソースコードが効率の悪いものになっていないか?
バイトコードになった時に思ったような形になっているか?
とかを確認することができます
プログラミングに慣れてきて余裕が出てきたら、ソースコードを書きっぱなしにするだけじゃなく細かい部分も気にするようになると、プログラミングは更に更に更に上達しますよ!
なぜそう書くべきなのか
という事が分かるようになるっていうのは、とっても大切ですよ!
プログラミング のレッスンに興味がある方、レッスン内容を聞いてみたい方、なんなりとお問い合わせください。
無料体験レッスンもありますのでお気軽にどうぞ!!!
