javapで列挙型を逆アセンブルすると、列挙型の暗黙的なコンストラクタ引数が存在しないように見えます。ここでjavapで逆アセンブルされた列挙型でコンストラクタ引数が表示されない
は、列挙型です:
enum Foo { X }
私はコンパイルして、このコマンドを使用して、(Javaの8u60上で)これを逆アセンブル:
javac Foo.java && javap -c -p Foo
そして、ここでは、私が手に出力されます:
final class Foo extends java.lang.Enum<Foo> {
public static final Foo X;
private static final Foo[] $VALUES;
public static Foo[] values();
Code:
0: getstatic #1 // Field $VALUES:[LFoo;
3: invokevirtual #2 // Method "[LFoo;".clone:()Ljava/lang/Object;
6: checkcast #3 // class "[LFoo;"
9: areturn
public static Foo valueOf(java.lang.String);
Code:
0: ldc #4 // class Foo
2: aload_0
3: invokestatic #5 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
6: checkcast #4 // class Foo
9: areturn
private Foo(); // <--- here
Code:
0: aload_0
1: aload_1
2: iload_2
3: invokespecial #6 // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V
6: return
static {};
Code:
0: new #4 // class Foo
3: dup
4: ldc #7 // String X
6: iconst_0
7: invokespecial #8 // Method "<init>":(Ljava/lang/String;I)V
10: putstatic #9 // Field X:LFoo;
13: iconst_1
14: anewarray #4 // class Foo
17: dup
18: iconst_0
19: getstatic #9 // Field X:LFoo;
22: aastore
23: putstatic #1 // Field $VALUES:[LFoo;
26: return
}
私の混乱は、各列挙定数をインスタンス化するために使用されるプライベートコンストラクタです。逆アセンブリは引数を取らないことを示しますが(private Foo();
)、引数を取ることは確かです。たとえば、load
命令は、渡された列挙定数名と序数、およびthis
ポインタを読み取って、それらを必要とするthe superclass constructorに渡すことができます。静的イニシャライザブロックのコードは、コンストラクタを呼び出す前に、それらの引数をスタックにプッシュすることも示しています。
は、今私は、これは単なるてjavapであいまいなバグだったと仮定しているだろうが、私は、Eclipseのコンパイラとまったく同じ列挙型をコンパイルしてjavap使用することを逆アセンブルするとき、コンストラクタはが示されているの引数を除いてまったく同じです。
final class Foo extends java.lang.Enum<Foo> {
public static final Foo X;
private static final Foo[] ENUM$VALUES;
static {};
Code:
0: new #1 // class Foo
3: dup
4: ldc #12 // String X
6: iconst_0
7: invokespecial #13 // Method "<init>":(Ljava/lang/String;I)V
10: putstatic #17 // Field X:LFoo;
13: iconst_1
14: anewarray #1 // class Foo
17: dup
18: iconst_0
19: getstatic #17 // Field X:LFoo;
22: aastore
23: putstatic #19 // Field ENUM$VALUES:[LFoo;
26: return
private Foo(java.lang.String, int); // <--- here
Code:
0: aload_0
1: aload_1
2: iload_2
3: invokespecial #23 // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V
6: return
public static Foo[] values();
Code:
0: getstatic #19 // Field ENUM$VALUES:[LFoo;
3: dup
4: astore_0
5: iconst_0
6: aload_0
7: arraylength
8: dup
9: istore_1
10: anewarray #1 // class Foo
13: dup
14: astore_2
15: iconst_0
16: iload_1
17: invokestatic #27 // Method java/lang/System.arraycopy:(Ljava/lang/Object;ILjava/lang/Object;II)V
20: aload_2
21: areturn
public static Foo valueOf(java.lang.String);
Code:
0: ldc #1 // class Foo
2: aload_0
3: invokestatic #35 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
6: checkcast #1 // class Foo
9: areturn
}
私の質問は:どのような物理的には、javacのコンパイル列挙型とてjavapはjavacのコンパイル列挙型のコンストラクタの引数を表示しないようになりEclipseのコンパイル列挙型の間で違うのですか?そして、この違いはバグです(javap、javac、またはEclipse)。
推測すると、 '-g'フラグの設定(デバッグ情報の生成を制御します)。 – CPerkins
@CPerkins良い仮説ですが、 '-g'(すべてのデバッグ情報を生成する)と' -g:none'(デバッグ情報を生成しません)を比較しました。 – Boann
'-v'(冗長)フラグを試しましたか?少なくとも、コンストラクタの記述子を表示する必要があります。私の推測では、 'javac'は最初のパラメータ' MANDATED'をマークしているので、 'javap'はそれらを省略することがあります。 – Clashsoft