5

Tôi đang gặp một số sự cố khi chạy chương trình chính đơn giản với thư viện Guava.Đối số không tương thích để hoạt động với thiết bị bytecode ASM

Tôi đã instrumented các lớp để có được các thông số phương pháp sử dụng mã của tôi từ đây: Java method parameters values in ASM

Vấn đề là, rằng trong khi các mã làm việc cho các dự án nhỏ (hay còn gọi là Tháp của Hà Nội), với Ổi Tôi có lỗi và ngoại lệ.

Đặc biệt, khi kiểm tra các phương pháp Joiner.join, tôi có lỗi này:

Exception in thread "Jalen Agent" java.lang.VerifyError: (class: com/google/common/base/Joiner, method: withKeyValueSeparator signature: (Ljava/lang/String;)Lcom/google/common/base/Joiner$MapJoiner;) Incompatible argument to function 
at Main.joinBench(Main.java:42) 
at Main.main(Main.java:20) 

Và khi chạy ví dụ sử dụng -noverify, tôi có một ngoại lệ:

Exception in thread "Jalen Agent" java.lang.ArrayIndexOutOfBoundsException: 1 
at com.google.common.base.Joiner.<init>(Joiner.java) 
at com.google.common.base.Joiner.on(Joiner.java:71) 
at Main.joinBench(Main.java:42) 
at Main.main(Main.java:20) 

Bytecode của phương pháp là nhất quán:

public static com.google.common.base.Joiner on(java.lang.String); 
     Code: 
     0: bipush  1 
     2: anewarray  #4     // class java/lang/Object 
     5: astore_1  
     6: aload_1  
     7: bipush  0 
     9: aload_0  
     10: aastore  
     11: ldc   #20     // int 369 
     13: ldc   #21     // String com/google/common/base/Joiner 
     15: ldc   #22     // String on 
     17: aload_1  
     18: invokestatic #28     // Method jalen/MethodStats.onMethodEntry:(ILjava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V 
     21: new   #2     // class com/google/common/base/Joiner 
     24: dup   
     25: aload_0  
     26: invokespecial #32     // Method "<init>":(Ljava/lang/String;)V 
     29: ldc   #20     // int 369 
     31: invokestatic #36     // Method jalen/MethodStats.onMethodExit:(I)V 
     34: areturn 

Tôi hiểu rằng lỗi có thể liên quan đến librar Phiên bản ies, nhưng chương trình java chính đã được biên dịch dựa vào thư viện có nhạc cụ và chạy bằng cách sử dụng cùng một lọ của thư viện.

Bất kỳ ý tưởng nào về lý do điều này xảy ra? Và làm thế nào nó có thể được giải quyết?

Cảm ơn :)

EDIT

Sau đây là các bytecode của phương pháp withKeyValueSeparator trước và sau khi thiết bị đo đạc

gốc bytecode:

public com.google.common.base.Joiner$MapJoiner withKeyValueSeparator(java.lang.String); 
Code: 
    0: new   #33     // class com/google/common/base/Joiner$MapJoiner 
    3: dup   
    4: aload_0  
    5: aload_1  
    6: aconst_null 
    7: invokespecial #34     // Method com/google/common/base/Joiner$MapJoiner."<init>":(Lcom/google/common/base/Joiner;Ljava/lang/String;Lcom/google/common/base/Joiner$1;)V 
    10: areturn 

instrumented bytecode:

public com.google.common.base.Joiner$MapJoiner withKeyValueSeparator(java.lang.String); 
Code: 
    0: bipush  1 
    2: anewarray  #4     // class java/lang/Object 
    5: astore_1  
    6: aload_1  
    7: bipush  1 
    9: aload_1  
    10: aastore  
    11: ldc   #199    // int 390 
    13: ldc   #21     // String com/google/common/base/Joiner 
    15: ldc   #200    // String withKeyValueSeparator 
    17: aload_1  
    18: invokestatic #28     // Method jalen/MethodStats.onMethodEntry:(ILjava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V 
    21: new   #8     // class com/google/common/base/Joiner$MapJoiner 
    24: dup   
    25: aload_0  
    26: aload_1  
    27: aconst_null 
    28: invokespecial #203    // Method com/google/common/base/Joiner$MapJoiner."<init>":(Lcom/google/common/base/Joiner;Ljava/lang/String;Lcom/google/common/base/Joiner$1;)V 
    31: ldc   #199    // int 390 
    33: invokestatic #36     // Method jalen/MethodStats.onMethodExit:(I)V 
    36: areturn 

Sau đây là các bytecode đầy đủ của lớp joiner:

gốc: http://pastebin.com/VsccVX18

instrumented: http://pastebin.com/xtke1a8y

+0

Bạn có thể thêm cờ '-v' vào lệnh' javap' của mình không? Trước đây in một số thông tin hữu ích khác có thể hữu ích. – Xyene

Trả lời

0

Trước tiên, tôi không hiểu tại sao điều này nên được liên quan đến phiên bản thư viện. Có vẻ như bytecode không được thiết kế chính xác, điều này làm cho việc xác minh thất bại và ngoại lệ nếu bạn sử dụng -noverify.

Về lỗi xác minh, nó cho biết có lỗi trong Joiner.withKeyValueSeparator(). Mã của phương thức này cố gắng gọi một phương thức khác với các đối số phương thức không tương thích. Bạn có thể cung cấp cho bytecode nhạc cụ của phương thức withKeyValueSeparator() không? (và perferrably non-instrumented là tốt)

Lỗi bạn nhìn thấy với -noverify xảy ra trong hàm tạo của Joiner, dường như không có gì sai với phương thức Joiner.on(). Một lần nữa, bạn có thể đăng bytecode của Joiner. phương pháp? (có dụng cụ và không được trang bị)

+0

Xin chào, cảm ơn vì thông tin chi tiết của bạn :). Tôi đã thêm bytecode của phương thức withKeyValueSeparator, cả bản gốc và nhạc cụ. Tôi cũng thêm một pastebin của lớp (cũng trong 2 phiên bản). – Adel

1

Mã gốc của withKeyValueSeparator chuyển một loạt các đối số của nó tới hàm tạo MapJoiner.Bạn đang thêm mã thiết bị đo lưu trữ một mảng trong khe thứ hai của bảng biến cục bộ (sử dụng astore_1). Điều này sẽ ghi đè đối số đầu tiên thành withKeyValueSeparator, là String. (Vị trí đầu tiên của bảng biến cục bộ là một ví dụ MapJoiner, hay còn gọi là this.) Vì vậy, khi mã của hàm ban đầu cố truyền đối tượng trong khe thứ hai của bảng var cục bộ tới hàm khởi tạo, có "Đối số không tương thích" lỗi.

Để khắc phục điều này, bạn nên phân bổ một vị trí mới trong bảng biến cục bộ cho mảng của bạn; this answer vạch ra cách thức.

Các vấn đề liên quan