1

I have created a JavaAgent using ASM that inserts method calls (INVOKESTATIC org/test/Logger/Log) at specific areas of in a class being loaded. The inserted method calls (org/test/Logger/Log) are declared in the JavaAgent itself.

This works under normal circumstances and the inserted method calls are called.

I configured this agent in JBOSS and started the server. The agent gets registered properly and the org/test/Logger/Log method is called several times.

But it eventually crashes with a NoClassDefFoundError:

Exception in thread "main" java.lang.NoClassDefFoundError: org/test/Logger/Log at org.apache.xerces.jaxp.SAXParserFactoryImpl.(Unknown Source) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at java.lang.Class.newInstance0(Class.java:355) at java.lang.Class.newInstance(Class.java:308) at javax.xml.parsers.FactoryFinder.newInstance(FactoryFinder.java:147) at javax.xml.parsers.FactoryFinder.findJarServiceProvider(FactoryFinder.java:298) at javax.xml.parsers.FactoryFinder.find(FactoryFinder.java:223) at javax.xml.parsers.SAXParserFactory.newInstance(SAXParserFactory.java:128) at org.jboss.xb.binding.parser.sax.SaxJBossXBParser.(SaxJBossXBParser.java:54) at org.jboss.xb.binding.UnmarshallerImpl.(UnmarshallerImpl.java:56) at org.jboss.xb.binding.UnmarshallerFactory$UnmarshallerFactoryImpl.newUnmarshaller(UnmarshallerFactory.java:96) at org.jboss.bootstrap.xml.BootstrapParser.parse(BootstrapParser.java:50) at org.jboss.bootstrap.microcontainer.ServerImpl.doStart(ServerImpl.java:123) at org.jboss.bootstrap.AbstractServerImpl.start(AbstractServerImpl.java:450) at org.jboss.Main.boot(Main.java:221) at org.jboss.Main$1.run(Main.java:556) at java.lang.Thread.run(Thread.java:662)

I am guessing since the org.apache.xerces.jaxp.SAXParserFactoryImpl. method is called through sun.reflect it might be using a different classloader and it does not have my javaagent in its path.

What could be going wrong here and how can I address this from within from javaagent itself? I want to make using this agent as easy as possible without my user's having to do too many configurations.

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192
Veni
  • 11
  • 3

1 Answers1

1

A Java agent is always loaded by the system class loader which finds its resources on the class path. You need to add your logger to the class path.

When running an application server, your application is not loaded by the system class loader but with a class loader that is specific to the application you are running. The logger is then not available to the system class loader.

You need to include all files that are used by your instrumented class to the agent jar and access data from the class path class. Note that application servers typically implement child-first class loaders. If you add your logger class to both the agent and your app, you will actually access two different logger classes.

Typically, in for example a Maven project, you would create the agent jar in a seperate module and include the logger in a provided scope into your actual application.

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192