lsongseven
lsongseven

Reputation: 21

strange exception of "java.lang.NoClassDefFoundError: javassist/ClassPath" when running with commandline

I hava a agent class, it simply print two lines before and after another project's main() method. The agent class is as follows

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;

    });
}}

And I have another project named as "HelloWorld", it simply print "Hi, i am in main()" in it's main method. The HelloWorld.class is as follows

public class HelloWorld {
public static void main(String[] args) {
    System.out.println("Hi, i am in main()");
}

Then I package the agent as a jar named as "agent.jar", and add "-javaagent:xxx/yyy/agent.jar" to vmoptions in IDEA, like this enter image description here

After that , when I run the hello-world, I get what i want like

<-----------before------->
 Hi, i am in main()
<-----------end------->

However, when I try to run the hello-world as a jar like "hello-world.jar" in command line like

java -javaagent:xxx/yyy/agent.jar -jar hello-world.jar

I get a strange error like

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

It is quite strange because I think the two ways (in IDEA and in command line) are the same. And when i check the hello-world.jar, i can see the javassist/ClassPath.class. enter image description here

Can any tell me why and how to fix this problem?

Thanks!

Upvotes: 1

Views: 2288

Answers (2)

There is something wrong with lookup paths. A possible workaround is to pack javassist into the JAR file containing the agent. To do that, perform the following:

  1. Unpack javassist via this command: jar xf javassist.jar. That will create javassist folder below the working directory, i.e. the folder from where you issued the command. Folder javassist will contain all class files of the library.
  2. Include the unpacked classes when building your JAR, i.e. use this command:
    jar -cvfm ./my-agent.jar manifest.mf ./my_classes ./javassist

Upvotes: 0

Richard
Richard

Reputation: 183

I faced the same issue, you can refer to the pom.xml below, and see the difference with yours in hello-world project.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.richard</groupId>
    <artifactId>my-agent-test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <java.version>1.8</java.version>
    </properties>


    <build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <mainClass>com.richard.Main</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>org.javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.20.0-GA</version>
        </dependency>
    </dependencies>

</project>

Upvotes: 0

Related Questions