Аннотация
Я читаю файлы классов, используя ASM, и мой MethodVisitor
получает странный аргумент при посещении перечисления: аргумент owner
для visitMethodInsn
должен быть внутренним name (например, mre/DoStuff
), но для перечисления я получаю owner
в форме дескриптора массива, например, [Lmre/Stuff;
.
Объяснение с примером
Сокращенная Groovy версия того, как я использую ClassReader
, ClassVisitor
и MethodVisitor
, выглядит следующим образом:
package mre
import org.objectweb.asm.*
import java.nio.file.Paths
class ClassTracer extends ClassVisitor {
ClassTracer() { super(Opcodes.ASM8) }
@Override
void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
println "C:visit($version, $access, $name, $signature, $superName, $interfaces)"
}
@Override
MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
println "C:visitMethod($access, $name, $descriptor, $signature, $exceptions)"
new MethodTracer(super.visitMethod(access, name, descriptor, signature, exceptions))
}
}
class MethodTracer extends MethodVisitor {
MethodTracer(MethodVisitor parent) { super(Opcodes.ASM8, parent) }
@Override
void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
println "M:visitMethodInsn($opcode, $owner, $name, $descriptor, $isInterface)"
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface)
}
}
static void main(String[] args) {
if (!args) throw new IllegalArgumentException(("Need class file path argument"))
new ClassReader(Paths.get(args[0]).toFile().bytes).accept(new ClassTracer(), ClassReader.SKIP_FRAMES)
}
При использовании, например, с mre/OneClass.class
из этого примера:
class OtherClass { void run() {} }
class OneClass {
void runOther() {
new OtherClass().run();
}
}
... затем я получаю ожидаемый аргумент внутреннего имени mre/OtherClass
для вызова метода run
:
M:visitMethodInsn(182, mre/OtherClass, run, ()V, false)
Однако при запуске на mre/OneEnum.class
этого перечисления:
enum OneEnum {a, b}
... тогда я неожиданно получаю аргумент дескриптора [Lmre/OneEnum;
для посещения метода клона:
M:visitMethodInsn(182, [Lmre/OneEnum;, clone, ()Ljava/lang/Object;, false)
Хотя это несоответствие выглядит как ошибка для меня, мне интересно, я что-то упустил. Я попытался переключить сгенерированную версию байт-кода между 7,8 и 11, но, похоже, это не имеет значения.
Вопрос
Итак, в двух словах: правильно ли я использую посетителей и оправдано ли мое заблуждение относительно аргумента дескриптора перечисления?