Wpis z mikrobloga

#java #programowanie
A więc bawię się asm, a dokładniej asm-tree bo mam całkiem sporo do przemielenia, i mam pewien problem, mam listę instrukcji (InsnList) które chce dodać na początek konstruktora, no i teraz jak to zrobić? Muszę jakoś znaleźć wywołanie do super(...) i wtedy wsadzić za tym elementem, ale nie mogę ogarnąć żadnego sensownego kodu na znalezienie wywołania do super(...) które się nie będzie gubiło przy bardziej zaawansowanych wywołaniach, jakieś rady? Lub może w asm coś takiego już jest?
  • 5
Nie wiem, jak to dokładnie wygląda w asm (sam bawiłem się jedynie BCEL), ale ze specyfikacji Javy wynika, że wywołanie konstruktora to powinna być pierwsza instrukcja INVOKESPECIAL w metodzie o sygnaturze :()V (przed nią pewnie będzie odkładanie parametrów konstruktora na stos) - można szukać w ten sposób. A może wygodniej byłoby napisać te Twoje instrukcje w metodzie innej klasy w zwykłej Javie, skompilować, dołączyć w runtime, a w konstruktorze dodać tylko wywołanie
@nachteil: ale ja właśnie chce dodać tylko 1 wywołanie metody do konstruktora, ale z powodu tego że java weryfikuje bytecode nie możesz tego zrobić przed super(), a edytuje wiele klas, każda z innymi konstruktorami.

Problem jest taki że jak np w super() uznasz że chcesz stworzyć nową instance super klasy to bytecode wygląda tak:
// klasa: http://pastebin.com/28rA7PvK
ALOAD 0 // this, od super.
NEW org/test/TestByte
DUP
ACONSTNULL
INVOKESPECIAL org/test/TestByte. (Ljava/lang/Object;)V
Ja to widzę tak - skoro jesteś w konstruktorze, to znaczy, że wcześniej coś zawołało najpierw NEW, a potem INVOKESPECIAL Testowa.. Pierwsza instrukcja konstruktora (na poziomie kodu wysokiego poziomu) to musi być zawołanie super(), czyli dążysz do tego, żeby zawołać INVOKESPECIAL org/diorite/TestByte..... W tym celu możesz chcieć przygotować jakieś parametry, potencjalnie tej samej klasy, ale jest ograniczenie - one też muszą zostać zainicjalizowane, zanim zostaną przekazane do super()