通过检测插入方法调用时,通过sun.reflect.NativeConstructorAccessorImpl.newInstance0

时间:2015-07-22 19:20:47

标签: java logging bytecode instrumentation java-bytecode-asm

我使用ASM创建了一个JavaAgent,它在正在加载的类的特定区域插入方法调用( INVOKESTATIC org / test / Logger / Log )。 插入的方法调用( org / test / Logger / Log )在JavaAgent本身中声明。

这在正常情况下有效,并且调用插入的方法调用。

我在JBOSS中配置了这个代理并启动了服务器。代理程序已正确注册,并且多次调用org / test / Logger / Log方法。

但它最终崩溃了NoClassDefFoundError:

  

线程中的异常" main" java.lang.NoClassDefFoundError:org / test / Logger / Log               在org.apache.xerces.jaxp.SAXParserFactoryImpl。(未知来源)               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)               在java.lang.Class.newInstance0(Class.java:355)               在java.lang.Class.newInstance(Class.java:308)               在javax.xml.parsers.FactoryFinder.newInstance(FactoryFinder.java:147)               在javax.xml.parsers.FactoryFinder.findJarServiceProvider(FactoryFinder.java:298)               在javax.xml.parsers.FactoryFinder.find(FactoryFinder.java:223)               在javax.xml.parsers.SAXParserFactory.newInstance(SAXParserFactory.java:128)               在org.jboss.xb.binding.parser.sax.SaxJBossXBParser。(SaxJBossXBParser.java:54)               在org.jboss.xb.binding.UnmarshallerImpl。(UnmarshallerImpl.java:56)               at org.jboss.xb.binding.UnmarshallerFactory $ UnmarshallerFactoryImpl.newUnmarshaller(UnmarshallerFactory.java:96)               在org.jboss.bootstrap.xml.BootstrapParser.parse(BootstrapParser.java:50)               在org.jboss.bootstrap.microcontainer.ServerImpl.doStart(ServerImpl.java:123)               在org.jboss.bootstrap.AbstractServerImpl.start(AbstractServerImpl.java:450)               在org.jboss.Main.boot(Main.java:221)               在org.jboss.Main $ 1.run(Main.java:556)               在java.lang.Thread.run(Thread.java:662)

我猜是因为 org.apache.xerces.jaxp.SAXParserFactoryImpl。方法是通过 sun.reflect 调用的,它可能正在使用不同的类加载器而它不会把我的javaagent放在它的路径上。

这里可能出现什么问题,如何从javaagent本身解决这个问题?我想尽可能简单地使用这个代理,而我的用户不必进行太多的配置。

1 个答案:

答案 0 :(得分:1)

Java代理总是由系统类加载器加载,它在类路径上查找其资源。您需要将记录器添加到类路径中。

运行应用程序服务器时,系统类加载器不会加载您的应用程序,而是使用特定于您正在运行的应用程序的类加载器。然后,记录器不可用于系统类加载器。

您需要将已检测类使用的所有文件包含在代理程序jar中,并从类路径类访问数据。请注意,应用程序服务器通常实现 child-first 类加载器。如果将记录器类添加到代理程序和应用程序中,您将实际访问两个不同的记录器类。

通常,在Maven项目中,您可以在单独的模块中创建代理jar,并将提供的范围中的记录器包含在您的实际应用程序中。