百度上的方法最多是破坏封装性的直接通过setAccessible加jar url。setAccessible 简单暴力,但是破坏了封装性,jdk版本随便改一下,可能就挂了。
还有一种方法是通过urlclassloader类,手动管理jar。但是这种方法会导致agent失效,从而导致程序无法正常运行。
Instrumentation 方法
最完美的方法是利用java agent的Instrumentation接口的appendToSystemClassLoaderSearch方法。
我找了很久才找到这个方法,线索是AppClassLoader的appendToClassPathForInstrumentation方法。
在项目里新建一个类
import java.lang.instrument.Instrumentation;
public class InstrumentationHolder {
public static Instrumentation instrumentation;
public static void premain(String agentOps, Instrumentation inst) {
instrumentation = inst;
}
}
把这个编译好的class按包名目录添加到一个zip中
然后在压缩包里添加META-INF/MANIFEST.MF文件
内容为
Manifest-Version: 1.0
Premain-Class: org.tomorrow.InstrumentationHolder
Can-Redefine-Classes: true
Premain-Class为之前新建的类名
然后可以把jar放到项目的资源目录
然后在IDE里面添加jvm参数
-javaagent:.\target\classes\agent.jar(zip文件路径)
这里以eclipse为例
然后只要启动,就可以通过在项目里通过这个Class获得Instrumentation了
之后只要用这个class操作就行了
Instrumentation只能加入jar,如果是文件夹就自己压缩一下