Я использую ASM и хочу переписать что-то вроде:
someMethod().targetMethod(args...)
to:
someMethod().injectedMethod(arg).targetMethod(args...)
Проблема в том, что я не знаю, какой метод был раньше, я знаю только целевой метод (поэтому найти someMethod()
и внедрить после этого не вариант).
У меня также есть много версий целевого метода с разными наборами параметров, с которыми я хочу, чтобы он работал.
Используя ASM, я могу легко найти вызов целевого метода, но, к сожалению, стек операндов в этот момент таков:
[ argN, ..., arg1, instance, ... ]
И хотя я могу вычислить, как далеко будет находиться экземпляр, я не могу внедрить байт-код, который будет его читать. Я знаю, что вы можете сделать это для 4 параметров, используя трюки с командами дублирования, но мне нужно общее решение.
Я мог бы добавить кучу локальных переменных и скопировать все из стека, дублировать указанный экземпляр и вернуть все обратно, но это неэффективность во время выполнения, которую я действительно не хочу.
Я думаю, что сработало бы, если бы я мог отслеживать, какие инструкции отвечают за размещение указателя экземпляра в стеке, а затем я мог бы внедрить вызов своего метода туда, а не при вызове целевого метода. Однако мне не повезло найти что-нибудь, чтобы помочь мне сделать это.
Я знаю, что такие вещи, как AspectJ, допускают это, но должны делать это для многих классов, поскольку они загружаются, а AspectJ слишком медленный.
Может ли кто-нибудь указать мне на инструменты анализа, построенные поверх ASM, которые могли бы позволить мне сделать это, или кто-нибудь может придумать лучший подход для внедрения одного вызова метода перед другим?