2006年01月11日

Java地獄案内

 ほとんどありえないことだが、仮に、あなたはJavaのバイトコードとクラスローダを理解しているものとしよう。もし理解していなければ、この先を読むのは時間の無駄だ。

 下をご覧いただきたい。

0: new #75; //class java/lang/StringBuffer
3: dup
4: invokespecial #76; //Method java/lang/StringBuffer."<init>":()V
7: astore_2
8: aload_2
9: ldc #78; //String ^$
11: invokevirtual #82; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/AbstractStringBuilder;

 これはMaven 1.0.2を使ってできたバイトコードだ。そしてこのコードは、どういうわけか知らないが、IBMのJ2SE 5.0ではNoSuchMethodErrorを投げる。AbstractStringBuilder関係らしい。

 問題を絞り込むべく私は、小さいテストコードを使って、これと同様のバイトコードを生成させることを試みた。が、うまくいかない。失敗例を下に示す。

0: new #2; //class java/lang/StringBuffer
3: dup
4: invokespecial #3; //Method java/lang/StringBuffer."<init>":()V
7: astore_1
8: aload_1
9: ldc #4; //String Hello
11: invokevirtual #5; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;

 約1時間の苦闘の末、私はようやく、AbstractStringBuilderが出る理由を発見した。maven-aspectj-pluginに含まれる(というか依存性解決でひっぱってくる)コンパイラのせいだ。

 問題のバイトコードをテストコード上に再現できたので、問題を絞り込むことができた。

 結論からいえば、IBMのJ2SE 5.0は、AbstractStringBuilder関係でSunのRIと互換性がない。上のバイトコードはRIのJavaVMでは問題なく動くが、IBMのJavaVMではNoSuchMethodErrorを投げる(x86/WindowsとPowerPC/Linuxで確認)。

Posted by hajime at 2006年01月11日 04:35
Comments