Java inner class inconsistency between descriptor and signature attribute? (class file)

瘦欲@ 提交于 2019-12-04 04:09:18

Using the code above and using JDK 1.6.0_33 I get the following output:

src\test>javap -c -s InnerClassTest1$Inner1
Compiled from "InnerClassTest1.java"
public class test.InnerClassTest1$Inner1 extends java.lang.Object{
final test.InnerClassTest1 this$0;
  Signature: Ltest/InnerClassTest1;

public test.InnerClassTest1$Inner1(test.InnerClassTest1, java.util.List);
  Signature: (Ltest/InnerClassTest1;Ljava/util/List;)V
  Code:
   0:   aload_0
   1:   aload_1
   2:   putfield        #1; //Field this$0:Ltest/InnerClassTest1;
   5:   aload_0
   6:   invokespecial   #2; //Method java/lang/Object."<init>":()V
   9:   aload_0
   10:  aload_2
   11:  putfield        #3; //Field arg:Ljava/util/List;
   14:  return

public int getX(int);
  Signature: (I)I
  Code:
   0:   iload_1
   1:   ireturn
}

src\test>javap -c -s InnerClassTest2$Inner1
Compiled from "InnerClassTest2.java"
public class test.InnerClassTest2$Inner1 extends java.lang.Object{
final test.InnerClassTest2 this$0;
  Signature: Ltest/InnerClassTest2;

public test.InnerClassTest2$Inner1(test.InnerClassTest2, java.util.List);
  Signature: (Ltest/InnerClassTest2;Ljava/util/List;)V
  Code:
   0:   aload_0
   1:   aload_1
   2:   putfield        #1; //Field this$0:Ltest/InnerClassTest2;
   5:   aload_0
   6:   invokespecial   #2; //Method java/lang/Object."<init>":()V
   9:   aload_0
   10:  aload_2
   11:  putfield        #3; //Field arg:Ljava/util/List;
   14:  return

public int getX(int);
  Signature: (I)I
  Code:
   0:   iload_1
   1:   ireturn

}

and the only differences are that my implementation has (to make the code compile):

    public int getX(int i) {
        return i;
    }

and the fact that your package name is probably different (org.benf.cfr.tests ?).

Other than that though, my output is pretty much the same. Are there any other differences in the code that might explain what you're seeing? From what I know about the compilation process and class files I wouldn't expect to see a difference in the output.

Good question - be interesting to find out why you're seeing this

Using Javap on InnerClassTest2$Inner1 gives

Compiled from "InnerClassTest2.java"
public class org.benf.cfr.tests.InnerClassTest2$Inner1<E> {
  final org.benf.cfr.tests.InnerClassTest2 this$0;
  public org.benf.cfr.tests.InnerClassTest2$Inner1(java.util.List<E>);
  public int getX(int);
}

Disassembling with Krakatau gives

.version 51 0
.source InnerClassTest2.java
.class super public org/benf/cfr/tests/InnerClassTest2$Inner1
.super java/lang/Object

.field final private arg Ljava/util/List;
.field synthetic final this$0 Lorg/benf/cfr/tests/InnerClassTest2;

.method public <init> : [_13]
    .limit stack 2
    .limit locals 3
    aload_0
    aload_1
    putfield org/benf/cfr/tests/InnerClassTest2$Inner1 this$0 Lorg/benf/cfr/tests/InnerClassTest2;
    aload_0
    invokespecial java/lang/Object <init> ()V
    aload_0
    aload_2
    putfield org/benf/cfr/tests/InnerClassTest2$Inner1 arg Ljava/util/List;
    return
.end method

.method public getX : (I)I
    .limit stack 1
    .limit locals 2
    iconst_2
    ireturn
.end method

.const [_13] = Utf8 (Lorg/benf/cfr/tests/InnerClassTest2;Ljava/util/List;)V

As you can see, the Krakatau output shows that the descriptor is actually correct, but for some reason Javap isn't displaying it. One thing about Javap is that it tries to arrange the output so it looks more like Java. Perhaps this is a new feature introduced in JDK7 that tries to make disassembled generics look more like Java by hiding the compiler added parameters. Unfortunately this makes Javap (even more) useless for seeing what's really there.

Interesting catch!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!