プログラマメモ2 - programmer no memo2

groovyからデコンパイラツールのjadをぐるぐるまわしてみる - できはよくない。 2007/08/22
2007/08/23

デコンパイラツールのjadを使うスクリプトをgroovyで書いてみた。
もちろん、groovyである必要はまったくないけど。

にあるサンプルを利用して書くとjadを使っていると途中で固まる現象に出会った。
理由は、なぜかよくわからないけど、どうも標準出力と標準エラーの両方の出力があるとそうなるっぽい。でも、ほんとのところは追求していません。

ちょっとだめった感じのコードは下記のような感じ。
def command = "ジャド"
def proc = command.execute()
proc.waitFor()


って何故このコードでだめなのかよくわからない。

追記:20070823 これはgroovyだからというわけではないです。groovyからは、Runtime.getRuntime().exec(self)とjava.lang.Runtimeを使用しているだけだから。

で、試行錯誤した結果、java5から導入されたProcessBuilderを使用してみてうまく動いた。


ただし、単に使うだけではなく、redirectErrorStreamをtrueにしたのが肝要ぽいです。
java5のjavadocには以下のように書いてありました。

このプロパティが true の場合、このオブジェクトの start() メソッドでそれ以降起動されたサブプロセスにより生成されるエラー出力は、標準出力とマージされます。これにより、Process.getInputStream() メソッドを使って、エラー出力と標準出力の両方を読み取ることができます。マージにより、エラーメッセージと対応する出力との相関を示すのが容易になります。初期値は false です。
javadoc api


あとファイル操作で参考

ディレクトリのファイルを再帰的にとれるのが、eachFileRecurse。
これすごく便利。

いまいちgroovyのStringの操作がよくわかってないので、おいおい練習していこうと思います。

かっこわるいけど、以下groovyコード。
import java.io.*;


if(this.args.length < 0){
println "Usage: decompile_by_jad.groovy [targetdirname]"
System.exit(0);
}

def dir = args[0]


def jad_path = "jad"; // maybe exist current dir....

new File(dir).eachFileRecurse{ f ->

if((f as String).endsWith(".class") && !( (f as String).contains('$') )){
println "=====================================";
println f;

def command = "${ jad_path } -r -o -s java ${f as String}"

try {
println "execute ${ command }";
ProcessBuilder builder = new ProcessBuilder( (command as String).split(' ') );
builder.redirectErrorStream( true );
Process process = builder.start();
InputStream stream = process.getInputStream();
while (true) {
int c = stream.read();
if (c == -1) {
stream.close();
break;
}
}
} catch (e) {
println e;
}
}
}

: