Skip to content

Commit

Permalink
Use previous weaving result if classes were generated during weaving
Browse files Browse the repository at this point in the history
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 eclipse-aspectj#279.
  • Loading branch information
urisimchoni authored and kriegaex committed Feb 8, 2024
1 parent cf2e7c4 commit da31a21
Showing 1 changed file with 24 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -358,9 +358,17 @@ public byte[] weaveClass(String name, final byte[] bytes, boolean mustWeave) thr

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)) {

Expand Down Expand Up @@ -448,6 +456,21 @@ private boolean couldWeave(String name, byte[] bytes) {
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;
Expand Down

0 comments on commit da31a21

Please sign in to comment.