【问题标题】:AspectJ with jar classloader带有 jar 类加载器的 AspectJ
【发布时间】:2019-07-03 00:44:46
【问题描述】:

我正在尝试检测基于 Jetty 构建的 Oracle Rest Data Service (ORDS)。方面应该跟踪 JDBC 调用。我没有看到编织发生。

我在另一个使用 JDBC 的独立应用程序中尝试了 AspectJ,并且还在独立 Jetty 中运行的应用程序中分析了 Servlet 调用,所有这些都对我有用。但在这种情况下,有一个例外,看起来并没有编织正在发生。应用程序本身在应用了所有 AspectJ 配置后按预期工作。

尝试了两个选项:

  • aspect 类和 aop 配置文件被放入 jar 中,这个 jar 被放置在 WEB-INF/lib 中。 aspectjrt.jar 也被复制到此目录中。
  • 方面类和方面配置已复制到 WEB-INF/classes 像这样
   ├── WEB-INF
   │   ├── beans.xml
   │   ├── classes
   │   │   ├── META-INF
   │   │   │   ├── MANIFEST.MF
   │   │   │   └── aop-ajc.xml
   │   │   └── WhereTheStatementTimeGo.class 

在这两种情况下都有如下异常。

这里是命令行和异常:

$JAVA_HOME/bin/java -javaagent:/DATA/PROJECTS/ASPECTJ19/lib/aspectjweaver.jar -Dorg.aspectj.tracing.enabled=true -Dorg.aspectj.tracing.factory=defaug.aspectj.tracing.messages=true   -jar ords.war standalone

[JarClassLoader@17f052a3] warning parse definitions failed -- (IllegalStateException) sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$AppClassLoader@18b4aac2
java.lang.IllegalStateException: sun.misc.Launcher$AppClassLoader@18b4aac2
    at oracle.dbtools.jarcl.NestedResourceHandler.jarClassLoader(NestedResourceHandler.java:36)
    at oracle.dbtools.jarcl.NestedResourceHandler.openConnection(NestedResourceHandler.java:23)
    at java.net.URL.openConnection(URL.java:979)
    at java.net.URL.openStream(URL.java:1045)
    at org.aspectj.weaver.loadtime.definition.DocumentParser.saxParsing(DocumentParser.java:157)
    at org.aspectj.weaver.loadtime.definition.DocumentParser.parse(DocumentParser.java:123)
    at org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.parseDefinitions(ClassLoaderWeavingAdaptor.java:290)
    at org.aspectj.weaver.loadtime.DefaultWeavingContext.getDefinitions(DefaultWeavingContext.java:130)
    at org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.initialize(ClassLoaderWeavingAdaptor.java:174)
    at org.aspectj.weaver.loadtime.Aj$ExplicitlyInitializedClassLoaderWeavingAdaptor.initialize(Aj.java:337)
    at org.aspectj.weaver.loadtime.Aj$ExplicitlyInitializedClassLoaderWeavingAdaptor.getWeavingAdaptor(Aj.java:342)
    at org.aspectj.weaver.loadtime.Aj$WeaverContainer.getWeaver(Aj.java:316)
    at org.aspectj.weaver.loadtime.Aj.preProcess(Aj.java:108)
    at org.aspectj.weaver.loadtime.ClassPreProcessorAgentAdapter.transform(ClassPreProcessorAgentAdapter.java:51)
    at sun.instrument.TransformerManager.transform(TransformerManager.java:188)
    at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:428)
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
    at oracle.dbtools.jarcl.JarClassLoader.findClass(JarClassLoader.java:77)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at oracle.dbtools.jarcl.Entrypoint.invoke(Entrypoint.java:50)
    at oracle.dbtools.jarcl.Entrypoint.main(Entrypoint.java:77)

2019-07-02 16:47:29.822:INFO::main: Logging initialized @3375ms to org.eclipse.jetty.util.log.StdErrLog
Jul 02, 2019 4:47:29 PM  
INFO: HTTP and HTTP/2 cleartext listening on port: 8080
Jul 02, 2019 4:47:29 PM  
INFO: Disabling document root because the specified folder does not exist: /Users/slinetsk/Downloads/ORDS/ords/standalone/doc_root
2019-07-02 16:47:30.632:INFO:oejs.Server:main: jetty-9.4.z-SNAPSHOT; built: 2019-02-20T15:50:58.683Z; git: 3285c4dd4bb00caddcded77f8e44e72c61b9ab72; jvm 1.8.0_211-b12
2019-07-02 16:47:30.693:INFO:oejs.session:main: DefaultSessionIdManager workerName=node0
2019-07-02 16:47:30.693:INFO:oejs.session:main: No SessionScavenger set, using defaults
2019-07-02 16:47:30.694:INFO:oejs.session:main: node0 Scavenging every 600000ms

输出中没有任何 AspectJ 跟踪相关信息

【问题讨论】:

  • 欢迎来到 SO,谢尔盖。这就是它在这里的工作方式:首先你了解MCVE 是什么,然后你提供一个,或者在你的问题中内联(单击“编辑”),或者你可以添加一个指向包含 MCVE 的 GitHub 存储库的链接(删除版权-首先是受保护的东西,然后留出足够的空间让我构建和运行应用程序,例如通过 Maven,然后重现问题)。仅错误日志不足以让我回答您的问题。
  • 谢谢。我确实有一个例子,但它不符合 MCVE 的条件。它是 VirtualBox 的虚拟机,里面有 Oracle DB 和 ORDS。问题是 VM 映像的大小为 26GB。我希望 Jar 类加载器的问题是已知的。
  • 我确信一个简单的 Jetty 设置也可以在容器外运行。也许这个问题也可以通过另一个不需要 Oracle DB 在后台的第 3 方库重现。即使它确实需要一个 Oracle 库,也可能在进行真正的数据库访问之前发生错误,堆栈跟踪建议类加载时间。那应该是可重现的。你需要帮助吗?帮助您的潜在帮手!通过创建 MCVE,您通常甚至可以更多地了解您自己的问题。
  • Jetty 本身一切正常,我将尝试访问 ORDS 的源代码以查看 oracle.dbtools.jarcl 的使用方式(部分 oracle.dbtools.jarcl.JarClassLoader.findClass (JarClassLoader.java:77在调用栈)创建MCVE
  • 其实我下载了ORDS,可以重现错误。看起来 Oracle 的自定义 JAR 类加载器做了一些 AspectJ 编织代理不喜欢但没有准备好的解决方案。我尝试通过-Daj.weaving.loadersToSkip=oracle.dbtools.jarcl.JarClassLoader 排除类加载器。这行得通,但是编织器将不再在库 JAR 中编织任何东西。您可以创建一个自定义 WAR,并在其中解压缩感兴趣的库。丑陋,但至少编织者会找到目标类。

标签: aspectj load-time-weaving


【解决方案1】:

我找到了一种解决方法,它让我可以毫无问题地运行服务器,并且还可以在各种类(例如内部 Jetty 类)上使用不同类型的切面切入点:

将 AspectJ weaver 和您的方面库(包含方面的 JAR 和 META-INF/aop.xml)复制到您开始 的子目录 lib >ords.war。然后将方面库附加到 JVM 引导类路径。您需要使用像 Java 8 这样的 JRE/JDK 版本,它实际上仍然支持引导类路径。 (其实我刚查过,JDK 11 仍然支持它。) 我不知道如何使用模块化的 JRE 来做到这一点。然后像这样开始你的 WAR:

java -Xbootclasspath/a:lib/aspect.jar -javaagent:lib/aspectjweaver.jar -jar ords.war standalone

再一次,插入换行符:

java
  -Xbootclasspath/a:lib/aspect.jar
  -javaagent:lib/aspectjweaver.jar
  -jar ords.war standalone

这种方法可确保在 Oracle JAR 类加载器执行其入口点魔法之前,已附加编织器并找到其以及方面类。

请注意,这里根本不需要修改 WAR 文件。


更新:作为替代方案,您可以动态附加 AspectJ 编织代理,而不是通过 -javaagent,请参阅

我很快测试了它,它有效。不过,这有点棘手:

  • 您必须将类似于 AspectJ 自述文件中的主类作为主类放入 WAR 中。该类将附加编织器,然后启动 JAR 类加载器。现在织布机已经到位,一切都按预期工作。
  • 需要注意的是,您需要在类路径上使用tools.jar、myaspect.jar 和aspectjweaver.jar 启动JVM,
    • 如果您想使用java -jar my.war 启动应用程序,则在引导类路径中
    • 或在正常的类路径上,如果可以使用-cp ...;my.war my.own.MainClass 启动应用程序,则可以。
  • 此外,从 Java 9 开始,不再有 tools.jar,但您需要使自己的入口点类依赖于模块 jdk.attach,并确保您实际使用 JDK 而不是 JRE 运行应用程序。否则,您将无法使用 API 动态附加代理。

总而言之我还是喜欢原来的解决方案,它更容易实现。

【讨论】:

  • 我创建了 MCVE,它是 ORDS 的剥离版本,只有类加载器组件。可以从这里github.com/lsa5521/AJCUSTLOADERTEST下载。我已使用此代码确认建议的解决方法确实有效。谢谢!
  • 那么我很高兴看到你接受 + 支持我的回答,谢尔盖。有趣的问题,这是我星期天早上喝茶时的谜题。 ;-)
  • 我刚刚更新了答案。我尝试了另一个解决方案,并使用另一个 JAR 类加载器在我自己的项目中验证了它(因为与加载时编织有关的问题是相同的)。
  • 另一个更新:原来的解决方案不需要启动类路径上的编织代理JAR,方面JAR就足够了,因为无论如何通过-javaagent:lib\aspectjweaver.jar找到了编织器。
  • 我绝对接受答案,正如我已经提到的那样,但我看不到如何在网站上做到这一点。看来我还没有足够的声望点这样做
猜你喜欢
  • 2012-07-01
  • 2011-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-04
  • 1970-01-01
  • 2018-03-14
相关资源
最近更新 更多