Я пытаюсь использовать ASM в javaagent , чтобы изменить создаваемый класс (sun/misc/URLClassPath
) в другой (fommil/URLClassPath
), который наследуется от него и переопределяет все методы. Я знаю, что целевой класс (java/net/URLClassLoader
), которым я являюсь retransforming
, — единственное, что создает sun/misc/URLClassPath
s и только в его конструкторе.
Основная идея примерно такая:
@Override
public MethodVisitor visitMethod(int access,
String name,
String desc,
String signature,
String[] exceptions) {
MethodVisitor visitor = super.visitMethod(access, name, desc, signature, exceptions);
return new MethodVisitor(Opcodes.ASM5, visitor) {
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
if (opcode == Opcodes.INVOKESPECIAL && "sun/misc/URLClassPath".equals(owner) && "<init>".equals(name)) {
super.visitMethodInsn(opcode, "fommil/URLClassPath", name, desc, itf);
} else {
super.visitMethodInsn(opcode, owner, name, desc, itf);
}
}
};
}
Я могу поместить println
в конструктор fommil/URLClassPath
и посмотреть, как он создается!
Однако ни один из методов fommil.URLClassPath
не вызывается. Всегда вызываются только методы суперкласса.
Даже если я изменю приведенный выше код так, чтобы не только invokespecial
/<init>
, но и все вызовы URLClassPath
были переписаны так, чтобы их invokevirtual
указывали на мой класс, мои методы все равно никогда не вызываются. Я даже пытался сделать это для всех внутренних классов URLClassLoader
.
Так почему же invokevirtual
не находят методы переопределения, даже если они повторно преобразованы? То, что я делаю — изменение типа конструируемой вещи — принципиально невозможно? Если да, то может кто-нибудь объяснить, почему?
Я знаю, что инструментирование основных классов JDK довольно зло, но, честно говоря, у меня нет большой альтернативы.
Единственное, что осталось попробовать, — это инструментировать все классы, которые пытаются создать экземпляр URLClassLoader
, заставить их вставляться во внутреннее поле ucp
и заменять его моей реализацией.