Ретрансформировать нативные методы в библиотеке Java Instrumentation Agent
Я пытаюсь написать библиотеку агента Java, которая загружается динамически через присоединение API, чтобы повторно преобразовать некоторые методы (те, которые появляются в следах стека определенных потоков) для записи метода входа / выхода. Информация о входе / выходе метода затем экспортируется через пользовательский MBean
,
Мой текущий "прототип" работает до сих пор, пока инструментальные методы не являются нативными.
В соответствии с документацией java.lang.instrument.Instrumentation # setNativeMethodPrefix (), агенты java должны иметь возможность заменить нативный метод на не родной метод-заглушку и добавить другой нативный метод с этим префиксом в своем имени, которое затем привязан к исходному коду исходного нативного метода.
Однако при реализации этого я получаю эту ошибку:
java.lang.UnsupportedOperationException: class redefinition failed: attempted to add a method
что верно, так как я добавил новый нативный метод.
Работает только замена нативного метода на неродной, но тогда я не могу делегировать обратный вызов исходному нативному методу. Определение нативного метода в другом классе не работает, так как нативные методы ищутся по имени класса и имени метода, и нет nativeMethodClassSuffix
или похожие. Определение другого класса с тем же именем в другом новом загрузчике классов будет работать, и я думаю, что было бы возможно с некоторыми косвенными указателями делегировать вызов новому классу, но одна нативная библиотека может быть связана только с нативными методами, загруженными классами только одного загрузчик классов, поэтому я не буду правильно связывать нативные методы.
Есть ли что-то очевидное, что я здесь скучаю? Мой код слишком длинный, чтобы публиковать здесь, если кто-то считает, что это помогает, я могу попытаться создать небольшой пример Java-агента, который показывает проблему и ссылается на нее здесь.
1 ответ
Есть ли что-то очевидное, что я здесь скучаю? Мой код слишком длинный, чтобы публиковать здесь, если кто-то считает, что это помогает, я могу попытаться создать небольшой пример Java-агента, который показывает проблему и ссылается на нее здесь.
Нет. Если вы замаскируете нативный метод, больше нет способа вызвать его из JNI. Вам нужно вызвать метод с использованием нативного кода. (Я понятия не имею, что это такое, но я был бы удивлен, если это невозможно)
Другой вариант - изменить все ссылки на собственный метод, а не маскировать его. Таким образом, вы все равно можете вызвать оригинальный метод, когда вы решите.