Abstract
I am reading class files using ASM, and my MethodVisitor gets a strange argument when visiting an enum: The owner argument to visitMethodInsn is supposed to be an internal name (e.g., mre/DoStuff), but for an enum, I get an owner in the form of an array descriptor, e.g., [Lmre/Stuff;.
Explanation with Example
A condensed Groovy version of how I am using the ClassReader, ClassVisitor, and MethodVisitor is the following:
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)
}
When using this with, e.g., the mre/OneClass.class from this example:
class OtherClass { void run() {} }
class OneClass {
void runOther() {
new OtherClass().run();
}
}
... then I get the expected internal name argument mre/OtherClass for the run method call:
M:visitMethodInsn(182, mre/OtherClass, run, ()V, false)
However, when run on the mre/OneEnum.class of this enum:
enum OneEnum {a, b}
... then I unexpectedly get a descriptor argument [Lmre/OneEnum; to a clone method visitation:
M:visitMethodInsn(182, [Lmre/OneEnum;, clone, ()Ljava/lang/Object;, false)
While this inconsistency seems like a bug to me, I am wondering whether I am missing something. I have tried toggling the generated byte code version between 7,8, and 11, but it seems to make no difference.
Question
So, in a nutshell: Am I using the visitors correctly, and is my confusion about the descriptor argument for the enum justified?