2013-02-28 12 views
8

Sto cercando di capire se c'è un motivo nelle specifiche per la discrepanza tra i descrittori java e le firme per le classi interne. (Sto guardando direttamente il contenuto dei file di classe qui, ma io uso javap per illustrare).Incoerenza della classe interna Java tra descrittore e attributo della firma? (file di classe)

(nb ho provato questo su JDK 1.6.0_33 e 1.7.0_05, entrambi hanno lo stesso problema se visti con javap da Java 7 - Java 6 di javap non sembra mostrare alcun informazioni firma generica, come per ogni risposta di Sean sotto)

Update:. Grazie a chi discutere - il mio prendere è

  • Il descrittore (che non contiene informazioni generiche) è corretta.
  • La firma (che è un attributo del metodo e contiene informazioni generiche) non è corretta. La voce ConstPool rilevanti per la firma del init > metodo di < è "ConstantUTF8 [(Ljava/util/lista <TE;>) V]"
  • javap in Java 6 non sembra al momento della firma, solo il descrittore. (La mia ipotesi!)

Nel caso in cui qualcuno si chieda, lo prendo senza usare JAVAP, guardando solo i file di classe, sto usando solo javap per mostrarlo. (quindi è improbabile che sia un javap bug).

considerare:

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

Se si guarda l'output di -cs javap sulle classi interne, sono sorprendentemente diverso!

pubblico org.benf.cfr.tests.InnerClassTest1 $ INNER1 (org.benf.cfr.tests.InnerClassTest1, java.util.List); Firma: (Lorg/benf/CFR/test/InnerClassTest1; Ljava/util/Lista;) V

vs

pubblico org.benf.cfr.tests.InnerClassTest2 $ INNER1 (java.util.List <E>); Firma: (Lorg/benf/CFR/test/InnerClassTest2; Ljava/util/Elenco;) V

... quello che utilizza generici manca il parametro implicito per classe esterna! (è presente correttamente in InnerClassTest1).

Non riesco a trovare nulla nella documentazione del file di classe per spiegare questo - qualcuno sa perché questo potrebbe essere?

Grazie!

Lee.


Aggiornamento -

Ho messo file di esempio a http://www.benf.org/files/innerClassTest.tgz

Dato risposta di Sean sotto, ho provato ad utilizzare javap su Java 6, e ho visto di uscita identica per entrambi, senza informazioni generiche - questo mi porta a credere che javap di java 6 non mostri informazioni complete sulla firma?

L'uscita esatta ottengo utilizzando javap su 1.7.0_05-b06 è

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  
} 
+0

Per favore, specificare i dettagli JDK –

+0

Aggiornato, grazie. – lab27

+0

Potresti pubblicare i file di classe attuali? Ciò potrebbe almeno ridurlo a un problema del compilatore rispetto a un problema del disassemblatore. – Antimony

risposta

1

Utilizzando il codice di cui sopra e l'utilizzo di JDK 1.6.0_33 ottengo il seguente 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 

} 

e la le uniche differenze sono che la mia implementazione ha (per compilare il codice):

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

e il fatto che il tuo pacchetto Il nome è probabilmente diverso (org.benf.cfr.tests?).

A parte questo, la mia uscita è praticamente la stessa. Ci sono altre differenze nel codice che potrebbero spiegare ciò che stai vedendo? Da quello che so sul processo di compilazione e sui file di classe non mi aspetto di vedere una differenza nell'output.

Buona domanda - essere interessante per scoprire il motivo per cui si sta vedendo questo

+0

Questo è molto interessante - Forse è qualcosa di peculiare del mio ambiente, anche se non ho idea di cosa possa essere! Ho inserito il mio/esatto/output, così come i file di classe [link] (http://www.benf.org/files/innerClassTest.tgz) qui, se vuoi dare un'occhiata. – lab27

+0

Mi chiedo se java 6 (stai usando quello?) Javap sta facendo qualcosa di diverso qui, perché non vedo alcuna informazione generica nell'output che hai per InnerClassTest2. – lab27

+0

Ho scaricato i file e ho fatto javap -c -p su di essi e l'output è identico al precedente (con l'eccezione del pacchetto diverso) - quindi sembra che javap sia il colpevole –

1

Utilizzando javap su InnerClassTest2$Inner1

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

Smontaggio con Krakatau dà

.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 

Come si può vedere, l'output di Krakatau mostra che il descrittore è effettivamente corretto, ma per qualche motivo Javap non lo sta visualizzando. Una cosa su Javap è che cerca di organizzare l'output in modo che assomigli più a Java. Forse questa è una nuova funzionalità introdotta in JDK7 che cerca di rendere i generici disassemblati più simili a Java nascondendo i parametri aggiunti dal compilatore. Sfortunatamente questo rende Javap (ancora più) inutile per vedere cosa c'è davvero.

Interessante cattura!