[Java]JadとJD-GUIのデコンパイルでJVMの気持ちを知ろう!

 

 

こんにちは。ナガオカ(@boot_kt)です。

 

javaファイルをコンパイルするとclassファイルができます

このclassファイルからデコンパイル、つまりソースコードの復活ができるって知ってましたか?

デコンパイルできる2つのツールについて紹介します

この記事のザックリした内容
前回の記事はコレ↓
>> [Java]文字列連結で、+演算子 or StringBuilder どちらを使うべき?
 

◆対象読者

  • Javaの知識が少しはある人
  • バイトコードって聞いたことある人
  • 前回の記事を読んだ人
  • classファイルからのデコンパイルを知りたい人
  • 基本的なDOSコマンドやshellコマンドを使える人

 

◆解決できるかも知れないお悩み

  • Jadの使い方
  • JD-GUIの使い方
  • JadとJD-GUIの違い

 

 

 

 

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を置けばいいでしょう

  1. コマンドプロンプト(Macならターミナル)起動
  2. jad.exeの置いてあるディレクトリへ移動
    豆知識
    Windowsの場合、エクスプローラーのアドレスバーでcmdEnterと打てば、そのフォルダがカレントとなっている状態でDOSプロンプトが起動します
  3. jad classname.class とか jad *.class と打てば、拡張子がjadのテキストファイルができます
  4. このjadファイルにデコンパイルしたソースコードが書かれています

 

コマンドプション

> jad -help

と打てば、jadが持つオプションが沢山でてきますが…..、面倒なので、1個だけピックアップします

-a – JVM命令をコメントとして生成する(注釈)
> 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ですので使い方は簡単です

  1. jd-gui.exeをダブルクリックして起動
  2. 起動したらウィンドウが開きます
  3. classファイルをウィンドウへドラッグ&ドロップ
  4. これで終わりです
    保存やコピーができますので、必要に応じて操作してください

 

元のソースコード

※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;
  }
}

 

広告




 

さいごに、

前回の記事ではjavapでバイトコードを見るだけでしたが、JadやJD-GUIを使ってバイトコードをソースコードの形で見るとさらに分かりやすくなります

書いたソースコードが効率の悪いものになっていないか?
バイトコードになった時に思ったような形になっているか?

とかを確認することができます

プログラミングに慣れてきて余裕が出てきたら、ソースコードを書きっぱなしにするだけじゃなく細かい部分も気にするようになると、プログラミングは更に更に更に上達しますよ!

なぜそう書くべきなのか

という事が分かるようになるっていうのは、とっても大切ですよ!

 


 

プログラミング のレッスンに興味がある方、レッスン内容を聞いてみたい方、なんなりとお問い合わせください。
無料体験レッスンもありますのでお気軽にどうぞ!!!

 

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

ABOUTこの記事をかいた人

Windows/Mac/Linuxを使う現役システムエンジニア&プログラマ。オープン系・組み込み系・制御系・Webシステム系と幅広い案件に携わる。C言語やC#やJava等数多くのコンパイラ言語を経験したが、少し飽きてきたので、最近はRubyやPython、WordPressなどのWeb系を修得中。初心者向けのプログラミング教室も運営中。オンライン・対面・出張等でプログラミングをレッスンします。