Java の class ファイルのバージョンを調べる Ruby スクリプト
Java の .class ファイルのバージョンを確認する必要があったので
さくっと Ruby スクリプトを書いた。
[class-version-checker.rb]
#!ruby ARGV.each { |path| open(path, "rb") { |file| a = file.read(10) p "#{a[6]*0xff+a[7]}.#{a[4]*0xff+a[5]}" } }
実行例
$ ruby class-version-checker.rb target.class "49.0"
こういう細かいスクリプトをサクっと書けるのが
Ruby のいいところだなぁとうっとりしていたら
file コマンドで取得できるが後からわかってがっかりしたという話。
$ file target.class target.class: compiled Java class data, version 49.0
がっかりしたので
version 49.0 (Java 1.5)の命令セットと
version 48.0 (Java 1.4)の命令セットは同じものだと聞いたことがあったので
バージョン情報だけ書き換えれば
Java 1.5 でコンパイルした class ファイルが Java 1.4 で
動かせるとも思ったので実験した。
[Target.java]
public class Target { public static void main(String[] args) { System.out.println("Hello World"); } }
[class-version-changer.rb]
#!ruby ARGV.each { |path| open(path, "rb") { |file| a = file.read if a[7] == 49 then a[7] = 48 open(path + ".new", "wb").write a puts "path" + ".new" end } }
$ javac -version javac 1.5.0_11 ... $ javac Target.java
Java 1.5 で実行
$ java -version java version "1.5.0_11" ... $ java Target Hello World
Java 1.4 で実行
$ java -version java version "1.4.2_14" $ java Target Exception in thread "main" java.lang.UnsupportedClassVersionError: Target (Unsupported major.minor version 49.0) ...
$ ruby class-version-changer.rb Target.class Target.class.new $ mv Target.class Target.class.old $ mv Target.class.new Target.class $ java Target Hello World
ホントに動いちゃった。
試したプログラムは簡単な Hello World プログラムで
複雑なプログラムでどうなるかはわからないので注意。