我有一个代理类,它只是在另一个项目的main()方法之前和之后打印两行。代理类如下所示
public class Agent {
static String packageName = "xxx.hello.world";
public static void premain(String agentArgs, Instrumentation inst) {
inst.addTransformer((classLoader, s, aClass, protectionDomain, bytes) -> {
byte[] transformed = null;
CtClass cl = null;
try {
ClassPool pool = new ClassPool();
pool.insertClassPath(new LoaderClassPath(Thread.currentThread().getContextClassLoader()));
pool.importPackage(packageName);
cl = pool.makeClass(new ByteArrayInputStream(bytes));
CtMethod[] methods = cl.getDeclaredMethods();
for (CtMethod method : methods) {
if ("main".equals(method.getName())) {
method.insertBefore("System.out.println(\"<-----------before------->\");");
method.insertAfter("System.out.println(\"<-----------end------->\");");
}
}
transformed = cl.toBytecode();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cl != null) {
cl.detach();
}
}
return transformed;
});
}}
我有另一个名为“HelloWorld”的项目,它只是在它的main方法中打印“Hi,i am in main()”。HelloWorld.class如下所示
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hi, i am in main()");
}
然后,我将代理打包为一个名为“agent.jar”的jar,并将“-javaagent:xxx/yyy/agent.jar”添加到IDEA中的vmoptions中,如x1c 0d1x所示
在那之后,当我运行hello世界时,我得到了我想要的东西,
<-----------before------->
Hi, i am in main()
<-----------end------->
然而,当我尝试在命令行中运行像“hello-world.jar”这样的jar文件时,
java -javaagent:xxx/yyy/agent.jar -jar hello-world.jar
我得到一个奇怪的错误,
Exception in thread "main" java.lang.NoClassDefFoundError: javassist/ClassPath
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
at java.lang.Class.getDeclaredMethod(Unknown Source)
at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(Unknown Source)
at sun.instrument.InstrumentationImpl.loadClassAndCallPremain(Unknown Source)
Caused by: java.lang.ClassNotFoundException: javassist.ClassPath
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 5 more
这很奇怪,因为我认为这两种方式(在IDEA和在命令行中)是相同的。当我检查hello-world.jar时,我可以看到javassist/ClassPath.class。
谁能告诉我为什么以及如何解决这个问题?
谢谢你,谢谢
2条答案
按热度按时间ki0zmccv1#
我也遇到了同样的问题,你可以参考下面的pom.xml,看看和你在hello-world项目中的区别。
quhf5bfb2#
查找路径有问题。一个可行的解决方法是将 javassist 打包到包含代理的JAR文件中。为此,请执行以下操作:
1.通过以下命令解包 javassist:
jar xf javassist.jar
。这将在工作目录下创建javassist
文件夹,即您发出命令的文件夹。文件夹 javassist 将包含库的所有类文件。1.在构建你的类的时候,包括解包的类,即使用此命令:
jar -cvfm ./my-agent.jar manifest.mf ./my_classes ./javassist