2017-12-18 9 views
3

私はいくつかの実験を行うために単純なJavaバイトコードパーサーを作成しましたが、最近は予期せぬ場所で失敗しました。 Javaの1.1.8.16のrt.jarからjava/lang/reflect/Member.javaを読みながら、私のパーサが怒ったMemberは(行方不明ACC_ABSTRACTフラグに注意してください)ので、同様にスタートするので:Java 1.0.2のインターフェイスメンバーにACC_ABSTRACTが設定されていないのはなぜですか?

Classfile Member.class 
    Last modified Aug 8, 2002; size 350 bytes 
    MD5 checksum 9a1aaec8e70e9a2ff9d63331cb0ea34e 
    Compiled from "Member.java" 
public interface java.lang.reflect.Member 
    minor version: 3 
    major version: 45 
    flags: (0x0201) ACC_PUBLIC, ACC_INTERFACE 
... 

のJava 1.2.2.17からのバージョンでは、これを修正し、フラグが設定されています0x0601ACC_ABSTRACT | ACC_INTERFACE | ACC_PUBLIC)。

私は見つけることができる最も古いJVM仕様(うわさによれ1.0.2)は、これは言っている(§4.1を、P 86は、強調追加):

インターフェースが暗黙的に抽象的である(§2.13.1) ;そのACC_ABSTRACTフラグに設定する必要があります。インターフェイスは最終的なものではありません。その実装が完了することは決してできません(2.13.1)。そのため、それはそのフラグセットを持つことができませんでした。 JVM仕様has similar words to say

バージョン9:

ACC_INTERFACEフラグが設定されている場合、ACC_ABSTRACTフラグを設定する必要があり、そしてACC_FINALACC_SUPERACC_ENUM、及びACC_MODULEフラグを設定する必要があります設定しないでください。

Oracle/Sun JVMはこの要件を「必須」にする必要がありますか?もしそうなら、いつ?そうでない場合は、JVMの仕様が必要であると偽っているのはなぜですか?

答えて

4

これはバグJDK-4059153でした。javacがインターフェイス用にACC_ABSTRACTを設定していませんでした。

このバグは1.2で修正されましたが、このバグで既に多くのクラスがコンパイルされていたため、ACC_INTERFACEのすべてのクラスに対してACC_ABSTRACTが自動的に追加されました。これは、新しいクラスファイルの仕様に厳密に従うことが最終的に決定されたJava 6まで機能しました。ただし、以前のバージョンのクラスファイルとの下位互換性については、これまでのところ回避方法が存在します。classFileParser.cpp

if ((flags & JVM_ACC_INTERFACE) && _major_version < JAVA_6_VERSION) { 
     // Set abstract bit for old class files for backward compatibility 
     flags |= JVM_ACC_ABSTRACT; 
    } 
+0

ありがとうございます@apangin。 * 2つのリンクを使って私の謎を解きほぐしてください。 – 0xbe5077ed

0

それはなぜ私にははっきりしていないが、私は は、Java 9のjavacでそれらをコンパイルし、手動でFoo0x200access_flagsを編集し、次のクラスを作成することによって、実験;その後、手動で何が起こるかを見るために異なるJavaのバージョンによってminor_versionmajor_versionサイクリング:

interface Foo { } 

class Bar implements Foo { 
    public static void main(String[] args) { 
     System.out.println("BAZ"); 
    } 
} 

結果: "誤る"

╭──────╥───────┬───────┬─────╮ 
│ Java ║ minor │ major │ out │ 
╞══════╬═══════╪═══════╪═════╡ 
│ 1.1 ║ 03 │ 2d │ BAZ │ 
│ 1.2 ║  " │  " │ BAZ │ 
│ 1.3 ║  " │ 2e │ BAZ │ 
│ 1.4 ║ 00 │ 2f │ BAZ │ 
│ 5 ║ 00 │ 31 │ BAZ │ 
│ 6 ║ 00 │ 32 │ err │ 
│ 7 ║ 00 │ 33 │ err │ 
│ 8 ║ 00 │ 34 │ err │ 
│ 9 ║ 00 │ 35 │ err │ 
└──────╨───────┴───────┴─────┘ 

は本当にこのように出力します:

Error: LinkageError occurred while loading main class Bar 
    java.lang.ClassFormatError: Illegal class modifiers in class Foo: 0x200 

だから私は彼らが最終的にJava 6でそれを強制することになったと思う。

まだ分かりません。

関連する問題