ASM instrumentação código de bytes de entrada do método / saída
-
13-09-2019 - |
Pergunta
Eu criei um agente JVMTI que faz o seguinte a um nível elevado:
-
onClassLoadHook enviar os bytecodes para a classe carregada a um processo Java separado que instrumento a classe usando ASM
-
obter os bytecodes para trás e carregá-los
No meu processo de java separado que os instrumentos a carregado de classe Java que eu faça o seguinte:
.. ..
cr = new ClassReader(inBytes, offset, inLen);
cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
ClassAdapter ca = new ClassAdapter(cw) {
..
..
@Override
public MethodVisitor visitMethod(final int access,
final String name,
final String desc,
String signature,
String[] exceptions) {
return new MethodAdapter(mv) {
@Override
public void visitCode() {
mv.visitVarInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/amir/Tester", "callTestStatic3", "(Ljava/lang/Object;)V");
mv.visitCode();
}
}
}
Quando tento decompile a classe que está escrito após essa instrumentação usando Java Decompiler - Eu vejo o seguinte função descompilados que eu sei que está errado:
public void func1(int arg1, int arg2)
{
int b;
Tester.callTestStatic3(???);
System.out.println("arg = " + a + " b = " + b);
}
porque minha função realmente se parece com isso:
public void func1(int a, int b)
{
System.out.println("arg = " +a + " b = " +b);
}
Alguém pode me dizer se eu fiz algo errado aqui? Minha única pista é que, se em vez de passar como um argumento para a minha função a este ponteiro, se eu passar em tipos primitivos, tudo funciona finie. Há algo especial sobre o este ponteiro que eu preciso para gerenciar? Eu comparei os bytecodes, e eu usei ASMIFIER para obter uma pista sobre o que declarações que eu preciso usar para gerar o bytecode certas.
Solução
Parece que o seu código está correto, com mv.visitCode (). javap mostra os Bytecodes esperados. Eu acho que o seu decompiler originais simplesmente não estava fazendo a coisa certa.
Outras dicas
Talvez não importa, mas você não deveria estar chamando super.visitCode()
?
@Override
public void visitCode() {
super.visitCode();
...
Eu usaria TraceClassVisitor para verificar exatamente o que estava sendo gerado.