I am building a Java agent that should manipulate bytecode using the ASM library. I need to add instructions at the beginning of the specific method. I managed to do that by creating agent following:
public class JavaAgent {
public static void begin(String methodName) throws IOException {
System.err.println("Begin");
}
public static void premain(String agentArgs, Instrumentation inst) throws FileNotFoundException, UnsupportedEncodingException {
MyTransformer transformer = new MyTransformer();
inst.addTransformer(transformer, true);
}
public class MyTransformer implements ClassFileTransformer {
public MyTransformer() {
this.className = className;
this.methodName = methodName;
}
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) {
if (className.equals("MyClass") {
ClassReader classReader = new ClassReader(classfileBuffer);
final ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
classReader.accept(new MyVisitor(classWriter), ClassReader.EXPAND_FRAMES);
return classWriter.toByteArray();
}
return classfileBuffer;
}
}
public class MyVisitor extends ClassVisitor {
public MyVisitor(ClassVisitor classVisitor) {
super(Opcodes.ASM4, classVisitor);
this.className = className;
this.methodName = methodName;
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
if (name.equals("myMethod")) {
return new MyMethodVisitor(super.visitMethod(access, name, desc, signature, exceptions), className, name, methodName);
}
return super.visitMethod(access, name, desc, signature, exceptions);
}
}
public class MyMethodVisitor extends MethodVisitor {
public MyMethodVisitor(MethodVisitor methodVisitor, String className, String methodName, String methodToVisit) {
super(Opcodes.ASM4, methodVisitor);
}
@Override
public void visitCode() {
visitMethodInsn(Opcodes.INVOKESTATIC, "agent/JavaAgent", "begin", "(Ljava/lang/String;)V", false);
super.visitCode();
}
}
This works perfectly with Java in any case, but I have some strange problems in Scala. If I have the following code in Scala everything works and I get a printed message from move
method
import java.io._
class Point(val xc: Int, val yc: Int) {
var x: Int = xc
var y: Int = yc
def move() {
println ("Point x location : " + x);
println ("Point y location : " + y);
}
}
object Demo {
def main(args: Array[String]) {
val pt = new Point(10, 20);
// Move to a new location
pt.move();
}
}
But if I add arguments to move
method I get nothing.
import java.io._
class Point(val xc: Int, val yc: Int) {
var x: Int = xc
var y: Int = yc
def move(xd : Int) {
println ("Point x location : " + x);
println ("Point y location : " + y);
}
}
object Demo {
def main(args: Array[String]) {
val pt = new Point(10, 20);
// Move to a new location
pt.move(2);
}
}
Of course, in the Agent I have class Point
and method move
specified.
Does anyone have an idea what the problem could be?