Skip to content

Latest commit

 

History

History
57 lines (48 loc) · 2.09 KB

agent.md

File metadata and controls

57 lines (48 loc) · 2.09 KB
title tags keywords
Agent
usage
agent, usage, java, loadtime

Spoon Agent

Spoon can also be used to transform classes at load time in the JVM. For this, SpoonClassFileTransformer provide an abstraction of ClassFileTransformer where the user can define Spoon transformation. Bytecode of classes will be decompiled on-the-fly when loaded, and the Spoon AST will be updated in consequence, and the code is recompiled on-the-fly.

The following example shows the definition of a basic JVM agent for inserting a tracing method call at the end of every method called foo.

Here is the agent:

public class Agent {
	public static void premain(String agentArgs, Instrumentation inst) {
		System.out.println( "Hello Agent" );

		//Create a SpoonClassFileTransformer, that
		// * excludes any classes not in our package from decompilation
		// * adds the statement System.out.println("Hello <className>"); to the (first) method named "foo" of every classes
        SpoonClassFileTransformer transformer = new SpoonClassFileTransformer(
                cl -> cl.startsWith("org/my/package"),
                new InsertPrintTransformer()
        );
		inst.addTransformer(transformer);

		System.out.println( "Agent Done." );
	}
}
public class InsertPrintTransformer implements TypeTransformer {

	@Override
	public boolean accept(CtType type) {
		if ((type instanceof CtClass) &&
				type.getMethodsByName("foo").size() > 0) {
			return true;
		} else {
			return false;
		}
	}

	@Override
	public void transform(CtType type) {
		System.err.println("Transforming " + type.getQualifiedName());
		CtMethod main = (CtMethod) type.getMethodsByName("foo").get(0);
		main.getBody().addStatement(type.getFactory().createCodeSnippetStatement("System.out.println(\"Hello " + type.getQualifiedName() + "\");"));
		System.err.println("Done transforming " + type.getQualifiedName());
	}
}

⚠️ The SpoonClassFileTransformer feature (and all features relying on decompilation) are not included in spoon-core but in spoon-decompiler. If you want to use them you should declare a dependency to spoon-decompiler.