如何为java代理指定类路径

时间:2014-10-09 13:59:26

标签: java jvm jvm-hotspot

我正在编写一个Java代理来检测目标类的目标方法。

我使用javassist库来做乐器。

所以java代理(让我们命名为CnAgent.class)需要它的依赖:javassist库来运行。

目录层次结构为:

.
├── META-INF
│   └── MANIFEST.MF
├── com
│   └── yet
│       └── another
│           └── test
│               └── agent
│                   ├── CnAgent.class
│                   └── CnTransformer.class
└── lib
    └── javassist-3.18.2-GA.jar

和MANIFEST.MF文件内容为:

Manifest-Version: 1.0
Class-Path: lib/javassist-3.18.2-GA.jar .
Agent-Class: com.yet.another.test.agent.CnAgent
Created-By: 1.8.0_11 (Oracle Corporation)
Can-Retransform-Classes: true

我按照以下命令创建了jar球:

jar cvfm CnAgent.jar META-INF/MENIFIEST.MF . lib

当我使用JVM的Attach API加载代理时。 错误打印:

error when transform : javassist/ClassPool
java.lang.NoClassDefFoundError: javassist/ClassPool

表示代理程序代码无法找到javassist库。

所以我的问题是:

  1. 如何设置代理库的类路径,让它找到依赖项?

  2. 为什么MANIFEST.MF中的Class-Path选项不起作用,是否仅在jar中直接在命令行中运行?

  3. 感谢你的智慧:)

2 个答案:

答案 0 :(得分:3)

您可以使用选项-Xbootclasspath :(设置路径)或-Xbootclasspath / a :(将给定路径附加到现有引导类路径)(请参阅doc from oracle)。但是,如链接中所述,它是非标准的。

作为替代方法,您可以将缺少的jar文件复制到%JAVA_HOME%/ jre / lib / ext目录中。

答案 1 :(得分:0)

上面的每Guido's条评论,您应该向代理商Boot-Class-Path添加MANIFEST.MF

请参阅这些java.lang.instrumentation文档(清单属性部分)

就我而言,我在Ant的build.xml中有这个:

    <manifest file="META-INF/MANIFEST.MF">
       <attribute name="Premain-Class" value="de.bodden.tamiflex.playout.Agent"/>
       <attribute name="Main-Class" value="de.bodden.tamiflex.playout.Agent"/>
       <attribute name="Can-Retransform-Classes" value="true"/>
       <attribute name="Implementation-Version" value="${tf.version}"/>
       <attribute name="Boot-Class-Path" value="guava-22.0.jar:guice-4.1.0.jar" />
   </manifest>

然后将guice和guava jar复制到我运行命令的目录中。 java -verbose:class -javaagent:poa.jar -jar ExampleProject.jar > loaded.txt

这也列出了所有加载的类,以便您调试Java类加载器实际正在执行的操作。

whiskeyspider的选项都不适用于我的案例。