I am trying to instrument Oracle Rest Data Service (ORDS) which is built on Jetty. The aspect should trace JDBC calls. I do not see the weaving happening.
I have tried AspectJ in a different standalone application which used JDBC and also profiled Servlet calls in an application running in standalone Jetty and all this worked for me. But in this case there is an exception and it does not look that weaving is happening. Application itself works as expected with all AspectJ configurations applied.
Two options have been tried:
├── WEB-INF
│ ├── beans.xml
│ ├── classes
│ │ ├── META-INF
│ │ │ ├── MANIFEST.MF
│ │ │ └── aop-ajc.xml
│ │ └── WhereTheStatementTimeGo.class
There was an exception like below in both cases.
Here is the command line and the exception:
$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
There was no any AspectJ tracing related info in the output
I found a workaround which lets me run the server without problems and also use different types of aspect pointcuts on all sorts of classes such as internal Jetty classes:
Copy the AspectJ weaver and your aspect library (JAR containing aspects and META-INF/aop.xml) to a subdirectory lib of where you are starting your ords.war. Then append the aspect library to the JVM boot classpath. You need to use a JRE/JDK version like Java 8 which actually still supports the boot classpath. (Actually I just checked, JDK 11 still supports it.) I don't know how to do this with modularised JREs. Then start your WAR like this:
java -Xbootclasspath/a:lib/aspect.jar -javaagent:lib/aspectjweaver.jar -jar ords.war standalone
One more time, with line breaks inserted:
java
-Xbootclasspath/a:lib/aspect.jar
-javaagent:lib/aspectjweaver.jar
-jar ords.war standalone
This approach makes sure that the weaver is attached and its as well as the aspect classes are found before the Oracle JAR classloader does its entry point magic.
Please note that you do not need to modify the WAR file at all here.
Update: As an alternative you could attach the AspectJ weaving agent dynamically instead of via -javaagent
, see
I quickly tested it, it works. It is kind of tricky, though:
tools.jar
, myaspect.jar
and aspectjweaver.jar
on the classpath,
java -jar my.war
-cp ...;my.war my.own.MainClass
.tools.jar
anymore but you need to make your own entry point class dependent on the module jdk.attach
and also make sure that you actually run the application with a JDK, not a JRE. Otherwise you cannot use the API for dynamically attaching agents.All in all I still favour the original solution, it is much easier to implement.