【问题标题】:NoClassDefFoundError when method call inserted via instrumentation is called via sun.reflect.NativeConstructorAccessorImpl.newInstance0通过 sun.reflect.NativeConstructorAccessorImpl.newInstance0 调用通过检测插入的方法调用时的 NoClassDefFoundError
【发布时间】:2015-10-12 20:41:51
【问题描述】:

我使用 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.(未知来源) 在 sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 在 sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) 在 sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) 在 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) 在 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 本身内部解决这个问题?我希望尽可能轻松地使用此代理,而无需我的用户进行太多配置。

【问题讨论】:

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


    【解决方案1】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-17
      • 1970-01-01
      • 2019-12-20
      相关资源
      最近更新 更多