Я где-то читал, что когда когда-либо метод вызывается «invokevirtual», ссылка на объект извлекается из верхней части стек, за которым следуют аргументы. Мне нужно как-то распечатать ссылку на объект. Является ли это возможным?Есть ли способ распечатать объект ref, который вызвал метод instance/Static, используя инструментарий с байтовым кодом
ответ
Итак, я не собираюсь делать это за вас, потому что фактический код раздражает и утомителен, и если вы действительно искренне заинтересованы, вы должны научиться самому это делать. Но я постараюсь быть полезным и предоставить вам какое-то направление.
Во-первых, вы захотите прочитать ASM tutorials here.
Формат байтового кода, который я собираюсь написать ниже, поступает от ASMIfier, потому что это намного более ясно. Я собираюсь полностью игнорировать javap, потому что он еще более педантичен и детализирован, но если вы хотите знать, что он на самом деле показывает вам, тогда вы должны прочитать о Java ClassFile format.
На самом деле, вы должны сделать это в первую очередь, просто чтобы убедиться, что ваше фоновое знание несколько заполнено.
Итак, вкратце из того, что вы собираетесь делать. Вы захотите написать ClassWriter, который ищет экземпляры кода операции INVOKEVIRTUAL.
invokevirtual выводит значения из стека в обратном порядке, поэтому последний параметр сначала и объект, который вы вызываете против последнего. # 38, на который вы ссылаетесь, также не является объектом, его ссылкой на постоянный пул, который содержит имя метода и пару дескрипторов метода, которая используется как метаданные, поскольку JVM является типичным.
Давайте предположим, что у вас есть этот код:
пакет образца;
public class JavaSimpleHelloWorld {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
Если запустить ASMIFier против него, вы получите что-то вроде этого для всего основного метода (режущей контекст вниз для краткости)
public static main([Ljava/lang/String;)V
L0
LINENUMBER 6 L0
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "Hello World"
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
L1
LINENUMBER 7 L1
RETURN
L2
LOCALVARIABLE args [Ljava/lang/String; L0 L2 0
MAXSTACK = 2
MAXLOCALS = 1
так, вы реализуете какое-то статическая свалку метод (public static final dump (Object o)) и написать посетителя класса, который реорганизует ваш байт-код.
Вы можете использовать дескриптор метода, чтобы выяснить, насколько глубоко в инструкциях толкового стека (ALOAD, LDC) вам нужно вставить DUP/INVOKE для печати объекта объекта методов. Например, дескриптор метода для System.out.println является [Ljava/lang/String;] V. Это означает, что метод принимает массив строк и возвращает void. Поэтому вам нужно вернуться в стек, чтобы найти цель объекта. Ваш байт-код будет, в свою очередь, выглядеть так:
Счастливый байт код сплетения.
public static main([Ljava/lang/String;)V
L0
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
DUP
INVOKESTATIC my/staticutil/ClassThatDumps.dump (Ljava/lang/Object;)V
LDC "Hello World"
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
RETURN
L1
LOCALVARIABLE args [Ljava/lang/String; L0 L1 0
MAXSTACK = 2
MAXLOCALS = 1
- 1. Есть ли способ получить объект, который вызвал мой статический метод как метод экземпляра?
- 2. Получить ссылку на объект, который вызвал метод?
- 3. Добавить объект, который вызвал метод, в список
- 4. Есть ли способ распечатать PID процесса, который вызвал мой двоичный код C
- 5. Шаблоны управления байтовым кодом
- 6. Получение экземпляра, который вызвал метод в C#
- 7. Как «ссылаться» на объект, который вызвал итератор
- 8. Есть ли способ распечатать объект в виде ярлыка?
- 9. Проблема с байтовым кодом в MSVC++
- 10. Есть ли способ распечатать весь контекст скорости?
- 11. Есть ли способ распечатать все данные класса
- 12. Внутри метода узнать объект, который вызвал этот метод?
- 13. Как метод Objective-C ссылается на объект, который его вызвал?
- 14. Как получить объект, который вызвал метод из метода
- 15. Сериализация по сравнению с байтовым кодом
- 16. Есть ли способ распечатать сертификат X509?
- 17. Есть ли способ получить экземпляр объекта, который создал другой объект?
- 18. Ошибка управления байтовым кодом, создающая ошибку Java verifier
- 19. Есть ли способ распечатать содержимое конкретного DIV
- 20. Python: Есть ли способ распечатать список?
- 21. Есть ли способ распечатать ссылку на консоль?
- 22. SBT: есть ли способ распечатать список разрешителей?
- 23. Есть ли способ распечатать бит-представление объекта?
- 24. Есть ли способ распечатать arraylist в группах?
- 25. Есть ли способ распечатать DateTime в миллисекундах?
- 26. Как получить объект, который вызвал DocumentFilter
- 27. Есть ли способ распечатать консольный журнал с JavaScript, в HTML?
- 28. Есть ли способ создать метод экземпляра, который (де) сериализует объект с маршалом?
- 29. Есть ли способ получить конкретный оператор, который вызвал сбой при использовании предложения «с» в Spock
- 30. Есть ли способ идентифицировать объект, вызывающий конкретный метод в java?
Что это за «объект ref, который называется ...» вашего названия должен быть? Почему вы упоминаете 'static' методы в своем названии, когда вы ссылаетесь на' invokevirtual' только в вопросе? – Holger
Я действительно изучал динамическое поведение класса. и предполагая, что каждый вызов метода в программе java преобразуется в invokevirtual/invokestatic в байт-код. например invokevirtual # 38, где # 38 ссылается на некоторый идентификатор в постоянном пуле. Поэтому просто хотелось узнать, как можно получить информацию о # 38 во время выполнения. –
Ваш комментарий описывает совсем другую вещь, чем ваш вопрос. Ваш вопрос касается ссылки на объект в стеке операндов, тогда как ваш комментарий относится к индексу в пул констант, встроенный в инструкцию. Итак, теперь у нас есть три несовместимые вещи, ваше название, ваш вопрос и ваш комментарий. Ответ на последний: вы можете найти эту информацию в том же месте, где вы получили «# 38». – Holger