Skip to content

ClassNotFoundException with executable JAR and New Relic agent #1057

Closed
@jdpgrailsdev

Description

@jdpgrailsdev

When using spring-boot 1.1.0.RC1 in combination with the latest New Relic agent, the application fails to start with ClassNotFoundException errors on start up for classes referenced by the main class. I have done some debugging into the spring-boot-loader code and have determined that there appears to be a class loader issue. Our application is being executed with a command similar to the following:

java -javaagent:newrelic.jar -jar myApplication.jar

where myApplication.jar is a spring-boot repackaged JAR file created by the spring-boot Gradle plugin (i.e. it contains all the necessary dependency JARs packaged inside). When the -javaagent option is not present in the command, the application starts successfully. I attached a remote debugger and determined that the issue/difference is with how the doLoadClass method in org.springframework.boot.loader.LaunchedURLClassLoader behaves. When the New Relic agent is NOT present, the call to return this.rootClassLoader.loadClass(name); throws a ClassNotFoundException, which causes the code to "try to find the class locally", per the comment in that method. When the agent is present, the call to the root class loader returns the main class. This then causes an issue, as the main class's class loader is set to the root class loader and not the LaunchedURLClassLoader instance, which knows about the nested/included JAR files from the application's JAR file. My suspicion is that the agent is causing the main class to get loaded into the root class loader during its instrumentation phase, thus causing it to be returned when attempting to launch the main class via the JarLauncher from the loader. The only work around that I have found is to not use the spring-boot-loader at all and include the dependency JAR's externally to the application JAR and run with both the -javaagent and -classpath options. It should also be noted that I verified that the New Relic agent was not making it into the repackaged JAR and verified that the code in ExecutableArchiveLauncher that prevents the agent from being included in the LaunchedURLClassLoader does appear to work, though does not solve this issue. One final twist: this issue does NOT happen if you launch the application via Gradle with the agent option present in the spring-boot configuration in build.gradle. From what I can tell, this is because launching via the Gradle plugin does not use the spring-boot-loader and its launchers: instead, if uses the Gradle Java execution and launches a new VM with the agent and classpath options. This should probably be changed to use the spring-boot-loader for consistency. Let me know if a sample application would be helpful and I will continue to debug this issue on my end to see if I can gain any additional insight into what is going on.

Metadata

Metadata

Assignees

No one assigned

    Labels

    status: invalidAn issue that we don't feel is valid

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions