5

Mam pewne problemy z uruchomieniem prostego programu głównego z bibliotekami Guava.Niezgodny argument do funkcji z instrumentacją kodu bajtowego ASM

mam oprzyrządowanie klas, aby uzyskać parametry metody używając mojego kod tutaj: Java method parameters values in ASM

Kwestia jest taka, że ​​podczas gdy kod działa dla małych projektów (aka Wieża Hanoi), z Guava mam błędy i wyjątki.

W szczególności podczas testowania metody Joiner.join, mam ten błąd:

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) 

A kiedy uruchomiony przykład stosując -noverify mam wyjątek:

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) 

kodu bajtowego Metoda jest spójna:

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 

Rozumiem, że błąd może być związany z biblioteką ego, ale główny program java został skompilowany z oprzyrządowaną biblioteką i uruchomiony przy użyciu tego samego słoika biblioteki.

Jakieś pomysły na to, dlaczego tak się dzieje? I jak można to rozwiązać?

Dzięki :)

EDIT

Oto kod bajtowy o metodzie withKeyValueSeparator przed i po instrumentacji

Original kodu bajtowego:

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 

instrumentalnej kodu bajtowego:

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 

Oto pełny kod bajtowy klasy stolarskich:

oryginalny: http://pastebin.com/VsccVX18

Instrumented: http://pastebin.com/xtke1a8y

+0

Czy możesz dodać flagę '-v' do swojego polecenia' javap'? Ta pierwsza drukuje inne użyteczne informacje, które mogą pomóc. – Xyene

Odpowiedz

0

Po pierwsze, nie widzę dlaczego ta powinna być związana z wersjami bibliotek. Wygląda na to, że kod bajtowy nie jest poprawnie sparametryzowany, co powoduje niepowodzenie weryfikacji i wyjątek, jeśli użyjesz -noverify.

Jeśli chodzi o błąd weryfikacji, oznacza to, że wystąpił błąd w Joiner.withKeyValueSeparator(). Kod tej metody próbuje wywołać inną metodę z niekompatybilnymi argumentami metody. Czy możesz podać instrumentowany kod bajtowy metody withKeyValueSeparator()? (i oczywiście także nie-przyrządowe)

Błąd, który widzisz z -noverify występuje w konstruktorze stolarskie, wydaje się, że nie ma nic złego w metodzie Joiner.on(). Ponownie, możesz opublikować kod bajtowy łącznika. metoda? (oprzyrządowany i nieobrobiony)

+0

Cześć, dziękuję za wasze spostrzeżenia :). Dodałem kod bajtowy metody zKeyValueSeparator, zarówno oryginalny, jak i oprzyrządowany. Dodałem również pastebin tej klasy (również w wersji 2). – Adel

1

Oryginalny kod withKeyValueSeparator przekazuje wiązkę swoich argumentów do konstruktora MapJoiner.Dodajesz kod oprzyrządowania, który przechowuje tablicę w drugim gnieździe tabeli zmiennych lokalnych (używając astore_1). To nadpisze pierwszy argument do withKeyValueSeparator, który jest String. (Pierwsze miejsce w lokalnej tablicy zmiennych to sama instancja MapJoiner, czyli this.) Zatem, gdy kod oryginalnej funkcji próbuje przekazać obiekt do drugiego slotu lokalnej tabeli var do konstruktora, pojawia się "Niekompatybilny argument" błąd.

Aby to naprawić, należy przydzielić nową szczelinę w lokalnej tabeli zmiennych dla tablicy; this answer określa, w jaki sposób.

Powiązane problemy