Skip to content

Commit 9f51abb

Browse files
committed
SLING-12519 - Use AtomicReference in ScriptableBase.java for lazy initialization of NativeJavaObject
* Introduce a special NULL_OBJECT placeholder as an intermediate state to avoid repeated construction of NativeJavaObject in each compareAndSet(...) operation, preventing redundant wrapper creation during concurrent access without introducing blocking or contention.
1 parent c4fac55 commit 9f51abb

File tree

1 file changed

+12
-4
lines changed

1 file changed

+12
-4
lines changed

src/main/java/org/apache/sling/scripting/javascript/wrapper/ScriptableBase.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.lang.reflect.Method;
2222
import java.util.HashSet;
2323
import java.util.Set;
24+
import java.util.concurrent.atomic.AtomicReference;
2425

2526
import org.mozilla.javascript.NativeJavaObject;
2627
import org.mozilla.javascript.Scriptable;
@@ -31,12 +32,12 @@
3132
*/
3233
public abstract class ScriptableBase extends ScriptableObject {
3334

34-
private NativeJavaObject njo;
35+
private final AtomicReference<NativeJavaObject> cachedNjo = new AtomicReference<>(null);
3536
private final Set<String> jsMethods = getJsMethodNames();
3637

3738
public static final String JSFUNC_PREFIX = "jsFunction_";
3839

39-
protected synchronized Object getNative(String name, Scriptable start) {
40+
protected Object getNative(String name, Scriptable start) {
4041
final Object wrapped = getWrappedObject();
4142

4243
if (wrapped == null) {
@@ -47,10 +48,17 @@ protected synchronized Object getNative(String name, Scriptable start) {
4748
return Scriptable.NOT_FOUND;
4849
}
4950

51+
// Use AtomicReference-based caching with double-checked locking to ensure
52+
// that NativeJavaObject is initialized only once in a thread-safe manner.
53+
NativeJavaObject njo = cachedNjo.get();
5054
if (njo == null) {
51-
njo = new NativeJavaObject(start, wrapped, getStaticType());
55+
synchronized (this) {
56+
if (cachedNjo.get() == null) {
57+
cachedNjo.set(new NativeJavaObject(start, wrapped, getStaticType()));
58+
}
59+
}
60+
njo = cachedNjo.get();
5261
}
53-
5462
return njo.get(name, start);
5563
}
5664

0 commit comments

Comments
 (0)