2013-05-22 35 views
7

Tôi đã dịch ngược một lớp học với javap và tôi nhìn thấy một số bản sao trong phần Hồ bơi cố định, như thế này:Sao chép nhóm liên tục của lớp Java?

#19 = Class    #350   // java/lang/StringBuilder 
... Some other class constants here 
#318 = Class    #350   // java/lang/StringBuilder 

Methodrefs tham khảo chỉ có một trong số họ:

#20 = Methodref   #19.#351  // java/lang/StringBuilder."<init>":()V 
#22 = Methodref   #19.#353  // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
#24 = Methodref   #19.#355  // java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; 
#25 = Methodref   #19.#356  // java/lang/StringBuilder.toString:()Ljava/lang/String; 
#110 = Methodref   #19.#445  // java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 

là lớp này đúng theo The class File Format? Tôi nghĩ rằng mỗi lớp được đề cập chỉ một lần và được giới thiệu sau đó bởi chỉ mục của nó trong phần bytecode.

$ javac -version 
javac 1.7.0_15 

Một điều kỳ lạ khác là nguồn gốc của lớp đại diện cho hồ bơi không đổi trong javac Pool.java. Điều này nói rằng nó sẽ không đặt một đối tượng vào hồ bơi nếu nó đã có (với sự giúp đỡ của một HashMap). Tôi tự hỏi, nếu các phương thức equals()/hashCode() của các lớp này được lồng ghép đúng cách.

Trả lời

1

Bạn nói đúng. Constant pool không yêu cầu mục trùng lặp. Một lớp chỉ nên có 1 mục nhập trong nhóm không đổi.

Điều này chắc chắn có vẻ là một lỗi. Kiểm tra này ra. Ai đó đã đăng nhập này như lỗi và nó đã được thừa nhận >>http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6746955

trả lời Cập nhật:

Một điều nữa tôi muốn chỉ ra ở đây là thêm các mục trùng lặp không thực hiện bất kỳ ý nghĩa bởi vì nó làm tăng kích thước byte của tệp lớp và phá hủy mục đích chính của tính nhỏ gọn của tệp lớp java, tính di động và tính di động mạng nhanh hơn. Tệp lớp nên càng nhỏ gọn càng tốt.

Bằng cách này, tệp lớp là hợp lệ vì nó tuân thủ định dạng tệp lớp được xác định. Nhưng nó không phải là một lý tưởng.

Như tôi đã quên, trả lời Câu hỏi thứ hai của bạn:

JVM gán tương tự tìm đối tượng hashcode cùng nhưng vẫn họ sẽ khác nhau. JVM sẽ không bao giờ tạo 2 đối tượng giống hệt nhau trừ khi cả hai đều đề cập đến cùng một đối tượng. Hashcode không là gì ngoài hệ thống phân vùng. Các đối tượng tìm kiếm tương tự được đặt vào cùng một phân vùng để thời gian di chuyển trở nên ít hơn trong khi tìm kiếm một đối tượng cụ thể. Hashcode không là gì ngoài một con trỏ tới phân vùng nhỏ đó.

Chỉ vì không thể gán mã băm riêng biệt cho từng đối tượng mới (vì số lượng đối tượng có thể lớn hơn số lượng mã băm duy nhất có thể tạo ra. . Nhưng đây là điều, 2 đối tượng trỏ đến cùng một tham chiếu trong bộ nhớ phải có cùng một hashcode.

Vì vậy,, đạo đức của câu chuyện, JVM đảm bảo rằng hai đối tượng riêng biệt không bao giờ có thể giống hệt ngay cả khi mã băm của chúng.

+0

Bạn có nhìn vào đó lỗi bạn đã liên kết? Nó đã được báo cáo trong năm 2008, và hoạt động cuối cùng trên nó là 2 năm trước đây. Đã thực sự bị hỏng, nó đã được cố định từ lâu rồi. – cHao

+0

Tôi đã không đề cập đến nó bao nhiêu tuổi. Tôi đã đề cập đến lỗi đó và sự thừa nhận của nó. Ý tôi là, đây thực sự là một lỗi. –

+0

Đó là một sự thiếu hiệu quả .... nhưng nó không chính xác. – cHao

3

Như tôi đã hiểu từ thông số JVM, không có giới hạn nào ngăn cản các mục trùng lặp trong nhóm không đổi. Nói chung các trình biên dịch tạo tệp lớp không có bản sao. Nhưng ngay cả khi tệp lớp có bản sao, nó cũng không ảnh hưởng đến hành vi mong đợi của nó.

Tệp lớp học mà bạn đã dịch ngược được tạo ra như thế nào?

0

Một lưu ý: theo JENKINS-22525 có vẻ như rằng trong khi các tập tin lớp với bản sao như vậy là hợp pháp về mặt kỹ thuật, J9 VM của IBM sẽ trong một số trường hợp từ chối để tải các lớp bên trong của họ, quan sát với

java.lang.IncompatibleClassChangeError: incompatible InnerClasses attribute between … 
Các vấn đề liên quan