If you want to make any source code changes/refactoring you will have to manually find all usages and apply your code changes;
Any way, I have two different aproach
Static search You can simply do
Text Search
in eclipse to find the occurance ofgetA2()
. It will directly take you to the Caller method (here CBusinessObject.verifyA()) -but it will give you every getA2() occurances, may be from different classRun time search Use
java instrumentation API
to change the byte code at run time on your required method to find invoking class and run asjava agent
- Enable you to identify the caller with out touching the existing code base and very useful especially when you don't have access to source code.
Here you go how to implement
Step 1- Write Agent main class to initiate instrumentation
public class BasicAgent {
public static void premain(String agentArguments, Instrumentation instrumentation){
System.out.println("Simple Agent");
FindUsageTransformer transformer = new FindUsageTransformer ();
instrumentation.addTransformer(transformer,true);
}
}
Step 2 -Write a ClassFileTransformer implementation and capture the method
public class FindUsageTransformer implements ClassFileTransformer{
Class clazz = null;
public byte[] transform(ClassLoader loader,String className,Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException {
if(className.equals("A")){
doClass(className, classBeingRedefined, classfileBuffer);
}
return classfileBuffer;
}
private byte[] doClass(String name, Class clazz, byte[] b) {
ClassPool pool = ClassPool.getDefault();
CtClass cl = null;
try {
cl = pool.makeClass(new java.io.ByteArrayInputStream(b));
CtMethod method = cl.getDeclaredMethod("getA2");
// here you have lot of options to explore
method.insertBefore("System.out.println(Thread.currentThread().getStackTrace()[0].getClassName()+ Thread.currentThread().getStackTrace()[0].getMethodName());");
b = cl.toBytecode();
} catch (Exception e) {
System.err.println("Could not instrument " + name
+ ", exception : " + e.getMessage());
} finally {
if (cl != null) {
cl.detach();
}
}
return b;
}
Step 3- create jar file for agent classes ( you have to set manifest file with premain class, and add javaassit jar) snippet of build file is given - you can do it by manually as well
<jar destfile="build/jar/BasicAgent.jar" basedir="build/classes">
<manifest>
<attribute name="Manifest-Version" value="1.0"/>
<attribute name="Premain-Class" value="com.sk.agent.basic.BasicAgent"/>
<attribute name="Boot-Class-Path" value="../lib/javassist.jar"/>
</manifest>
</jar>
Step 4- Run your main application with java agent - before that set VM arguments to load agent
-`javaagent:D:\softwares\AgentProject\AgentLib\build\jar\BasicAgent.jar`
Pre requisite : you would need javassist.jar
in the class path.