コンパイル時にジェネリック型がJavaコードから消去されていることはよく知っています。 getGenericType
などの実装に1.5 + JVMが使用する情報(属性)は何ですか?ジェネリック型はどこにJavaクラスファイルに保存されていますか?
答えて
これらは属性Signature
に格納されています。 updated Java Virtual Machine Specificationのセクション4.8.8およびフィールドタイプシグネチャのフォーマットについてはセクション4.4.4を参照してください。
はここjavap -verbose java.util.Map
を使用した例です:
public interface java.util.Map
SourceFile: "Map.java"
Signature: length = 0x2
00 1E
[other attributes omitted]
ここSignature
属性を指定します(あなたはこのようにビッグエンディアンを読めば、JVMクラスファイル形式のすべての整数の数量のようなもの)定数プール値#30( 30 = 0x1E)。そこで、見てみましょう。
const #30 = Asciz <K:Ljava/lang/Object;V:Ljava/lang/Object;>Ljava/lang/Object;;
4.4.4で指定された文法のコンテキストでこれを読んでください。したがって、これは2種類のパラメータ、K extends java.lang.Object
とV extends java.lang.Object
を使用します。型自体(Map
)もクラスjava.lang.Object
を継承し、インターフェイスはありません。
実際にJavaジェネリックはtype erasureによって実装されているため、バイトコードには型情報はありません。例えば
は、のは、非一般的な形式で見て2 List
フィールドを宣言したクラス、ジェネリックに1つ、他を見てみましょう:
class NonGeneric {
List list;
}
そして、いずれの場合も
class Generic {
List<String> list;
}
得られたバイトコードは以下の通りです:
Code:
Stack=3, Locals=1, Args_size=1
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: aload_0
5: new #2; //class java/util/ArrayList
8: dup
9: invokespecial #3; //Method java/util/ArrayList."<init>":()V
12: putfield #4; //Field list:Ljava/util/List;
15: return
何referenはありません(ArrayList
でもList
でも使用されているタイプのString
)に変更します。したがって、ジェネリックが実際にタイプ消去によって実装されていることがわかります。
しかし、定数プールを見ると、違いがわかります。
非ジェネリック定数プール:
Constant pool:
const #1 = Method #6.#15; // java/lang/Object."<init>":()V
const #2 = class #16; // java/util/ArrayList
const #3 = Method #2.#15; // java/util/ArrayList."<init>":()V
const #4 = Field #5.#17; // NonGeneric.list:Ljava/util/List;
const #5 = class #18; // NonGeneric
const #6 = class #19; // java/lang/Object
const #7 = Asciz list;
const #8 = Asciz Ljava/util/List;;
const #9 = Asciz <init>;
const #10 = Asciz ()V;
// snip the rest //
ジェネリック定数プール:
Constant pool:
const #1 = Method #6.#17; // java/lang/Object."<init>":()V
const #2 = class #18; // java/util/ArrayList
const #3 = Method #2.#17; // java/util/ArrayList."<init>":()V
const #4 = Field #5.#19; // Generic.list:Ljava/util/List;
const #5 = class #20; // Generic
const #6 = class #21; // java/lang/Object
const #7 = Asciz list;
const #8 = Asciz Ljava/util/List;;
const #9 = Asciz Signature;
const #10 = Asciz Ljava/util/List<Ljava/lang/String;>;;
const #11 = Asciz <init>;
const #12 = Asciz ()V;
// snip the rest//
見ることができるように2つの余分な定数があり、Generic
クラスでは、私たちが見ることができ、#9
および#10
の定数プールにあり、List
は汎用タイプString
です。
(そして、私はChris Jester-Young's answerから学んだ新しい知識を取り入れた)クラスファイルの解体でさらに探し
は、一定の#10を参照するには、右Generic
クラスのCode: block
前にそこにあります
java.util.List list;
Signature: length = 0x2
00 0A
進値0A
は、定数プール#10
を指し、小数で10
ある:
const #10 = Asciz Ljava/util/List<Ljava/lang/String;>;;
したがって、フィールドが汎用タイプであることを示すために、定数プールからの情報が使用されます。
- 1. オープンなジェネリック型を配列に保存していますか?
- 2. MacではどこにJavaシステムのプロパティが保存されていますか?
- 3. IPB4 - グループ名はどこに保存されていますか?
- 4. CloudWatchログデータはどこに保存されていますか?
- 5. コアダンプファイルはどこに保存されていますか?
- 6. ロケールのリソースはどこに保存されていますか?
- 7. memcachedはどこに保存されていますか?
- 8. EventListenerはどこに保存されていますか?
- 9. phonegap - ファイルはどこに保存されていますか?
- 10. gitデータベースファイルはどこに保存されていますか?
- 11. Android:データベースファイルはどこに保存されていますか?
- 12. TortoiseHg拡張はどこに保存されていますか?
- 13. Alfresco PDFプレビューはどこに保存されていますか?
- 14. IDはどこに保存されていますか?
- 15. KeyChainデータはどこに保存されていますか?
- 16. メソッドローカル変数はどこに保存されていますか?
- 17. .pickleファイルはどこに保存されていますか?
- 18. SQLQuery1.sqlはどこに保存されていますか?
- 19. :コマンド履歴はどこに保存されていますか?
- 20. Jcommentsのデータはどこに保存されていますか?
- 21. ModX Evolution:SMTPパスワードはどこに保存されていますか?
- 22. CDEダッシュボードファイルはどこに保存されていますか?
- 23. Wordpress - カスタムフィールドはどこに保存されていますか?
- 24. テキストファイルはどこに保存されていますか?
- 25. JSESSIONIDはどこに保存されていますか? (JavaEE)
- 26. クロージャー、値はどこに保存されていますか?
- 27. Properties.Settings.Defaultはどこに保存されていますか?
- 28. ServiceWorkerのデータはどこに保存されていますか?
- 29. HttpSessionデータはどこに保存されていますか?
- 30. Xcode 8テンプレートはどこに保存されていますか?