Java内部类描述符和签名属性之间不一致? (类文件) [英] Java inner class inconsistency between descriptor and signature attribute? (class file)

查看:204
本文介绍了Java内部类描述符和签名属性之间不一致? (类文件)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图了解规范中是否有理由说明内部类的Java描述符和签名之间的差异. (我在这里直接查看类文件的内容,但是我使用javap进行说明).

I'm trying to understand if there's a reason in the spec for the discrepany between java descriptors and signatures for inner classes. (I'm looking directly at the content of the class files here, but I use javap to illustrate).

(nb我已经在JDK 1.6.0_33和1.7.0_05上尝试过,当使用来自Java 7的javap进行查看时,它们都有相同的问题-Java 6的javap似乎没有显示任何泛型签名信息,请按照以下Sean的回答.)

( n.b. I have tried this on JDK 1.6.0_33 and 1.7.0_05, both have the same issue when viewed with javap from Java 7 - java 6's javap doesn't seem to show any generic signature info, as per Sean's answer below. )

更新:多亏了那些人的讨论-我的观点是

Update : Thanks to those discussing - my take is

  • 描述符(不包含通用信息)是正确的.
  • 签名(该方法的属性,并且确实包含通用信息)不正确. < init>的签名的相关ConstPool条目.方法是"ConstantUTF8 [(Ljava/util/list< TE;>)V]"
  • Java 6中的Javap不会查看签名,而只能查看描述符. (我的猜测!)

万一有人想知道,我没有使用JAVAP就打了这个,只是自己看了类文件,我只是用javap来显示它. (因此不太可能是javap错误).

In case anyone wonders, I hit this without using JAVAP, just looking at the class files myself, I am only using javap to show it. (so it's unlikely to be a javap bug).

考虑:

public class InnerClassTest1 {

  public int getX() {
    return new Inner1(new ArrayList<String>()).getX(4);
  }

  public class Inner1 {
    private final List arg;

    public Inner1(List arg) {
        this.arg = arg;
    }....

vs

public class InnerClassTest2 {

   public int getX() {
      return new Inner1(new ArrayList<String>()).getX(4);
   }

   public class Inner1<E> {
    private final List<E> arg;

    public Inner1(List<E> arg) {
        this.arg = arg;
    }.....

如果您在内部类上查看javap -cs的输出,它们的区别令人惊讶!

If you look at the output of javap -cs on the inner classes, they're surprisingly different!

public org.benf.cfr.tests.InnerClassTest1 $ Inner1( org.benf.cfr.tests.InnerClassTest1, java.util.List); 签名:(Lorg/benf/cfr/tests/InnerClassTest1; Ljava/util/List;)V

public org.benf.cfr.tests.InnerClassTest1$Inner1(org.benf.cfr.tests.InnerClassTest1, java.util.List); Signature: (Lorg/benf/cfr/tests/InnerClassTest1;Ljava/util/List;)V

vs

public org.benf.cfr.tests.InnerClassTest2 $ Inner1(java.util.List< E>)); 签名:(Lorg/benf/cfr/tests/InnerClassTest2; Ljava/util/List;)V

public org.benf.cfr.tests.InnerClassTest2$Inner1(java.util.List<E>); Signature: (Lorg/benf/cfr/tests/InnerClassTest2;Ljava/util/List;)V

... 使用泛型的那个缺少外部类的隐式参数!(在InnerClassTest1中正确存在).

... the one which uses generics is missing the implicit parameter for the outer class! (it's correctly present in InnerClassTest1).

我在类文件文档中找不到任何东西可以解释这一点-有人知道为什么会这样吗?

I can't find anything in the class file documentation to explain this - does anyone know why this might be?

谢谢!

李.

更新-

我将示例文件放置在http://www.benf.org/files/innerClassTest.tgz

在下面给出Sean的答案,我尝试在java 6上使用javap,并且看到了两者的相同输出,没有通用信息-这使我相信Java 6的javap不会显示完整的签名信息?

Given Sean's answer below, I tried using javap on java 6, and I saw identical output for both, with no generic information - this leads me to believe that java 6's javap is not displaying full signature information?

我在1.7.0_05-b06上使用javap得到的确切输出是

The exact output I get using javap on 1.7.0_05-b06 is

public class org.benf.cfr.tests.InnerClassTest2$Inner1<E> {
 final org.benf.cfr.tests.InnerClassTest2 this$0;
 Signature: Lorg/benf/cfr/tests/InnerClassTest2;

public org.benf.cfr.tests.InnerClassTest2$Inner1(java.util.List<E>);
 Signature: (Lorg/benf/cfr/tests/InnerClassTest2;Ljava/util/List;)V
 Code:
   0: aload_0       
   1: aload_1       
   2: putfield      #1                  // Field this$0:Lorg/benf/cfr/tests/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: iconst_2      
   1: ireturn       
}

推荐答案

InnerClassTest2$Inner1上使用Javap会提供

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);
}

与Krakatau一起拆解会提供

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

如您所见,Krakatau输出显示描述符实际上是正确的,但是由于某些原因Javap没有显示它.关于Javap的一件事是,它试图安排输出,使其看起来更像Java.也许这是JDK7中引入的一项新功能,它通过隐藏编译器添加的参数,试图使反汇编的泛型看起来更像Java.不幸的是,这使Javap(甚至更多)无助于查看实际内容.

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.

有趣的收获!

这篇关于Java内部类描述符和签名属性之间不一致? (类文件)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆