Skip to content

Commit 0ad38b8

Browse files
micapolos-googlekluever
authored andcommitted
Fix memory leak in SingletonImmutableBiMap which would appear in transpiled J2ObjC code.
The @RetainedWith annotation can not be used on both sides of the retain-cycle. The RegularImmutableBiMap does not have this problem, because it uses Inverse inner class. This CL applies similar trick in SingletonImmutableBiMap, although without additional inner class. RELNOTES=Update SingletonImmutableBiMap to avoid retain-cycle in transpiled Obj-C code. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=317856944
1 parent 6cc0bb9 commit 0ad38b8

File tree

2 files changed

+14
-8
lines changed

2 files changed

+14
-8
lines changed

cycle_whitelist.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ NAMESPACE junit.framework
1313
NAMESPACE org.junit
1414

1515
# ***** REAL CYCLES *****
16-
# Inverses (currently not solvable by weakening a reference)
17-
FIELD com.google.common.base.Converter.reverse
1816
# Cycle exists until future completes
1917
FIELD com.google.common.util.concurrent.AbstractFuture.Listener.executor com.google.common.util.concurrent.ExecutionSequencer.TaskNonReentrantExecutor
2018

@@ -23,6 +21,7 @@ FIELD com.google.common.util.concurrent.AbstractFuture.Listener.executor com.goo
2321
# The Runnable type is so generic that it produces too many false positives.
2422
TYPE java.lang.Runnable
2523

24+
FIELD com.google.common.base.Converter.reverse
2625
FIELD com.google.common.collect.AbstractBiMap.EntrySet.iterator.$.entry com.google.common.collect.AbstractBiMap.EntrySet.iterator.$.next.$
2726
FIELD com.google.common.collect.AbstractMapBasedMultimap.map
2827
FIELD com.google.common.collect.AbstractMultimap.asMap com.google.common.collect.AbstractMapBasedMultimap.NavigableAsMap
@@ -36,6 +35,7 @@ FIELD com.google.common.collect.ImmutableRangeSet.ranges
3635
FIELD com.google.common.collect.ImmutableSet.asList
3736
FIELD com.google.common.collect.Maps.FilteredMapValues.unfiltered
3837
FIELD com.google.common.collect.Sets.SubSet.inputSet
38+
FIELD com.google.common.collect.SingletonImmutableBiMap.inverse
3939
FIELD com.google.common.collect.TreeTraverser.PostOrderNode.childIterator
4040
FIELD com.google.common.collect.TreeTraverser.PreOrderIterator.stack
4141
FIELD com.google.common.util.concurrent.AbstractFuture.Listener.executor com.google.common.util.concurrent.MoreExecutors.rejectionPropagatingExecutor.$

guava/src/com/google/common/collect/SingletonImmutableBiMap.java

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ final class SingletonImmutableBiMap<K, V> extends ImmutableBiMap<K, V> {
4242
checkEntryNotNull(singleKey, singleValue);
4343
this.singleKey = singleKey;
4444
this.singleValue = singleValue;
45+
this.inverse = null;
4546
}
4647

4748
private SingletonImmutableBiMap(K singleKey, V singleValue, ImmutableBiMap<V, K> inverse) {
@@ -90,16 +91,21 @@ ImmutableSet<K> createKeySet() {
9091
return ImmutableSet.of(singleKey);
9192
}
9293

93-
@LazyInit @RetainedWith transient ImmutableBiMap<V, K> inverse;
94+
private final transient @Nullable ImmutableBiMap<V, K> inverse;
95+
@LazyInit @RetainedWith private transient @Nullable ImmutableBiMap<V, K> lazyInverse;
9496

9597
@Override
9698
public ImmutableBiMap<V, K> inverse() {
97-
// racy single-check idiom
98-
ImmutableBiMap<V, K> result = inverse;
99-
if (result == null) {
100-
return inverse = new SingletonImmutableBiMap<>(singleValue, singleKey, this);
99+
if (inverse != null) {
100+
return inverse;
101101
} else {
102-
return result;
102+
// racy single-check idiom
103+
ImmutableBiMap<V, K> result = lazyInverse;
104+
if (result == null) {
105+
return lazyInverse = new SingletonImmutableBiMap<>(singleValue, singleKey, this);
106+
} else {
107+
return result;
108+
}
103109
}
104110
}
105111
}

0 commit comments

Comments
 (0)