Tar*_*rek 13 java eclipse hierarchy
解释这有点棘手.我有一个A类:
public class A {
private Integer a1;
private Integer a2;
// getters and setters.
}
Run Code Online (Sandbox Code Playgroud)
有一个静态类B返回我的类A:
public static class B {
public static A getCurrentA() {
return a;
}
}
Run Code Online (Sandbox Code Playgroud)
我需要找到B返回的所有A类用法.所以让我们说C级呼叫c.setA(B.getCurrentA()),然后再进一步调用c.getA().getA2();,我想找到所有这些.
在真实场景中,我有217个不同的类调用B.getCurrentA().我不能手动跟踪Eclipse中的所有调用,并找出调用哪些方法.
Eclipse调用层次结构视图仅向我显示所有调用B.getCurrentA().
我怎样才能做到这一点?
编辑
克里斯海耶斯明白我想做什么.为了在不破坏整个系统的情况下重构一些非常糟糕的遗留代码,我需要首先使用Hibernate的投影微调一些查询(系统中的每个映射实体都被急切加载,并且许多实体是相关的,因此一些查询需要很长时间时间取出一切).但首先我需要找到使用哪些属性,以便我不会在某处获得NullPointerException ...
这是我手动做的一个例子:
打开找到的第一个方法,让我们说它是下面的方法:
public class CController {
C c = new C();
CFacade facade = new CFacade();
List<C> Cs = new ArrayList<C>();
public void getAllCs() {
c.setA(B.getCurrentA()); // found it!
facade.search(c);
}
}
Run Code Online (Sandbox Code Playgroud)在CFacade类中打开搜索方法:
public class CFacade {
CBusinessObject cBo = new CBusinessObject();
public List<C> search(C c) {
// doing stuff...
cBo.verifyA(c);
cBo.search(c); // yes, the system is that complicated
}
}
Run Code Online (Sandbox Code Playgroud)打开CBusinessObject类中的verifyA方法并标识使用的字段a2:
public class CBusinessObject {
public void verifyA(c) {
if (Integer.valueOf(1).equals(c.getA().getA2())) {
// do stuff
else {
// something else
}
}
}
Run Code Online (Sandbox Code Playgroud)接下来的216场比赛重复步骤2-4 ......耶.
请帮忙.
Sat*_*eri 12
如果要更改/重构任何源代码,则必须手动查找所有用法并应用代码更改;
无论如何,我有两种不同的方法
静态搜索你可以简单地Text Search在eclipse中找到它的出现getA2().它将直接带你到Caller方法(这里是CBusinessObject.verifyA()) - 但是它会给你每个getA2()的出现,可能来自不同的类
运行时搜索用于java instrumentation API在运行时更改所需方法的字节代码以查找调用类并运行为java agent - 使您能够识别调用者而不触及现有代码库,并且非常有用,尤其是当您无法访问源代码时码.
在这里,您将了解如何实施
步骤1-编写代理主类以启动检测
public class BasicAgent {
public static void premain(String agentArguments, Instrumentation instrumentation){
System.out.println("Simple Agent");
FindUsageTransformer transformer = new FindUsageTransformer ();
instrumentation.addTransformer(transformer,true);
}
}
Run Code Online (Sandbox Code Playgroud)
第2步 - 编写ClassFileTransformer实现并捕获该方法
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;
}
Run Code Online (Sandbox Code Playgroud)
步骤3-为代理类创建jar文件(你必须设置带有premain类的清单文件,并添加javaassit jar)给出构建文件的片段 - 你也可以手动完成
<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>
Run Code Online (Sandbox Code Playgroud)
步骤4-使用java代理运行主应用程序 - 在此之前将VM参数设置为加载代理
-`javaagent:D:\softwares\AgentProject\AgentLib\build\jar\BasicAgent.jar`
Run Code Online (Sandbox Code Playgroud)
先决条件:您需要javassist.jar在课程路径中.