I am write a Java Agent to instrument a target Method of a target Class.
I use the javassist library to do instrument.
So the java agent (let named CnAgent.class) need its dependency : javassist library to run.
The directory hierarchy is :
.
├── META-INF
│ └── MANIFEST.MF
├── com
│ └── yet
│ └── another
│ └── test
│ └── agent
│ ├── CnAgent.class
│ └── CnTransformer.class
└── lib
└── javassist-3.18.2-GA.jar
and the MANIFEST.MF file content is :
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
I create jar ball by following command:
jar cvfm CnAgent.jar META-INF/MENIFIEST.MF . lib
when I load the Agent with Attach API of JVM. the error prints :
error when transform : javassist/ClassPool
java.lang.NoClassDefFoundError: javassist/ClassPool
which means the javassist library cannot be found by agent code.
So my question is :
How to set Agent library's class path letting it find the dependencies?
Why the Class-Path option in MANIFEST.MF not works , does it only for jar directly ran in command line ?
Thanks your wisdom :)
You can use the option -Xbootclasspath: (sets the path) or -Xbootclasspath/a: (appends the given path to the existing boot class path) (refer to doc from oracle). But, as described in the link, it is non-standard.
As an alternative, you can copy the missing jar file in the %JAVA_HOME%/jre/lib/ext directory.
Per Guido's comment above, you should add Boot-Class-Path
to your agent MANIFEST.MF
.
See these java.lang.instrumentation
docs (Manifest Attributes section)
In my case, I have this in Ant's 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>
and then copy the guice and guava jars to the directory I run the command from e.g. java -verbose:class -javaagent:poa.jar -jar ExampleProject.jar > loaded.txt
This also lists all the classes loaded to allow you to debug what Java class loader is actually doing.
Neither option from whiskeyspider worked for my case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With