2013-02-28 20 views
8

Tôi đang cố gắng để hiểu nếu có một lý do trong spec cho sự khác biệt giữa các mô tả java và chữ ký cho các lớp bên trong. (Tôi đang xem trực tiếp nội dung của các tệp lớp ở đây, nhưng tôi sử dụng javap để minh họa).Java không thống nhất lớp bên trong giữa mô tả và thuộc tính chữ ký? (lớp tập tin)

(nb Tôi đã thử này trên JDK 1.6.0_33 và 1.7.0_05, cả hai đều có cùng một vấn đề khi xem với javap từ Java 7 - java 6 của javap dường như không hiển thị bất kỳ thông tin chữ ký chung chung, như mỗi câu trả lời của Sean dưới đây)

cập nhật:. Nhờ có những thảo luận - mất của tôi là

  • Bộ mô tả (mà không chứa thông tin chung chung) là đúng.
  • Chữ ký (là thuộc tính của phương thức và chứa thông tin chung) không chính xác. Mục ConstPool liên quan cho SIGNATURE của <init> phương pháp là "ConstantUTF8 [(Ljava/util/danh sách <TE;>) V]"
  • javap trong Java 6 không nhìn vào chữ ký, chỉ là mô tả. (Tôi đoán!)

Trong trường hợp bất kỳ ai thắc mắc, tôi nhấn vào đây mà không sử dụng JAVAP, chỉ cần tự xem các tệp lớp, tôi chỉ sử dụng javap để hiển thị nó. (vì vậy nó không phải là một lỗi javap).

xem xét:

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

Nếu bạn nhìn vào đầu ra của -cs javap trên các lớp bên trong, họ ngạc nhiên khác nhau!

org.benf.cfr.tests.InnerClassTest1 $ Inner1 (org.benf.cfr.tests.InnerClassTest1, java.util.List); Chữ ký: (Lorg/benf/cfr/kiểm tra/InnerClassTest1; Ljava/util/List;) V

vs

công org.benf.cfr.tests.InnerClassTest2 $ Inner1 (java.util.List <E>); Chữ ký: (Lorg/benf/cfr/tests/InnerClassTest2; Ljava/util/List;) V

... một trong số đó sử dụng Generics thiếu tham số ngầm cho lớp ngoài! (hiển thị chính xác trong InnerClassTest1).

Tôi không thể tìm thấy bất kỳ thứ gì trong tài liệu tệp lớp học để giải thích điều này - có ai biết tại sao điều này có thể là không?

Cảm ơn!

Lee.


Update -

tôi đã đặt file ví dụ tại http://www.benf.org/files/innerClassTest.tgz

Với Sean câu trả lời dưới đây, tôi cố gắng sử dụng javap trên java 6, và tôi thấy đầu ra giống hệt nhau cho cả hai, không có thông tin chung - điều này khiến tôi tin rằng javap java 6 không hiển thị thông tin chữ ký đầy đủ?

Kết quả chính xác tôi được sử dụng javap trên 1.7.0_05-b06 là

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

Vui lòng chỉ định chi tiết JDK –

+0

Đã cập nhật, cảm ơn. – lab27

+0

Bạn có thể đăng các tệp lớp thực tế không? Điều đó sẽ ít nhất thu hẹp nó xuống một vấn đề trình biên dịch vs một vấn đề disassembler. – Antimony

Trả lời

1

Dùng đoạn code trên và sử dụng JDK 1.6.0_33 tôi nhận được kết quả như sau:

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 

} 

và những khác biệt duy nhất là việc triển khai của tôi có (để thực hiện việc biên dịch mã):

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

và thực tế là gói của bạn tên e có thể khác (org.benf.cfr.tests?).

Ngoài ra, sản lượng của tôi cũng khá giống nhau. Có bất kỳ sự khác biệt nào khác trong mã có thể giải thích những gì bạn đang thấy không? Từ những gì tôi biết về quá trình biên soạn và các tập tin lớp tôi sẽ không mong đợi để thấy một sự khác biệt trong đầu ra.

Tốt câu hỏi - rất thú vị để tìm hiểu lý do tại sao bạn thấy thông báo này

+0

Điều đó rất thú vị - Có lẽ đó là điều gì đó đặc biệt với môi trường của tôi, mặc dù tôi không biết điều đó có thể là gì! Tôi đã đưa ra/chính xác/đầu ra của tôi, cũng như các tập tin lớp [link] (http://www.benf.org/files/innerClassTest.tgz) ở đây, nếu bạn muốn có một cái nhìn. – lab27

+0

Tôi tự hỏi nếu java 6 (bạn đang sử dụng nó?) Javap đang làm một cái gì đó khác nhau ở đây, như tôi không thấy bất kỳ thông tin chung trong đầu ra bạn có cho InnerClassTest2. – lab27

+0

Tôi đã tải xuống các tệp của bạn và đã thực hiện javap -c -p trên chúng và đầu ra giống với ở trên (ngoại trừ gói khác) - vì vậy có vẻ như javap là thủ phạm –

1

Sử dụng javap trên InnerClassTest2$Inner1 cho

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

Tháo với Krakatau cho

.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 

Như bạn có thể thấy, đầu ra Krakatau cho thấy rằng bộ mô tả thực sự đúng, nhưng vì một lý do nào đó Javap không hiển thị nó. Một điều về Javap là nó cố gắng sắp xếp đầu ra để nó trông giống Java hơn. Có lẽ đây là một tính năng mới được giới thiệu trong JDK7 mà cố gắng làm cho các generics bị tháo rời trông giống Java hơn bằng cách ẩn các tham số được thêm vào của trình biên dịch. Thật không may điều này làm cho Javap (thậm chí nhiều hơn) vô ích khi nhìn thấy những gì thực sự ở đó.

Thú vị bắt!