From 4d7c71ea79520b3555917cd157cee6315ebc5205 Mon Sep 17 00:00:00 2001 From: Google Java Core Libraries Date: Tue, 8 Oct 2024 09:25:48 -0700 Subject: [PATCH] Add `@RetainedLocalRef` to `volatile` `value` field references to resolve potential memory issues in a J2ObjC context. RELNOTES=n/a PiperOrigin-RevId: 683652108 --- .../util/concurrent/AbstractFuture.java | 23 ++++++++++--------- .../util/concurrent/AbstractFuture.java | 23 ++++++++++--------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/android/guava/src/com/google/common/util/concurrent/AbstractFuture.java b/android/guava/src/com/google/common/util/concurrent/AbstractFuture.java index 93e69514140b..6ddb7386bdac 100644 --- a/android/guava/src/com/google/common/util/concurrent/AbstractFuture.java +++ b/android/guava/src/com/google/common/util/concurrent/AbstractFuture.java @@ -28,6 +28,7 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.ForOverride; import com.google.j2objc.annotations.ReflectionSupport; +import com.google.j2objc.annotations.RetainedLocalRef; import java.lang.reflect.Field; import java.security.AccessController; import java.security.PrivilegedActionException; @@ -442,7 +443,7 @@ public V get(long timeout, TimeUnit unit) if (Thread.interrupted()) { throw new InterruptedException(); } - Object localValue = value; + @RetainedLocalRef Object localValue = value; if (localValue != null & !(localValue instanceof SetFuture)) { return getDoneValue(localValue); } @@ -550,7 +551,7 @@ public V get() throws InterruptedException, ExecutionException { if (Thread.interrupted()) { throw new InterruptedException(); } - Object localValue = value; + @RetainedLocalRef Object localValue = value; if (localValue != null & !(localValue instanceof SetFuture)) { return getDoneValue(localValue); } @@ -609,13 +610,13 @@ private V getDoneValue(Object obj) throws ExecutionException { @Override public boolean isDone() { - final Object localValue = value; + @RetainedLocalRef Object localValue = value; return localValue != null & !(localValue instanceof SetFuture); } @Override public boolean isCancelled() { - final Object localValue = value; + @RetainedLocalRef Object localValue = value; return localValue instanceof Cancellation; } @@ -638,7 +639,7 @@ public boolean isCancelled() { @CanIgnoreReturnValue @Override public boolean cancel(boolean mayInterruptIfRunning) { - Object localValue = value; + @RetainedLocalRef Object localValue = value; boolean rValue = false; if (localValue == null | localValue instanceof SetFuture) { // Try to delay allocating the exception. At this point we may still lose the CAS, but it is @@ -724,7 +725,7 @@ protected void interruptTask() {} * @since 14.0 */ protected final boolean wasInterrupted() { - final Object localValue = value; + @RetainedLocalRef Object localValue = value; return (localValue instanceof Cancellation) && ((Cancellation) localValue).wasInterrupted; } @@ -846,7 +847,7 @@ protected boolean setException(Throwable throwable) { @CanIgnoreReturnValue protected boolean setFuture(ListenableFuture future) { checkNotNull(future); - Object localValue = value; + @RetainedLocalRef Object localValue = value; if (localValue == null) { if (future.isDone()) { Object value = getFutureValue(future); @@ -1109,9 +1110,9 @@ protected void afterDone() {} @CheckForNull protected final Throwable tryInternalFastPathGetFailure() { if (this instanceof Trusted) { - Object obj = value; - if (obj instanceof Failure) { - return ((Failure) obj).exception; + @RetainedLocalRef Object localValue = value; + if (localValue instanceof Failure) { + return ((Failure) localValue).exception; } } return null; @@ -1204,7 +1205,7 @@ private void addPendingString(StringBuilder builder) { builder.append("PENDING"); - Object localValue = value; + @RetainedLocalRef Object localValue = value; if (localValue instanceof SetFuture) { builder.append(", setFuture=["); appendUserObject(builder, ((SetFuture) localValue).future); diff --git a/guava/src/com/google/common/util/concurrent/AbstractFuture.java b/guava/src/com/google/common/util/concurrent/AbstractFuture.java index f9eceed6afde..94e26b19bb56 100644 --- a/guava/src/com/google/common/util/concurrent/AbstractFuture.java +++ b/guava/src/com/google/common/util/concurrent/AbstractFuture.java @@ -28,6 +28,7 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.ForOverride; import com.google.j2objc.annotations.ReflectionSupport; +import com.google.j2objc.annotations.RetainedLocalRef; import java.lang.reflect.Field; import java.security.AccessController; import java.security.PrivilegedActionException; @@ -442,7 +443,7 @@ public V get(long timeout, TimeUnit unit) if (Thread.interrupted()) { throw new InterruptedException(); } - Object localValue = value; + @RetainedLocalRef Object localValue = value; if (localValue != null & !(localValue instanceof SetFuture)) { return getDoneValue(localValue); } @@ -550,7 +551,7 @@ public V get() throws InterruptedException, ExecutionException { if (Thread.interrupted()) { throw new InterruptedException(); } - Object localValue = value; + @RetainedLocalRef Object localValue = value; if (localValue != null & !(localValue instanceof SetFuture)) { return getDoneValue(localValue); } @@ -609,13 +610,13 @@ private V getDoneValue(Object obj) throws ExecutionException { @Override public boolean isDone() { - final Object localValue = value; + @RetainedLocalRef Object localValue = value; return localValue != null & !(localValue instanceof SetFuture); } @Override public boolean isCancelled() { - final Object localValue = value; + @RetainedLocalRef Object localValue = value; return localValue instanceof Cancellation; } @@ -638,7 +639,7 @@ public boolean isCancelled() { @CanIgnoreReturnValue @Override public boolean cancel(boolean mayInterruptIfRunning) { - Object localValue = value; + @RetainedLocalRef Object localValue = value; boolean rValue = false; if (localValue == null | localValue instanceof SetFuture) { // Try to delay allocating the exception. At this point we may still lose the CAS, but it is @@ -724,7 +725,7 @@ protected void interruptTask() {} * @since 14.0 */ protected final boolean wasInterrupted() { - final Object localValue = value; + @RetainedLocalRef Object localValue = value; return (localValue instanceof Cancellation) && ((Cancellation) localValue).wasInterrupted; } @@ -846,7 +847,7 @@ protected boolean setException(Throwable throwable) { @CanIgnoreReturnValue protected boolean setFuture(ListenableFuture future) { checkNotNull(future); - Object localValue = value; + @RetainedLocalRef Object localValue = value; if (localValue == null) { if (future.isDone()) { Object value = getFutureValue(future); @@ -1109,9 +1110,9 @@ protected void afterDone() {} @CheckForNull protected final Throwable tryInternalFastPathGetFailure() { if (this instanceof Trusted) { - Object obj = value; - if (obj instanceof Failure) { - return ((Failure) obj).exception; + @RetainedLocalRef Object localValue = value; + if (localValue instanceof Failure) { + return ((Failure) localValue).exception; } } return null; @@ -1204,7 +1205,7 @@ private void addPendingString(StringBuilder builder) { builder.append("PENDING"); - Object localValue = value; + @RetainedLocalRef Object localValue = value; if (localValue instanceof SetFuture) { builder.append(", setFuture=["); appendUserObject(builder, ((SetFuture) localValue).future);