Skip to content

Commit d5dc284

Browse files
change to ensure strong reference is held throughout register() method
1 parent f0da2f8 commit d5dc284

File tree

1 file changed

+14
-5
lines changed

1 file changed

+14
-5
lines changed

src/com/sun/jna/internal/Cleaner.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,27 @@ private Cleaner() {
5858
cleanerRunning = new AtomicBoolean(false);
5959
}
6060

61-
public Cleanable register(Object obj, Runnable cleanupTask) {
61+
public Cleanable register(Object referent, Runnable cleanupTask) {
6262
// The important side effect is the PhantomReference, that is yielded
6363
// after the referent is GCed
64-
Cleanable cleanable = add(new CleanerRef(obj, referenceQueue, cleanupTask));
64+
Cleanable cleanable = add(new CleanerRef(referent, referenceQueue, cleanupTask));
6565

6666
if (cleanerRunning.compareAndSet(false, true)) {
6767
Logger.getLogger(Cleaner.class.getName()).log(Level.FINE, "Starting CleanerThread");
6868
Thread cleanerThread = new CleanerThread();
6969
cleanerThread.start();
7070
}
7171

72+
// NOTE: This is a "pointless" check in the conventional sense, however it serves to guarantee that the
73+
// referent is not garbage collected before the CleanerRef is fully constructed which can happen due
74+
// to reordering of instructions by the compiler or the CPU. In Java 9+ Reference.reachabilityFence() was
75+
// introduced to provide this guarantee, but we want to stay compatible with Java 8, so this is the common
76+
// idiom to achieve the same effect, by ensuring that the referent is still strongly reachable at
77+
// this point.
78+
if (referent == null) {
79+
throw new IllegalArgumentException("The referent object must not be null");
80+
}
81+
7282
return cleanable;
7383
}
7484

@@ -83,13 +93,12 @@ private void remove(final CleanerRef node) {
8393
}
8494

8595
private static class CleanerRef extends PhantomReference<Object> implements Cleanable {
86-
private final Runnable cleanupTask;
87-
private final AtomicBoolean cleaned;
96+
private volatile Runnable cleanupTask;
97+
private AtomicBoolean cleaned = new AtomicBoolean(false);
8898

8999
CleanerRef(Object referent, ReferenceQueue<? super Object> q, Runnable cleanupTask) {
90100
super(referent, q);
91101
this.cleanupTask = cleanupTask;
92-
this.cleaned = new AtomicBoolean(false);
93102
}
94103

95104
@Override

0 commit comments

Comments
 (0)