diff --git a/infer/src/checkers/ThreadSafety.ml b/infer/src/checkers/ThreadSafety.ml index b9eb69377..48350eea6 100644 --- a/infer/src/checkers/ThreadSafety.ml +++ b/infer/src/checkers/ThreadSafety.ml @@ -330,7 +330,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct | ("android.app.Activity" | "android.view.View"), "findViewById" -> (* assume findViewById creates fresh View's (note: not always true) *) true - | "android.support.v4.util.Pools$SimplePool", "acquire" -> + | "android.support.v4.util.Pools$Pool", "acquire" -> (* a pool should own all of its objects *) true | _ -> diff --git a/infer/tests/codetoanalyze/java/threadsafety/Containers.java b/infer/tests/codetoanalyze/java/threadsafety/Containers.java index 3222ce37c..6d352a72f 100644 --- a/infer/tests/codetoanalyze/java/threadsafety/Containers.java +++ b/infer/tests/codetoanalyze/java/threadsafety/Containers.java @@ -24,6 +24,7 @@ import android.support.v4.util.Pools.SynchronizedPool; import android.support.v4.util.SparseArrayCompat; import android.util.SparseArray; import android.support.v4.util.SimpleArrayMap; +import android.support.v4.util.Pools; import android.support.v4.util.Pools.SimplePool; class ContainerWrapper { @@ -175,7 +176,7 @@ class Containers { static boolean sUsePooling; - private Obj poolWrapper() { + private Obj poolWrapper1() { Obj obj = sUsePooling ? sPool.acquire() : null; if (obj == null) { obj = new Obj(); @@ -184,8 +185,28 @@ class Containers { return obj; } - void poolWrapperOk() { - Obj obj = poolWrapper(); + void poolWrapperOk1() { + Obj obj = poolWrapper1(); + obj.f = new Object(); + } + + private Pools.Pool mPool; + private boolean mIsSync; + + private Obj poolWrapper2() { + Obj item; + if (mIsSync) { + synchronized (this) { + item = mPool.acquire(); + } + } else { + item = mPool.acquire(); + } + return item; + } + + void poolWrapperOk2() { + Obj obj = poolWrapper2(); obj.f = new Object(); } @@ -265,4 +286,5 @@ class Containers { } simplePool.release(a); } + }