我正在开发一个项目,尝试将其他Log4j日志记录语句插入到正在运行的webapp中。为了实现这一点,我通过启动Java代理 启动WildFly时的JVM参数:
-javaagent:path/to/agent.jar
代理的premain方法接收Instrumentation对象并建立用于远程访问的MBean。使用Instrumentation和Javassist实现日志记录插入。到目前为止,这完美地运作。 但是,为了使其保持工作,agent.jar还必须在部署时驻留在webapp的WAR文件中,因为用于记录的log4j Logger类随此JAR一起发布。如果没有,我在Instrumentation API更新类定义时会得到VerifyError。但试图加载,例如通过插入像“Math.random()”这样的代码,java.lang中的类按预期工作 重要的是要注意代理类是使用AppClassLoader加载的,AppClassLoader也是应用程序的ModuleClassLoader的父级。 因此,我想知道为什么无法通过ModuleClassLoader委派加载驻留在agent.jar中的类。 这些观察使我假设webapp模块需要声明对外部JAR的显式依赖,即使这些类对于父AppClassLoader是已知的。对于安全问题,这对我来说很有意义。
任何人都可以确认这些假设,或者是否有人有其他想法或经历导致此行为的原因?
谢谢!
----------------编辑---------------------
使用WildFly类加载机制帮助我更详细地描述我的问题。假设我想使用属于我的webapp的ManagedBean中的ModuleClassLoader加载名为 com.example.LoggerClass 的类(驻留在agent.jar!中):
Class<?> aClass = this.getClass().getClassLoader().loadClass("com.example.LoggerClass");
这会导致ClassNotFoundExxception! 但是手动将它委托给底层的AppClassLoader非常有效:
Class<?> aClass = this.getClass().getClassLoader().getParent().loadClass("com.example.LoggerClass");
现在有关ModuleClassLoader的loadClass方法的JBoss文档告诉以下内容:
查找一个类,可能委托给其他加载器
这可以解释我上面显示的行为,假设ModuleClassLoader由于安全问题而没有委托类加载。在某些情况下,有没有办法覆盖它并使ModuleClassLoader委托给AppClassLoader?
答案 0 :(得分:0)
Java代理总是由系统类加载器加载。所有依赖项必须在类路径上可用。如果您遇到验证程序错误,则在加载完成之前验证发生时,您的字节代码是非法的。这意味着,您的问题与类加载器无关。