带有 jar 类加载器的 AspectJ
AspectJ with jar classloader
我正在尝试检测基于 Jetty 构建的 Oracle Rest Data Service (ORDS)。该方面应跟踪 JDBC 调用。我没有看到编织发生。
我已经在另一个使用 JDBC 的独立应用程序中尝试了 AspectJ,并且还在独立 Jetty 中的应用程序 运行 中分析了 Servlet 调用,所有这些都对我有用。但在这种情况下有一个例外,看起来并没有发生编织。应用程序本身在应用所有 AspectJ 配置的情况下按预期工作。
已尝试两种方案:
- aspect class 和 aop 配置文件被放入 jar 中,这个 jar 被放置在 WEB-INF/lib 中。 aspectjrt.jar 也被复制到此目录中。
- 方面 class 和方面配置已复制到 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 跟踪相关信息
我找到了一个解决方法,它让我 运行 服务器没有问题,并且还在各种 classes 上使用不同类型的方面切入点,例如内部 Jetty classes:
将 AspectJ 编织器和方面库(包含方面和 META-INF/aop.xml 的 JAR 复制到子目录 lib 您开始 ords.war 的地方。然后将方面库附加到 JVM 引导 class 路径。您需要使用像 Java 8 这样的 JRE/JDK 版本,它实际上仍然支持引导 class 路径。 (其实我刚刚查了一下,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 classloader 执行其入口点魔术之前找到 weaver 及其方面 classes。
请注意,您根本不需要在此处修改 WAR 文件。
更新: 作为替代方案,您可以动态附加 AspectJ 编织代理,而不是通过 -javaagent
,请参阅
我很快测试了它,它有效。不过有点棘手:
- 您必须将您自己的主 class 与 AspectJ read-me 中的那个类似,作为主 class 放入 WAR 中。 class 将附加编织器,然后启动 JAR classloader。现在编织器已经到位,一切都按预期工作。
- 需要注意的是,您需要在 class 路径上使用
tools.jar
、myaspect.jar
和 aspectjweaver.jar
启动 JVM,
- 如果您想使用
java -jar my.war
启动应用程序,则在启动 classpath 上
- 或在正常的 class 路径上 您是否可以使用
-cp ...;my.war my.own.MainClass
. 启动应用程序
- 此外,自 Java 9 以来,不再有
tools.jar
,但您需要根据模块 jdk.attach
创建自己的入口点 class,并确保您实际上 运行 带有 JDK 的应用程序,而不是 JRE。否则您不能使用 API 动态附加代理。
总而言之我还是喜欢原来的方案,实现起来简单多了。
我正在尝试检测基于 Jetty 构建的 Oracle Rest Data Service (ORDS)。该方面应跟踪 JDBC 调用。我没有看到编织发生。
我已经在另一个使用 JDBC 的独立应用程序中尝试了 AspectJ,并且还在独立 Jetty 中的应用程序 运行 中分析了 Servlet 调用,所有这些都对我有用。但在这种情况下有一个例外,看起来并没有发生编织。应用程序本身在应用所有 AspectJ 配置的情况下按预期工作。
已尝试两种方案:
- aspect class 和 aop 配置文件被放入 jar 中,这个 jar 被放置在 WEB-INF/lib 中。 aspectjrt.jar 也被复制到此目录中。
- 方面 class 和方面配置已复制到 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 跟踪相关信息
我找到了一个解决方法,它让我 运行 服务器没有问题,并且还在各种 classes 上使用不同类型的方面切入点,例如内部 Jetty classes:
将 AspectJ 编织器和方面库(包含方面和 META-INF/aop.xml 的 JAR 复制到子目录 lib 您开始 ords.war 的地方。然后将方面库附加到 JVM 引导 class 路径。您需要使用像 Java 8 这样的 JRE/JDK 版本,它实际上仍然支持引导 class 路径。 (其实我刚刚查了一下,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 classloader 执行其入口点魔术之前找到 weaver 及其方面 classes。
请注意,您根本不需要在此处修改 WAR 文件。
更新: 作为替代方案,您可以动态附加 AspectJ 编织代理,而不是通过 -javaagent
,请参阅
我很快测试了它,它有效。不过有点棘手:
- 您必须将您自己的主 class 与 AspectJ read-me 中的那个类似,作为主 class 放入 WAR 中。 class 将附加编织器,然后启动 JAR classloader。现在编织器已经到位,一切都按预期工作。
- 需要注意的是,您需要在 class 路径上使用
tools.jar
、myaspect.jar
和aspectjweaver.jar
启动 JVM,- 如果您想使用
java -jar my.war
启动应用程序,则在启动 classpath 上
- 或在正常的 class 路径上 您是否可以使用
-cp ...;my.war my.own.MainClass
. 启动应用程序
- 如果您想使用
- 此外,自 Java 9 以来,不再有
tools.jar
,但您需要根据模块jdk.attach
创建自己的入口点 class,并确保您实际上 运行 带有 JDK 的应用程序,而不是 JRE。否则您不能使用 API 动态附加代理。
总而言之我还是喜欢原来的方案,实现起来简单多了。