mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8256517
: (ref) Reference.clear during reference processing may lose notification
8240696: (ref) Reference.clear may extend the lifetime of the referent Use private native helper to implement Reference.clear. Reviewed-by: pliden, rkennke, mchung
This commit is contained in:
parent
3c230b8ac5
commit
66943fefa7
14 changed files with 295 additions and 31 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -34,6 +34,22 @@ class FinalReference<T> extends Reference<T> {
|
|||
super(referent, q);
|
||||
}
|
||||
|
||||
/* May only be called when the reference is inactive, so no longer weak. */
|
||||
@Override
|
||||
public T get() {
|
||||
// Cannot call super.get() when active, as the GC could
|
||||
// deactivate immediately after the test.
|
||||
return getFromInactiveFinalReference();
|
||||
}
|
||||
|
||||
/* May only be called when the reference is inactive, so no longer weak.
|
||||
* Clearing while active would discard the finalization request.
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
clearInactiveFinalReference();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean enqueue() {
|
||||
throw new InternalError("should never reach here");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -82,7 +82,7 @@ final class Finalizer extends FinalReference<Object> { /* Package-private; must
|
|||
}
|
||||
|
||||
try {
|
||||
Object finalizee = this.getInactive();
|
||||
Object finalizee = this.get();
|
||||
assert finalizee != null;
|
||||
if (!(finalizee instanceof java.lang.Enum)) {
|
||||
jla.invokeFinalize(finalizee);
|
||||
|
|
|
@ -100,10 +100,10 @@ public abstract class Reference<T> {
|
|||
* [active/unregistered] [1]
|
||||
*
|
||||
* Transitions:
|
||||
* clear
|
||||
* clear [2]
|
||||
* [active/registered] -------> [inactive/registered]
|
||||
* | |
|
||||
* | | enqueue [2]
|
||||
* | | enqueue
|
||||
* | GC enqueue [2] |
|
||||
* | -----------------|
|
||||
* | |
|
||||
|
@ -114,7 +114,7 @@ public abstract class Reference<T> {
|
|||
* v | |
|
||||
* [pending/enqueued] --- |
|
||||
* | | poll/remove
|
||||
* | poll/remove |
|
||||
* | poll/remove | + clear [4]
|
||||
* | |
|
||||
* v ReferenceHandler v
|
||||
* [pending/dequeued] ------> [inactive/dequeued]
|
||||
|
@ -140,12 +140,14 @@ public abstract class Reference<T> {
|
|||
* [1] Unregistered is not permitted for FinalReferences.
|
||||
*
|
||||
* [2] These transitions are not possible for FinalReferences, making
|
||||
* [pending/enqueued] and [pending/dequeued] unreachable, and
|
||||
* [inactive/registered] terminal.
|
||||
* [pending/enqueued], [pending/dequeued], and [inactive/registered]
|
||||
* unreachable.
|
||||
*
|
||||
* [3] The garbage collector may directly transition a Reference
|
||||
* from [active/unregistered] to [inactive/unregistered],
|
||||
* bypassing the pending-Reference list.
|
||||
*
|
||||
* [4] The queue handler for FinalReferences also clears the reference.
|
||||
*/
|
||||
|
||||
private T referent; /* Treated specially by GC */
|
||||
|
@ -342,22 +344,6 @@ public abstract class Reference<T> {
|
|||
return this.referent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load referent with strong semantics. Treating the referent
|
||||
* as strong referent is ok when the Reference is inactive,
|
||||
* because then the referent is switched to strong semantics
|
||||
* anyway.
|
||||
*
|
||||
* This is only used from Finalizer to bypass the intrinsic,
|
||||
* which might return a null referent, even though it is not
|
||||
* null, and would subsequently not finalize the referent/finalizee.
|
||||
*/
|
||||
T getInactive() {
|
||||
assert this instanceof FinalReference;
|
||||
assert next == this; // I.e. FinalReference is inactive
|
||||
return this.referent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the referent of this reference object is {@code obj}.
|
||||
* Using a {@code null} {@code obj} returns {@code true} if the
|
||||
|
@ -383,6 +369,41 @@ public abstract class Reference<T> {
|
|||
* clears references it does so directly, without invoking this method.
|
||||
*/
|
||||
public void clear() {
|
||||
clear0();
|
||||
}
|
||||
|
||||
/* Implementation of clear(), also used by enqueue(). A simple
|
||||
* assignment of the referent field won't do for some garbage
|
||||
* collectors.
|
||||
*/
|
||||
private native void clear0();
|
||||
|
||||
/* -- Operations on inactive FinalReferences -- */
|
||||
|
||||
/* These functions are only used by FinalReference, and must only be
|
||||
* called after the reference becomes inactive. While active, a
|
||||
* FinalReference is considered weak but the referent is not normally
|
||||
* accessed. Once a FinalReference becomes inactive it is considered a
|
||||
* strong reference. These functions are used to bypass the
|
||||
* corresponding weak implementations, directly accessing the referent
|
||||
* field with strong semantics.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Load referent with strong semantics.
|
||||
*/
|
||||
T getFromInactiveFinalReference() {
|
||||
assert this instanceof FinalReference;
|
||||
assert next != null; // I.e. FinalReference is inactive
|
||||
return this.referent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear referent with strong semantics.
|
||||
*/
|
||||
void clearInactiveFinalReference() {
|
||||
assert this instanceof FinalReference;
|
||||
assert next != null; // I.e. FinalReference is inactive
|
||||
this.referent = null;
|
||||
}
|
||||
|
||||
|
@ -413,7 +434,7 @@ public abstract class Reference<T> {
|
|||
* it was not registered with a queue when it was created
|
||||
*/
|
||||
public boolean enqueue() {
|
||||
this.referent = null;
|
||||
clear0(); // Intentionally clear0() rather than clear()
|
||||
return this.queue.enqueue(this);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue