aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUri Simchoni <urisimchoni@gmail.com>2024-02-04 12:51:15 +0200
committerAlexander Kriegisch <Alexander@Kriegisch.name>2024-02-08 12:17:55 +0700
commitefef3c0792f521256fc3889744878ead11f8324a (patch)
treeba6209138685e28ff5a07d56ac4d7c90bfae2543
parent5cdff3bf0c7c62d42ab2022e0ac4ed55ef63108a (diff)
downloadaspectj-efef3c0792f521256fc3889744878ead11f8324a.tar.gz
aspectj-efef3c0792f521256fc3889744878ead11f8324a.zip
Use previous weaving result if classes were generated during weaving
A parallel-capable class loader might load the same class multiple times in multiple threads, see https://docs.oracle.com/javase/7/docs/technotes/guides/lang/cl-mt.html. In this scenario, the JVM instrumentation mechanism invokes the AspectJ weaver twice on the same class. In simple weaving scenarios, this would just cause weaving logic to run multiple times and produce the same result for each thread, but if the weaver is generating new classes, it is undesirable to generate those classes multiple times. To avoid this, the generatedClasses map in WeavingAdaptor keeps track of classes for which inner classes were generated and avoids re-weaving them. However, before this change, if a class was found in the generated map, the weaver would return the un-woven bytes, which would cause AspectJ not to work for some of the threads. This change returns the woven bytes instead of re-running weaving. Fixes #279.
-rw-r--r--weaver/src/main/java/org/aspectj/weaver/tools/WeavingAdaptor.java25
1 files changed, 24 insertions, 1 deletions
diff --git a/weaver/src/main/java/org/aspectj/weaver/tools/WeavingAdaptor.java b/weaver/src/main/java/org/aspectj/weaver/tools/WeavingAdaptor.java
index 009aa7daa..551ef45e6 100644
--- a/weaver/src/main/java/org/aspectj/weaver/tools/WeavingAdaptor.java
+++ b/weaver/src/main/java/org/aspectj/weaver/tools/WeavingAdaptor.java
@@ -358,9 +358,17 @@ public class WeavingAdaptor implements IMessageContext {
boolean debugOn = !messageHandler.isIgnoring(Message.DEBUG);
+ name = name.replace('/', '.');
+ byte[] wovenBytes = wovenWithGeneratedClass(name);
+ if (wovenBytes != null) {
+ if (debugOn) {
+ debug("returning woven bytes for '" + name + "' that were generated by a previous weaving process");
+ }
+ return wovenBytes;
+ }
+
try {
delegateForCurrentClass = null;
- name = name.replace('/', '.');
if (couldWeave(name, bytes)) {
if (accept(name, bytes)) {
@@ -448,6 +456,21 @@ public class WeavingAdaptor implements IMessageContext {
return !generatedClasses.containsKey(name) && shouldWeaveName(name);
}
+ /**
+ * Return the bytes from a (parallel?) weaving process that generated an inner class, e.g. to support Around closures.
+ * This is done instead of weaving again, as weaving would generate another inner class.
+ * @param name
+ * @return the cached bytes of a previously woven class, or null if not found
+ */
+ private byte[] wovenWithGeneratedClass(String name) {
+ IUnwovenClassFile woven = generatedClasses.get(name);
+ if (woven == null) {
+ return null;
+ }
+
+ return woven.getBytes();
+ }
+
// ATAJ
protected boolean accept(String name, byte[] bytes) {
return true;