From ab0d17d29fe65310a237bab72aa47606cab40cd4 Mon Sep 17 00:00:00 2001 From: Alexander Kriegisch Date: Mon, 28 Feb 2022 07:07:08 +0700 Subject: [PATCH] Make Stack in JoinPointImpl InheritableThreadLocal In case of asynchronous proceeding for nested around-advice, child threads need copies of the original around-closure stack. Otherwise, the target method thread will have popped the stack empty after unwinding. Fixes #128. Signed-off-by: Alexander Kriegisch --- .../runtime/reflect/JoinPointImpl.java | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/runtime/src/main/java/org/aspectj/runtime/reflect/JoinPointImpl.java b/runtime/src/main/java/org/aspectj/runtime/reflect/JoinPointImpl.java index bb09e68697..851a8b3dca 100644 --- a/runtime/src/main/java/org/aspectj/runtime/reflect/JoinPointImpl.java +++ b/runtime/src/main/java/org/aspectj/runtime/reflect/JoinPointImpl.java @@ -79,6 +79,18 @@ public EnclosingStaticPartImpl(int count, String kind, Signature signature, Sour } } + static class InheritableThreadLocalAroundClosureStack extends InheritableThreadLocal> { + @Override + protected Stack initialValue() { + return new Stack<>(); + } + + @Override + protected Stack childValue(Stack parentValue) { + return (Stack) parentValue.clone(); + } + } + Object _this; Object target; Object[] args; @@ -140,7 +152,7 @@ public final String toLongString() { // will either be using arc or arcs but not both. arcs being non-null // indicates it is in use (even if an empty stack) private AroundClosure arc = null; - private Stack arcs = null; + private InheritableThreadLocalAroundClosureStack arcs = null; public void set$AroundClosure(AroundClosure arc) { this.arc = arc; @@ -149,12 +161,12 @@ public final String toLongString() { public void stack$AroundClosure(AroundClosure arc) { // If input parameter arc is null this is the 'unlink' call from AroundClosure if (arcs == null) { - arcs = new Stack<>(); + arcs = new InheritableThreadLocalAroundClosureStack(); } if (arc==null) { - this.arcs.pop(); + this.arcs.get().pop(); } else { - this.arcs.push(arc); + this.arcs.get().push(arc); } } @@ -167,7 +179,8 @@ public Object proceed() throws Throwable { return arc.run(arc.getState()); } } else { - return arcs.peek().run(arcs.peek().getState()); + final AroundClosure ac = arcs.get().peek(); + return ac.run(ac.getState()); } } @@ -177,7 +190,7 @@ public Object proceed(Object[] adviceBindings) throws Throwable { if (arcs == null) { ac = arc; } else { - ac = arcs.peek(); + ac = arcs.get().peek(); } if (ac == null) {