From c3ef09ae53376eb530c91ca2a95c3c4f8fa25bf5 Mon Sep 17 00:00:00 2001 From: Timotej Kapus Date: Mon, 9 Dec 2024 01:06:08 -0800 Subject: [PATCH] [infer][starvation] Report locks on UI thread Reviewed By: ngorogiannis Differential Revision: D66294273 fbshipit-source-id: f03f7a319690da4374e109165ef27853d83f4f52 --- .../documentation/issues/LOCK_ON_UI_THREAD.md | 13 ++++ infer/man/man1/infer-full.txt | 1 + infer/man/man1/infer-report.txt | 1 + infer/man/man1/infer.txt | 1 + infer/src/base/IssueType.ml | 5 ++ infer/src/base/IssueType.mli | 2 + infer/src/concurrency/starvation.ml | 70 ++++++++++++------- infer/src/concurrency/starvationDomain.mli | 2 + .../java/starvation-whole-program/issues.exp | 23 ++++++ .../codetoanalyze/java/starvation/UiLock.java | 15 ++++ .../codetoanalyze/java/starvation/issues.exp | 26 +++++++ 11 files changed, 132 insertions(+), 27 deletions(-) create mode 100644 infer/documentation/issues/LOCK_ON_UI_THREAD.md create mode 100644 infer/tests/codetoanalyze/java/starvation/UiLock.java diff --git a/infer/documentation/issues/LOCK_ON_UI_THREAD.md b/infer/documentation/issues/LOCK_ON_UI_THREAD.md new file mode 100644 index 00000000000..59d291e44db --- /dev/null +++ b/infer/documentation/issues/LOCK_ON_UI_THREAD.md @@ -0,0 +1,13 @@ +A method annoted as being on UIThread acquires a lock. This could be a potential performance issue + +Example: + +```java +class Example { + @UiThread + void foo() { + synchronized(this) { + } + } +} +``` diff --git a/infer/man/man1/infer-full.txt b/infer/man/man1/infer-full.txt index a95f92eb41f..90d7df0d904 100644 --- a/infer/man/man1/infer-full.txt +++ b/infer/man/man1/infer-full.txt @@ -667,6 +667,7 @@ OPTIONS LINEAGE_FLOW (enabled by default), LOCKLESS_VIOLATION (enabled by default), LOCK_CONSISTENCY_VIOLATION (enabled by default), + LOCK_ON_UI_THREAD (disabled by default), Leak_after_array_abstraction (enabled by default), Leak_in_footprint (enabled by default), Leak_unknown_origin (disabled by default), diff --git a/infer/man/man1/infer-report.txt b/infer/man/man1/infer-report.txt index 16762128792..1620830a58c 100644 --- a/infer/man/man1/infer-report.txt +++ b/infer/man/man1/infer-report.txt @@ -182,6 +182,7 @@ OPTIONS LINEAGE_FLOW (enabled by default), LOCKLESS_VIOLATION (enabled by default), LOCK_CONSISTENCY_VIOLATION (enabled by default), + LOCK_ON_UI_THREAD (disabled by default), Leak_after_array_abstraction (enabled by default), Leak_in_footprint (enabled by default), Leak_unknown_origin (disabled by default), diff --git a/infer/man/man1/infer.txt b/infer/man/man1/infer.txt index 8088935e340..6a5fbb14d69 100644 --- a/infer/man/man1/infer.txt +++ b/infer/man/man1/infer.txt @@ -667,6 +667,7 @@ OPTIONS LINEAGE_FLOW (enabled by default), LOCKLESS_VIOLATION (enabled by default), LOCK_CONSISTENCY_VIOLATION (enabled by default), + LOCK_ON_UI_THREAD (disabled by default), Leak_after_array_abstraction (enabled by default), Leak_in_footprint (enabled by default), Leak_unknown_origin (disabled by default), diff --git a/infer/src/base/IssueType.ml b/infer/src/base/IssueType.ml index 8a6e99d5567..79ae94a2e3c 100644 --- a/infer/src/base/IssueType.ml +++ b/infer/src/base/IssueType.ml @@ -719,6 +719,11 @@ let lock_consistency_violation = ~user_documentation:[%blob "./documentation/issues/LOCK_CONSISTENCY_VIOLATION.md"] +let lock_on_ui_thread = + register ~hum:"Lock on UI Thread" ~id:"LOCK_ON_UI_THREAD" ~category:PerfRegression ~enabled:false + Warning Starvation ~user_documentation:[%blob "./documentation/issues/LOCK_ON_UI_THREAD.md"] + + let lockless_violation = register ~category:NoCategory ~id:"LOCKLESS_VIOLATION" Error Starvation ~user_documentation:[%blob "./documentation/issues/LOCKLESS_VIOLATION.md"] diff --git a/infer/src/base/IssueType.mli b/infer/src/base/IssueType.mli index 58fe83e5795..4c20d0834c9 100644 --- a/infer/src/base/IssueType.mli +++ b/infer/src/base/IssueType.mli @@ -247,6 +247,8 @@ val lockless_violation : t val lock_consistency_violation : t +val lock_on_ui_thread : t + val expensive_loop_invariant_call : t val memory_leak : t diff --git a/infer/src/concurrency/starvation.ml b/infer/src/concurrency/starvation.ml index 3a10d39e64c..c02791df3e6 100644 --- a/infer/src/concurrency/starvation.ml +++ b/infer/src/concurrency/starvation.ml @@ -564,6 +564,8 @@ module ReportMap : sig val add_starvation : report_add_t + val add_lock_on_ui_thread : report_add_t + val add_strict_mode_violation : report_add_t val issue_log_of : t -> IssueLog.t @@ -623,6 +625,10 @@ end = struct add tenv pattrs loc ltr message IssueType.lockless_violation map + let add_lock_on_ui_thread tenv pattrs loc ltr message map = + add tenv pattrs loc ltr message IssueType.lock_on_ui_thread map + + let add_arbitrary_code_execution_under_lock tenv pattrs loc ltr message map = add tenv pattrs loc ltr message IssueType.arbitrary_code_execution_under_lock map @@ -632,6 +638,7 @@ end = struct [ deadlock ; lockless_violation ; ipc_on_ui_thread + ; lock_on_ui_thread ; regex_op_on_ui_thread ; starvation ; strict_mode_violation @@ -908,33 +915,42 @@ let report_on_pair ~analyze_ondemand tenv pattrs (pair : Domain.CriticalPair.t) let loc = CriticalPair.get_earliest_lock_or_call_loc ~procname:pname pair in let ltr = CriticalPair.make_trace pname pair in ReportMap.add_lockless_violation tenv pattrs loc ltr error_message report_map - | LockAcquire {locks} when is_not_private -> ( - match - List.find locks ~f:(fun lock -> Acquisitions.lock_is_held lock pair.elem.acquisitions) - with - | Some lock -> - let error_message = - Format.asprintf "Potential self deadlock. %a%a twice." pname_pp pname Lock.pp_locks lock - in - let loc = CriticalPair.get_earliest_lock_or_call_loc ~procname:pname pair in - let ltr = CriticalPair.make_trace ~header:"In method " pname pair in - ReportMap.add_deadlock tenv pattrs loc ltr error_message report_map - | None when Config.starvation_whole_program -> - report_map - | None -> - List.fold locks ~init:report_map ~f:(fun acc lock -> - Lock.root_class lock - |> Option.value_map ~default:acc ~f:(fun other_class -> - (* get the class of the root variable of the lock in the lock acquisition - and retrieve all the summaries of the methods of that class; - then, report on the parallel composition of the current pair and any pair in these - summaries that can indeed run in parallel *) - fold_reportable_summaries analyze_ondemand tenv other_class ~init:acc - ~f:(fun acc (other_pname, summary) -> - Domain.fold_critical_pairs_of_summary - (report_on_parallel_composition ~should_report_starvation tenv pattrs pair - lock other_pname ) - summary acc ) ) ) ) + | LockAcquire {locks; thread} when is_not_private -> ( + let report_map = + if ThreadDomain.is_uithread thread && should_report_starvation then + let error_message = + Format.asprintf "%a acquired in UI Thread!" (Format.pp_print_list Lock.pp_locks) locks + in + let ltr, loc = make_trace_and_loc () in + ReportMap.add_lock_on_ui_thread tenv pattrs loc ltr error_message report_map + else report_map + in + match + List.find locks ~f:(fun lock -> Acquisitions.lock_is_held lock pair.elem.acquisitions) + with + | Some lock -> + let error_message = + Format.asprintf "Potential self deadlock. %a%a twice." pname_pp pname Lock.pp_locks lock + in + let loc = CriticalPair.get_earliest_lock_or_call_loc ~procname:pname pair in + let ltr = CriticalPair.make_trace ~header:"In method " pname pair in + ReportMap.add_deadlock tenv pattrs loc ltr error_message report_map + | None when Config.starvation_whole_program -> + report_map + | None -> + List.fold locks ~init:report_map ~f:(fun acc lock -> + Lock.root_class lock + |> Option.value_map ~default:acc ~f:(fun other_class -> + (* get the class of the root variable of the lock in the lock acquisition + and retrieve all the summaries of the methods of that class; + then, report on the parallel composition of the current pair and any pair in these + summaries that can indeed run in parallel *) + fold_reportable_summaries analyze_ondemand tenv other_class ~init:acc + ~f:(fun acc (other_pname, summary) -> + Domain.fold_critical_pairs_of_summary + (report_on_parallel_composition ~should_report_starvation tenv pattrs + pair lock other_pname ) + summary acc ) ) ) ) | _ -> report_map diff --git a/infer/src/concurrency/starvationDomain.mli b/infer/src/concurrency/starvationDomain.mli index 5723c6f43e1..7c9ba24696b 100644 --- a/infer/src/concurrency/starvationDomain.mli +++ b/infer/src/concurrency/starvationDomain.mli @@ -20,6 +20,8 @@ module F = Format module ThreadDomain : sig type t = UnknownThread | UIThread | BGThread | AnyThread | NamedThread of string + val is_uithread : t -> bool + include AbstractDomain.WithBottom with type t := t end diff --git a/infer/tests/codetoanalyze/java/starvation-whole-program/issues.exp b/infer/tests/codetoanalyze/java/starvation-whole-program/issues.exp index 6fd19bbe21a..e7c00f621c2 100644 --- a/infer/tests/codetoanalyze/java/starvation-whole-program/issues.exp +++ b/infer/tests/codetoanalyze/java/starvation-whole-program/issues.exp @@ -3,20 +3,30 @@ codetoanalyze/java/starvation-whole-program/AttributeFlows.java, AttributeFlows. codetoanalyze/java/starvation-whole-program/AttributeFlows.java, AttributeFlows.postRunnableFieldToUIThreadBad():void, 127, IPC_ON_UI_THREAD, no_bucket, WARNING, [`void AttributeFlows.postRunnableFieldToUIThreadBad()`,Method call: `void AttributeFlows$6.run()`,Method call: `void AttributeFlows.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] codetoanalyze/java/starvation-whole-program/ConstructedAttributes.java, ConstructedAttributes.postBlockingCallToUIExecutorBad():void, 52, IPC_ON_UI_THREAD, no_bucket, WARNING, [`void ConstructedAttributes.postBlockingCallToUIExecutorBad()`,Method call: `void ConstructedAttributes$1.run()`,Method call: `void ConstructedAttributes.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] codetoanalyze/java/starvation-whole-program/ConstructedAttributes.java, ConstructedAttributes.postBlockingCallToUIHandlerBad():void, 64, IPC_ON_UI_THREAD, no_bucket, WARNING, [`void ConstructedAttributes.postBlockingCallToUIHandlerBad()`,Method call: `void ConstructedAttributes$1.run()`,Method call: `void ConstructedAttributes.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] +codetoanalyze/java/starvation-whole-program/Deadlock.java, Deadlock.postDeadlockBad():void, 19, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void Deadlock.postDeadlockBad()`,Method call: `void Deadlock$1.run()`, locks `this.this$0.monitorA` in `class Deadlock$1`] +codetoanalyze/java/starvation-whole-program/Deadlock.java, Deadlock.postDeadlockBad():void, 19, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void Deadlock.postDeadlockBad()`,Method call: `void Deadlock$1.run()`, locks `this.this$0.monitorB` in `class Deadlock$1`] codetoanalyze/java/starvation-whole-program/Deadlock.java, Deadlock.postDeadlockBad():void, 19, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void Deadlock.postDeadlockBad()`,Method call: `void Deadlock$1.run()`, locks `this.this$0.monitorA` in `class Deadlock$1`, locks `this.this$0.monitorB` in `class Deadlock$1`,[Trace 2] `void Deadlock.postDeadlockBad()`,Method call: `void Deadlock$2.run()`, locks `this.this$0.monitorB` in `class Deadlock$2`, locks `this.this$0.monitorA` in `class Deadlock$2`] codetoanalyze/java/starvation-whole-program/Deadlock.java, Deadlock.postDeadlockBad():void, 30, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void Deadlock.postDeadlockBad()`,Method call: `void Deadlock$2.run()`, locks `this.this$0.monitorB` in `class Deadlock$2`, locks `this.this$0.monitorA` in `class Deadlock$2`,[Trace 2] `void Deadlock.postDeadlockBad()`,Method call: `void Deadlock$1.run()`, locks `this.this$0.monitorA` in `class Deadlock$1`, locks `this.this$0.monitorB` in `class Deadlock$1`] +codetoanalyze/java/starvation-whole-program/Deadlock.java, Deadlock.postOnUIThreadOk():void, 46, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void Deadlock.postOnUIThreadOk()`,Method call: `void Deadlock$3.run()`, locks `this.this$0.monitorC` in `class Deadlock$3`] +codetoanalyze/java/starvation-whole-program/Deadlock.java, Deadlock.postOnUIThreadOk():void, 46, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void Deadlock.postOnUIThreadOk()`,Method call: `void Deadlock$3.run()`, locks `this.this$0.monitorD` in `class Deadlock$3`] +codetoanalyze/java/starvation-whole-program/Deadlock.java, Deadlock.postOnUIThreadOk():void, 57, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void Deadlock.postOnUIThreadOk()`,Method call: `void Deadlock$4.run()`, locks `this.this$0.monitorC` in `class Deadlock$4`] +codetoanalyze/java/starvation-whole-program/Deadlock.java, Deadlock.postOnUIThreadOk():void, 57, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void Deadlock.postOnUIThreadOk()`,Method call: `void Deadlock$4.run()`, locks `this.this$0.monitorD` in `class Deadlock$4`] codetoanalyze/java/starvation-whole-program/Deadlock.java, Deadlock.postOnBGThreadBad():void, 73, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void Deadlock.postOnBGThreadBad()`,Method call: `void Deadlock$5.run()`, locks `this.this$0.monitorE` in `class Deadlock$5`, locks `this.this$0.monitorF` in `class Deadlock$5`,[Trace 2] `void Deadlock.postOnBGThreadBad()`,Method call: `void Deadlock$6.run()`, locks `this.this$0.monitorF` in `class Deadlock$6`, locks `this.this$0.monitorE` in `class Deadlock$6`] codetoanalyze/java/starvation-whole-program/Deadlock.java, Deadlock.postOnBGThreadBad():void, 84, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void Deadlock.postOnBGThreadBad()`,Method call: `void Deadlock$6.run()`, locks `this.this$0.monitorF` in `class Deadlock$6`, locks `this.this$0.monitorE` in `class Deadlock$6`,[Trace 2] `void Deadlock.postOnBGThreadBad()`,Method call: `void Deadlock$5.run()`, locks `this.this$0.monitorE` in `class Deadlock$5`, locks `this.this$0.monitorF` in `class Deadlock$5`] codetoanalyze/java/starvation-whole-program/DirectStarvation.java, DirectStarvation.postBlockingCallToUIThreadBad():void, 29, IPC_ON_UI_THREAD, no_bucket, WARNING, [`void DirectStarvation.postBlockingCallToUIThreadBad()`,Method call: `void DirectStarvation$1.run()`,Method call: `void DirectStarvation.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] codetoanalyze/java/starvation-whole-program/ImplicitConstructor.java, ImplicitConstructor.postBlockingCallToUIExecutorBad():void, 54, IPC_ON_UI_THREAD, no_bucket, WARNING, [`void ImplicitConstructor.postBlockingCallToUIExecutorBad()`,Method call: `void ImplicitConstructor$1.run()`,Method call: `void ImplicitConstructor.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] codetoanalyze/java/starvation-whole-program/ImplicitConstructor.java, ImplicitConstructor.postBlockingCallToUIHandlerBad():void, 66, IPC_ON_UI_THREAD, no_bucket, WARNING, [`void ImplicitConstructor.postBlockingCallToUIHandlerBad()`,Method call: `void ImplicitConstructor$1.run()`,Method call: `void ImplicitConstructor.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] +codetoanalyze/java/starvation-whole-program/IndirectStarvation.java, IndirectStarvation.postBlockingCallToBackgroundThreadAndLockBad():void, 32, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void IndirectStarvation.postBlockingCallToBackgroundThreadAndLockBad()`,Method call: `void IndirectStarvation$1.run()`, locks `this.this$0.monitorA` in `class IndirectStarvation$1`] codetoanalyze/java/starvation-whole-program/IndirectStarvation.java, IndirectStarvation.postBlockingCallToBackgroundThreadAndLockBad():void, 32, STARVATION, no_bucket, ERROR, [[Trace 1] `void IndirectStarvation.postBlockingCallToBackgroundThreadAndLockBad()`,Method call: `void IndirectStarvation$1.run()`, locks `this.this$0.monitorA` in `class IndirectStarvation$1`,[Trace 2] `void IndirectStarvation.postBlockingCallToBackgroundThreadAndLockBad()`,Method call: `void IndirectStarvation$2.run()`, locks `this.this$0.monitorA` in `class IndirectStarvation$2`,Method call: `void IndirectStarvation.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] +codetoanalyze/java/starvation-whole-program/IndirectStarvation.java, IndirectStarvation.postBlockingCallToBackgroundThreadAndUseOtherLockOk():void, 56, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void IndirectStarvation.postBlockingCallToBackgroundThreadAndUseOtherLockOk()`,Method call: `void IndirectStarvation$3.run()`, locks `this.this$0.monitorB` in `class IndirectStarvation$3`] codetoanalyze/java/starvation-whole-program/MainMethod.java, MainMethod.main(java.lang.String[]):void, 24, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void MainMethod.main(String[])`,Method call: `void MainMethod$1.run()`, locks `MainMethod.monitorA` in `class MainMethod`, locks `MainMethod.monitorB` in `class MainMethod`,[Trace 2] `void MainMethod.main(String[])`, locks `MainMethod.monitorB` in `class MainMethod`, locks `MainMethod.monitorA` in `class MainMethod`] codetoanalyze/java/starvation-whole-program/MainMethod.java, MainMethod.main(java.lang.String[]):void, 26, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void MainMethod.main(String[])`, locks `MainMethod.monitorB` in `class MainMethod`, locks `MainMethod.monitorA` in `class MainMethod`,[Trace 2] `void MainMethod.main(String[])`,Method call: `void MainMethod$1.run()`, locks `MainMethod.monitorA` in `class MainMethod`, locks `MainMethod.monitorB` in `class MainMethod`] codetoanalyze/java/starvation-whole-program/ModeledExecutors.java, ModeledExecutors.staticPostBlockingCallToUIThreadBad():void, 50, IPC_ON_UI_THREAD, no_bucket, WARNING, [`void ModeledExecutors.staticPostBlockingCallToUIThreadBad()`,Method call: `void ModeledExecutors$3.run()`,Method call: `void ModeledExecutors.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] codetoanalyze/java/starvation-whole-program/ModeledExecutors.java, ModeledExecutors.staticRunBlockingCallToUIThreadBad():void, 61, IPC_ON_UI_THREAD, no_bucket, WARNING, [`void ModeledExecutors.staticRunBlockingCallToUIThreadBad()`,Method call: `void ModeledExecutors$4.run()`,Method call: `void ModeledExecutors.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] codetoanalyze/java/starvation-whole-program/ModeledExecutors.java, ModeledExecutors.staticPostDelayedBlockingCallToUIThreadBad():void, 72, IPC_ON_UI_THREAD, no_bucket, WARNING, [`void ModeledExecutors.staticPostDelayedBlockingCallToUIThreadBad()`,Method call: `void ModeledExecutors$5.run()`,Method call: `void ModeledExecutors.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] codetoanalyze/java/starvation-whole-program/ModeledExecutors.java, ModeledExecutors.scheduleGuaranteedDelayedDeadlockBad():void, 97, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void ModeledExecutors.scheduleGuaranteedDelayedDeadlockBad()`,Method call: `void ModeledExecutors$7.run()`, locks `this.this$0.monitorA` in `class ModeledExecutors$7`, locks `this.this$0.monitorB` in `class ModeledExecutors$7`,[Trace 2] `void ModeledExecutors.scheduleGuaranteedDelayedDeadlockBad()`,Method call: `void ModeledExecutors$8.run()`, locks `this.this$0.monitorB` in `class ModeledExecutors$8`, locks `this.this$0.monitorA` in `class ModeledExecutors$8`] +codetoanalyze/java/starvation-whole-program/ModeledExecutors.java, ModeledExecutors.scheduleGuaranteedDelayedDeadlockBad():void, 110, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ModeledExecutors.scheduleGuaranteedDelayedDeadlockBad()`,Method call: `void ModeledExecutors$8.run()`, locks `this.this$0.monitorA` in `class ModeledExecutors$8`] +codetoanalyze/java/starvation-whole-program/ModeledExecutors.java, ModeledExecutors.scheduleGuaranteedDelayedDeadlockBad():void, 110, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ModeledExecutors.scheduleGuaranteedDelayedDeadlockBad()`,Method call: `void ModeledExecutors$8.run()`, locks `this.this$0.monitorB` in `class ModeledExecutors$8`] codetoanalyze/java/starvation-whole-program/ModeledExecutors.java, ModeledExecutors.scheduleGuaranteedDelayedDeadlockBad():void, 110, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void ModeledExecutors.scheduleGuaranteedDelayedDeadlockBad()`,Method call: `void ModeledExecutors$8.run()`, locks `this.this$0.monitorB` in `class ModeledExecutors$8`, locks `this.this$0.monitorA` in `class ModeledExecutors$8`,[Trace 2] `void ModeledExecutors.scheduleGuaranteedDelayedDeadlockBad()`,Method call: `void ModeledExecutors$7.run()`, locks `this.this$0.monitorA` in `class ModeledExecutors$7`, locks `this.this$0.monitorB` in `class ModeledExecutors$7`] codetoanalyze/java/starvation-whole-program/ModeledExecutors.java, ModeledExecutors.submitBlockingCallToUIThreadBad():void, 127, IPC_ON_UI_THREAD, no_bucket, WARNING, [`void ModeledExecutors.submitBlockingCallToUIThreadBad()`,Method call: `void ModeledExecutors$9.run()`,Method call: `void ModeledExecutors.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] codetoanalyze/java/starvation-whole-program/ModeledExecutors.java, ModeledExecutors.scheduleBlockingCallToUIThreadBad():void, 140, IPC_ON_UI_THREAD, no_bucket, WARNING, [`void ModeledExecutors.scheduleBlockingCallToUIThreadBad()`,Method call: `void ModeledExecutors$10.run()`,Method call: `void ModeledExecutors.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] @@ -26,22 +36,35 @@ codetoanalyze/java/starvation-whole-program/ModeledHandler.java, ModeledHandler. codetoanalyze/java/starvation-whole-program/MyActivity.java, MyActivity.onCreate(android.os.Bundle):void, 28, IPC_ON_UI_THREAD, no_bucket, WARNING, [`void MyActivity.onCreate(Bundle)`,Method call: `void MyActivity.bad()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] codetoanalyze/java/starvation-whole-program/MyActivity.java, MyActivity.onStart():void, 33, IPC_ON_UI_THREAD, no_bucket, WARNING, [`void MyActivity.onStart()`,Method call: `void MyActivity.bad()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] codetoanalyze/java/starvation-whole-program/MyActivity.java, MyActivity.onRestart():void, 38, IPC_ON_UI_THREAD, no_bucket, WARNING, [`void MyActivity.onRestart()`,Method call: `void MyActivity.bad()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] +codetoanalyze/java/starvation-whole-program/MyActivity.java, MyActivity.onStop():void, 48, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void MyActivity.onStop()`, locks `this.monitorA` in `class MyActivity`] codetoanalyze/java/starvation-whole-program/MyActivity.java, MyActivity.onStop():void, 48, STARVATION, no_bucket, ERROR, [[Trace 1] `void MyActivity.onStop()`, locks `this.monitorA` in `class MyActivity`,[Trace 2] `void MyActivity.onStop()`,Method call: `void MyActivity$1.run()`, locks `this.this$0.monitorA` in `class MyActivity$1`,Method call: `void MyActivity.bad()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] +codetoanalyze/java/starvation-whole-program/MyActivity.java, MyActivity.onDestroy():void, 68, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void MyActivity.onDestroy()`, locks `this.monitorC` in `class MyActivity`] codetoanalyze/java/starvation-whole-program/MyActivity.java, MyActivity.onDestroy():void, 68, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void MyActivity.onDestroy()`, locks `this.monitorC` in `class MyActivity`, locks `this.monitorB` in `class MyActivity`,[Trace 2] `void MyActivity.onPause()`,Method call: `void MyActivity$2.run()`, locks `this.this$0.monitorB` in `class MyActivity$2`, locks `this.this$0.monitorC` in `class MyActivity$2`] +codetoanalyze/java/starvation-whole-program/MyActivity.java, MyActivity.onDestroy():void, 69, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void MyActivity.onDestroy()`, locks `this.monitorB` in `class MyActivity`] codetoanalyze/java/starvation-whole-program/MyActivity.java, MyActivity.onPause():void, 76, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void MyActivity.onPause()`,Method call: `void MyActivity$2.run()`, locks `this.this$0.monitorB` in `class MyActivity$2`, locks `this.this$0.monitorC` in `class MyActivity$2`,[Trace 2] `void MyActivity.onDestroy()`, locks `this.monitorC` in `class MyActivity`, locks `this.monitorB` in `class MyActivity`] +codetoanalyze/java/starvation-whole-program/MyActivity.java, MyActivity.onResume():void, 95, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void MyActivity.onResume()`, locks `this.FP_monitorD` in `class MyActivity`] codetoanalyze/java/starvation-whole-program/MyActivity.java, MyActivity.onResume():void, 95, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void MyActivity.onResume()`, locks `this.FP_monitorD` in `class MyActivity`, locks `this.FP_monitorE` in `class MyActivity`,[Trace 2] `void MyActivity.onResume()`,Method call: `void MyActivity$3.run()`, locks `this.this$0.FP_monitorE` in `class MyActivity$3`, locks `this.this$0.FP_monitorD` in `class MyActivity$3`] +codetoanalyze/java/starvation-whole-program/MyActivity.java, MyActivity.onResume():void, 96, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void MyActivity.onResume()`, locks `this.FP_monitorE` in `class MyActivity`] codetoanalyze/java/starvation-whole-program/MyActivity.java, MyActivity.onResume():void, 100, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void MyActivity.onResume()`,Method call: `void MyActivity$3.run()`, locks `this.this$0.FP_monitorE` in `class MyActivity$3`, locks `this.this$0.FP_monitorD` in `class MyActivity$3`,[Trace 2] `void MyActivity.onResume()`, locks `this.FP_monitorD` in `class MyActivity`, locks `this.FP_monitorE` in `class MyActivity`] codetoanalyze/java/starvation-whole-program/MyServiceConnection.java, MyServiceConnection.onServiceConnected(android.content.ComponentName,android.os.IBinder):void, 37, IPC_ON_UI_THREAD, no_bucket, WARNING, [`void MyServiceConnection.onServiceConnected(ComponentName,IBinder)`,Method call: `void MyServiceConnection.bad()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] codetoanalyze/java/starvation-whole-program/MyServiceConnection.java, MyServiceConnection.onServiceDisconnected(android.content.ComponentName):void, 42, IPC_ON_UI_THREAD, no_bucket, WARNING, [`void MyServiceConnection.onServiceDisconnected(ComponentName)`,Method call: `void MyServiceConnection.bad()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] codetoanalyze/java/starvation-whole-program/MyView.java, MyView.scheduleOnBGThread():void, 21, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void MyView.scheduleOnBGThread()`,Method call: `void MyView$1.run()`, locks `this.this$0.monitorA` in `class MyView$1`, locks `this.this$0.monitorB` in `class MyView$1`,[Trace 2] `void MyView.scheduleOnUIThread()`,Method call: `void MyView$2.run()`, locks `this.this$0.monitorB` in `class MyView$2`, locks `this.this$0.monitorA` in `class MyView$2`] +codetoanalyze/java/starvation-whole-program/MyView.java, MyView.scheduleOnUIThread():void, 34, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void MyView.scheduleOnUIThread()`,Method call: `void MyView$2.run()`, locks `this.this$0.monitorA` in `class MyView$2`] +codetoanalyze/java/starvation-whole-program/MyView.java, MyView.scheduleOnUIThread():void, 34, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void MyView.scheduleOnUIThread()`,Method call: `void MyView$2.run()`, locks `this.this$0.monitorB` in `class MyView$2`] codetoanalyze/java/starvation-whole-program/MyView.java, MyView.scheduleOnUIThread():void, 34, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void MyView.scheduleOnUIThread()`,Method call: `void MyView$2.run()`, locks `this.this$0.monitorB` in `class MyView$2`, locks `this.this$0.monitorA` in `class MyView$2`,[Trace 2] `void MyView.scheduleOnBGThread()`,Method call: `void MyView$1.run()`, locks `this.this$0.monitorA` in `class MyView$1`, locks `this.this$0.monitorB` in `class MyView$1`] codetoanalyze/java/starvation-whole-program/StaticInitAttributes.java, StaticInitAttributes.postBlockingCallToUIExecutorBad():void, 52, IPC_ON_UI_THREAD, no_bucket, WARNING, [`void StaticInitAttributes.postBlockingCallToUIExecutorBad()`,Method call: `void StaticInitAttributes$1.run()`,Method call: `void StaticInitAttributes.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] codetoanalyze/java/starvation-whole-program/StaticInitAttributes.java, StaticInitAttributes.postBlockingCallToUIHandlerBad():void, 64, IPC_ON_UI_THREAD, no_bucket, WARNING, [`void StaticInitAttributes.postBlockingCallToUIHandlerBad()`,Method call: `void StaticInitAttributes$1.run()`,Method call: `void StaticInitAttributes.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] +codetoanalyze/java/starvation-whole-program/ThreadScheduling.java, ThreadScheduling.scheduleBlockingCallOnContendedLockBad():void, 36, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ThreadScheduling.scheduleBlockingCallOnContendedLockBad()`,Method call: `void ThreadScheduling$2.run()`, locks `this.this$0.monitorA` in `class ThreadScheduling$2`] codetoanalyze/java/starvation-whole-program/ThreadScheduling.java, ThreadScheduling.scheduleBlockingCallOnContendedLockBad():void, 36, STARVATION, no_bucket, ERROR, [[Trace 1] `void ThreadScheduling.scheduleBlockingCallOnContendedLockBad()`,Method call: `void ThreadScheduling$2.run()`, locks `this.this$0.monitorA` in `class ThreadScheduling$2`,[Trace 2] `void ThreadScheduling.scheduleBlockingCallOnContendedLockBad()`,Method call: `void ThreadScheduling$1.run()`, locks `this.this$0.monitorA` in `class ThreadScheduling$1`,Method call: `void ThreadScheduling.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] codetoanalyze/java/starvation-whole-program/ThreadScheduling.java, ThreadScheduling.scheduleDeadlockBad():void, 60, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void ThreadScheduling.scheduleDeadlockBad()`,Method call: `void ThreadScheduling$3.run()`, locks `this.this$0.monitorB` in `class ThreadScheduling$3`, locks `this.this$0.monitorC` in `class ThreadScheduling$3`,[Trace 2] `void ThreadScheduling.scheduleDeadlockBad()`,Method call: `void ThreadScheduling$4.run()`, locks `this.this$0.monitorC` in `class ThreadScheduling$4`, locks `this.this$0.monitorB` in `class ThreadScheduling$4`] +codetoanalyze/java/starvation-whole-program/ThreadScheduling.java, ThreadScheduling.scheduleDeadlockBad():void, 62, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ThreadScheduling.scheduleDeadlockBad()`,Method call: `void ThreadScheduling$4.run()`, locks `this.this$0.monitorB` in `class ThreadScheduling$4`] +codetoanalyze/java/starvation-whole-program/ThreadScheduling.java, ThreadScheduling.scheduleDeadlockBad():void, 62, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ThreadScheduling.scheduleDeadlockBad()`,Method call: `void ThreadScheduling$4.run()`, locks `this.this$0.monitorC` in `class ThreadScheduling$4`] codetoanalyze/java/starvation-whole-program/ThreadScheduling.java, ThreadScheduling.scheduleDeadlockBad():void, 62, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void ThreadScheduling.scheduleDeadlockBad()`,Method call: `void ThreadScheduling$4.run()`, locks `this.this$0.monitorC` in `class ThreadScheduling$4`, locks `this.this$0.monitorB` in `class ThreadScheduling$4`,[Trace 2] `void ThreadScheduling.scheduleDeadlockBad()`,Method call: `void ThreadScheduling$3.run()`, locks `this.this$0.monitorB` in `class ThreadScheduling$3`, locks `this.this$0.monitorC` in `class ThreadScheduling$3`] +codetoanalyze/java/starvation-whole-program/ThreadScheduling.java, ThreadScheduling.scheduleBlockingCallOnContendedLockViaInheritanceBad():void, 89, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ThreadScheduling.scheduleBlockingCallOnContendedLockViaInheritanceBad()`,Method call: `void ThreadScheduling$5.run()`, locks `this.this$0.monitorD` in `class ThreadScheduling$5`] codetoanalyze/java/starvation-whole-program/ThreadScheduling.java, ThreadScheduling.scheduleBlockingCallOnContendedLockViaInheritanceBad():void, 89, STARVATION, no_bucket, ERROR, [[Trace 1] `void ThreadScheduling.scheduleBlockingCallOnContendedLockViaInheritanceBad()`,Method call: `void ThreadScheduling$5.run()`, locks `this.this$0.monitorD` in `class ThreadScheduling$5`,[Trace 2] `void ThreadScheduling.scheduleBlockingCallOnContendedLockViaInheritanceBad()`,Method call: `void ThreadScheduling$BadThread.run()`, locks `this.this$0.monitorD` in `class ThreadScheduling$BadThread`,Method call: `void ThreadScheduling.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] codetoanalyze/java/starvation-whole-program/UnknownThread.java, UnknownThread.postDeadlockToUnknownAndBackgroundBad():void, 57, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void UnknownThread.postDeadlockToUnknownAndBackgroundBad()`,Method call: `void UnknownThread$3.run()`, locks `this.this$0.monitorA` in `class UnknownThread$3`, locks `this.this$0.monitorB` in `class UnknownThread$3`,[Trace 2] `void UnknownThread.postDeadlockToUnknownAndBackgroundBad()`,Method call: `void UnknownThread$4.run()`, locks `this.this$0.monitorB` in `class UnknownThread$4`, locks `this.this$0.monitorA` in `class UnknownThread$4`] codetoanalyze/java/starvation-whole-program/UnknownThread.java, UnknownThread.postDeadlockToUnknownAndBackgroundBad():void, 68, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void UnknownThread.postDeadlockToUnknownAndBackgroundBad()`,Method call: `void UnknownThread$4.run()`, locks `this.this$0.monitorB` in `class UnknownThread$4`, locks `this.this$0.monitorA` in `class UnknownThread$4`,[Trace 2] `void UnknownThread.postDeadlockToUnknownAndBackgroundBad()`,Method call: `void UnknownThread$3.run()`, locks `this.this$0.monitorA` in `class UnknownThread$3`, locks `this.this$0.monitorB` in `class UnknownThread$3`] codetoanalyze/java/starvation-whole-program/UnknownThread.java, UnknownThread.postDeadlockToUIAndBackgroundBad():void, 84, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void UnknownThread.postDeadlockToUIAndBackgroundBad()`,Method call: `void UnknownThread$5.run()`, locks `this.this$0.monitorC` in `class UnknownThread$5`, locks `this.this$0.monitorD` in `class UnknownThread$5`,[Trace 2] `void UnknownThread.postDeadlockToUIAndBackgroundBad()`,Method call: `void UnknownThread$6.run()`, locks `this.this$0.monitorD` in `class UnknownThread$6`, locks `this.this$0.monitorC` in `class UnknownThread$6`] +codetoanalyze/java/starvation-whole-program/UnknownThread.java, UnknownThread.postDeadlockToUIAndBackgroundBad():void, 95, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void UnknownThread.postDeadlockToUIAndBackgroundBad()`,Method call: `void UnknownThread$6.run()`, locks `this.this$0.monitorC` in `class UnknownThread$6`] +codetoanalyze/java/starvation-whole-program/UnknownThread.java, UnknownThread.postDeadlockToUIAndBackgroundBad():void, 95, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void UnknownThread.postDeadlockToUIAndBackgroundBad()`,Method call: `void UnknownThread$6.run()`, locks `this.this$0.monitorD` in `class UnknownThread$6`] codetoanalyze/java/starvation-whole-program/UnknownThread.java, UnknownThread.postDeadlockToUIAndBackgroundBad():void, 95, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void UnknownThread.postDeadlockToUIAndBackgroundBad()`,Method call: `void UnknownThread$6.run()`, locks `this.this$0.monitorD` in `class UnknownThread$6`, locks `this.this$0.monitorC` in `class UnknownThread$6`,[Trace 2] `void UnknownThread.postDeadlockToUIAndBackgroundBad()`,Method call: `void UnknownThread$5.run()`, locks `this.this$0.monitorC` in `class UnknownThread$5`, locks `this.this$0.monitorD` in `class UnknownThread$5`] diff --git a/infer/tests/codetoanalyze/java/starvation/UiLock.java b/infer/tests/codetoanalyze/java/starvation/UiLock.java new file mode 100644 index 00000000000..14c460692b7 --- /dev/null +++ b/infer/tests/codetoanalyze/java/starvation/UiLock.java @@ -0,0 +1,15 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +import android.support.annotation.UiThread; + +class UiLock { + @UiThread + void lockOnUiThreadWarning() { + synchronized (this) { + } + } +} diff --git a/infer/tests/codetoanalyze/java/starvation/issues.exp b/infer/tests/codetoanalyze/java/starvation/issues.exp index c1e32c2ae3a..aaf8aa7f99d 100644 --- a/infer/tests/codetoanalyze/java/starvation/issues.exp +++ b/infer/tests/codetoanalyze/java/starvation/issues.exp @@ -1,4 +1,5 @@ codetoanalyze/java/starvation/AsyncTaskGet.java, AsyncTaskGet.taskGetOnUiThreadBad():void, 20, STARVATION, no_bucket, ERROR, [`void AsyncTaskGet.taskGetOnUiThreadBad()`,calls `Object AsyncTask.get()`] +codetoanalyze/java/starvation/AsyncTaskGet.java, AsyncTaskGet.lockOnUiThreadBad():void, 31, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void AsyncTaskGet.lockOnUiThreadBad()`, locks `this.lock` in `class AsyncTaskGet`] codetoanalyze/java/starvation/AsyncTaskGet.java, AsyncTaskGet.lockOnUiThreadBad():void, 31, STARVATION, no_bucket, ERROR, [[Trace 1] `void AsyncTaskGet.lockOnUiThreadBad()`, locks `this.lock` in `class AsyncTaskGet`,[Trace 2] `void AsyncTaskGet.taskGetUnderLock()`, locks `this.lock` in `class AsyncTaskGet`,calls `Object AsyncTask.get()`] codetoanalyze/java/starvation/Binders.java, Binders.interBad():void, 36, IPC_ON_UI_THREAD, no_bucket, WARNING, [`void Binders.interBad()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] codetoanalyze/java/starvation/Binders.java, Binders.intraBad():void, 41, IPC_ON_UI_THREAD, no_bucket, WARNING, [`void Binders.intraBad()`,Method call: `void Binders.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] @@ -13,12 +14,15 @@ codetoanalyze/java/starvation/Binders.java, Binders.doGetRealSizeBad(android.vie codetoanalyze/java/starvation/Countdwn.java, Countdwn.awaitOnMainByCallBad():void, 16, STARVATION, no_bucket, ERROR, [`void Countdwn.awaitOnMainByCallBad()`,calls `void CountDownLatch.await()`] codetoanalyze/java/starvation/Countdwn.java, Countdwn.awaitOnMainByAnnotBad():void, 21, STARVATION, no_bucket, ERROR, [`void Countdwn.awaitOnMainByAnnotBad()`,calls `void CountDownLatch.await()`] codetoanalyze/java/starvation/FutureGet.java, FutureGet.getDirectBad():void, 21, STARVATION, no_bucket, ERROR, [`void FutureGet.getDirectBad()`,calls `Object Future.get()`] +codetoanalyze/java/starvation/FutureGet.java, FutureGet.getIndirectBad():void, 26, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void FutureGet.getIndirectBad()`, locks `this.lock` in `class FutureGet`] codetoanalyze/java/starvation/FutureGet.java, FutureGet.getIndirectBad():void, 26, STARVATION, no_bucket, ERROR, [[Trace 1] `void FutureGet.getIndirectBad()`, locks `this.lock` in `class FutureGet`,[Trace 2] `void FutureGet.getUnderLock()`, locks `this.lock` in `class FutureGet`,calls `Object Future.get()`] codetoanalyze/java/starvation/FutureGet.java, FutureGet.getTimeoutOneDayBad():void, 43, STARVATION, no_bucket, ERROR, [`void FutureGet.getTimeoutOneDayBad()`,calls `Object Future.get(long,TimeUnit)`] codetoanalyze/java/starvation/FutureGet.java, FutureGet.getTimeoutOneHourBad():void, 59, STARVATION, no_bucket, ERROR, [`void FutureGet.getTimeoutOneHourBad()`,calls `Object Future.get(long,TimeUnit)`] codetoanalyze/java/starvation/FutureGet.java, FutureGet.getTimeout50000001MicroSecondsBad():void, 83, STARVATION, no_bucket, ERROR, [`void FutureGet.getTimeout50000001MicroSecondsBad()`,calls `Object Future.get(long,TimeUnit)`] codetoanalyze/java/starvation/FutureGet.java, FutureGet.getTimeout64BitsBad():void, 91, STARVATION, no_bucket, ERROR, [`void FutureGet.getTimeout64BitsBad()`,calls `Object Future.get(long,TimeUnit)`] +codetoanalyze/java/starvation/IndirectBlock.java, IndirectBlock.takeExpensiveLockOnUiThreadBad():void, 23, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void IndirectBlock.takeExpensiveLockOnUiThreadBad()`, locks `this.expensiveLock` in `class IndirectBlock`] codetoanalyze/java/starvation/IndirectBlock.java, IndirectBlock.takeExpensiveLockOnUiThreadBad():void, 23, STARVATION, no_bucket, ERROR, [[Trace 1] `void IndirectBlock.takeExpensiveLockOnUiThreadBad()`, locks `this.expensiveLock` in `class IndirectBlock`,[Trace 2] `void IndirectBlock.doTransactUnderLock()`, locks `this.expensiveLock` in `class IndirectBlock`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] +codetoanalyze/java/starvation/IndirectBlock.java, IndirectBlock.takeRemoteExpensiveLockOnUiThreadBad(IndirectInterproc):void, 35, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void IndirectBlock.takeRemoteExpensiveLockOnUiThreadBad(IndirectInterproc)`,Method call: `void IndirectInterproc.takeLock()`, locks `i` in `class IndirectInterproc`] codetoanalyze/java/starvation/IndirectBlock.java, IndirectBlock.takeRemoteExpensiveLockOnUiThreadBad(IndirectInterproc):void, 35, STARVATION, no_bucket, ERROR, [[Trace 1] `void IndirectBlock.takeRemoteExpensiveLockOnUiThreadBad(IndirectInterproc)`,Method call: `void IndirectInterproc.takeLock()`, locks `i` in `class IndirectInterproc`,[Trace 2] `void IndirectInterproc.doTransactUnderLock(Binder)`, locks `this` in `class IndirectInterproc`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] codetoanalyze/java/starvation/InnerClass.java, InnerClass.FP_outerInnerOk(InnerClass$InnerClassA):void, 20, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void InnerClass.FP_outerInnerOk(InnerClass$InnerClassA)`, locks `this` in `class InnerClass`,Method call: `void InnerClass$InnerClassA.lockInner()`, locks `a` in `class InnerClass$InnerClassA`,[Trace 2] `InnerClass$InnerClassA.(InnerClass,Object)`, locks `this` in `class InnerClass$InnerClassA`,Method call: `void InnerClass.lockOuter()`, locks `this$0` in `class InnerClass`] codetoanalyze/java/starvation/InnerClass.java, InnerClass.FP_outerInnerOk(InnerClass$InnerClassA):void, 20, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void InnerClass.FP_outerInnerOk(InnerClass$InnerClassA)`, locks `this` in `class InnerClass`,Method call: `void InnerClass$InnerClassA.lockInner()`, locks `a` in `class InnerClass$InnerClassA`,[Trace 2] `void InnerClass$InnerClassA.innerOuterBad()`, locks `this` in `class InnerClass$InnerClassA`,Method call: `void InnerClass.lockOuter()`, locks `this.this$0` in `class InnerClass$InnerClassA`] @@ -31,6 +35,7 @@ codetoanalyze/java/starvation/Intraproc.java, Intraproc.intraBad(IntraprocA):voi codetoanalyze/java/starvation/Intraproc.java, IntraprocA.intraBad(Intraproc):void, 35, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void IntraprocA.intraBad(Intraproc)`, locks `this` in `class IntraprocA`, locks `o` in `class Intraproc`,[Trace 2] `void Intraproc.intraBad(IntraprocA)`, locks `this` in `class Intraproc`, locks `o` in `class IntraprocA`] codetoanalyze/java/starvation/LazyInit.java, LazyInit.baselineBad():java.lang.Object, 29, IPC_ON_UI_THREAD, no_bucket, WARNING, [`Object LazyInit.baselineBad()`,Method call: `Object LazyInit.init()`,Method call: `void LazyInit.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] codetoanalyze/java/starvation/LazyInit.java, LazyInit.notLazyInitBad():void, 46, IPC_ON_UI_THREAD, no_bucket, WARNING, [`void LazyInit.notLazyInitBad()`,Method call: `Object LazyInit.init()`,Method call: `void LazyInit.doTransact()`,calls `boolean Binder.transact(int,Parcel,Parcel,int)`] +codetoanalyze/java/starvation/LegacySync.java, LegacySync.onUiThreadOpBad():java.lang.Object, 25, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`Object LegacySync.onUiThreadOpBad()`, locks `this.table` in `class LegacySync`] codetoanalyze/java/starvation/LegacySync.java, LegacySync.onUiThreadOpBad():java.lang.Object, 25, STARVATION, no_bucket, ERROR, [[Trace 1] `Object LegacySync.onUiThreadOpBad()`, locks `this.table` in `class LegacySync`,[Trace 2] `void LegacySync.notOnUiThreadSyncedBad()`, locks `this.table` in `class LegacySync`,calls `Object Future.get()`] codetoanalyze/java/starvation/LocklessTests.java, LocklessTestsA.locklessMethod():void, 23, LOCKLESS_VIOLATION, no_bucket, ERROR, [`void LocklessTestsA.locklessMethod()`, locks `this` in `class LocklessTestsA`] codetoanalyze/java/starvation/LocklessTests.java, LocklessTestsB.locklessMethod():void, 39, LOCKLESS_VIOLATION, no_bucket, ERROR, [`void LocklessTestsB.locklessMethod()`, locks `this` in `class LocklessTestsB`] @@ -49,10 +54,15 @@ codetoanalyze/java/starvation/MyActivity.java, MyActivity.onDestroy():void, 58, codetoanalyze/java/starvation/NonBlk.java, NonBlk.deadlockABBad():void, 33, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void NonBlk.deadlockABBad()`, locks `this` in `class NonBlk`, locks `this.future` in `class NonBlk`,[Trace 2] `void NonBlk.deadlockBABad()`, locks `this.future` in `class NonBlk`, locks `this` in `class NonBlk`] codetoanalyze/java/starvation/NonBlk.java, NonBlk.deadlockBABad():void, 40, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void NonBlk.deadlockBABad()`, locks `this.future` in `class NonBlk`, locks `this` in `class NonBlk`,[Trace 2] `void NonBlk.deadlockABBad()`, locks `this` in `class NonBlk`, locks `this.future` in `class NonBlk`] codetoanalyze/java/starvation/NotUnderLock.java, NotUnderLock.firstAcquisitionBad():void, 17, ARBITRARY_CODE_EXECUTION_UNDER_LOCK, no_bucket, ERROR, [`void NotUnderLock.firstAcquisitionBad()`, locks `this` in `class NotUnderLock`,Method call: `void NotUnderLock.callFutureSetOk()`,calls `boolean SettableFuture.set(Object)`] +codetoanalyze/java/starvation/ObjWait.java, ObjWait.waitOnMainWithoutTimeoutBad():void, 23, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ObjWait.waitOnMainWithoutTimeoutBad()`, locks `this.o` in `class ObjWait`] codetoanalyze/java/starvation/ObjWait.java, ObjWait.waitOnMainWithoutTimeoutBad():void, 24, STARVATION, no_bucket, ERROR, [`void ObjWait.waitOnMainWithoutTimeoutBad()`,calls `wait` on `this.o` in `class ObjWait`] +codetoanalyze/java/starvation/ObjWait.java, ObjWait.waitOnMainWithExcessiveTimeout1Bad():void, 30, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ObjWait.waitOnMainWithExcessiveTimeout1Bad()`, locks `this.o` in `class ObjWait`] codetoanalyze/java/starvation/ObjWait.java, ObjWait.waitOnMainWithExcessiveTimeout1Bad():void, 31, STARVATION, no_bucket, ERROR, [`void ObjWait.waitOnMainWithExcessiveTimeout1Bad()`,calls `wait` on `this.o` in `class ObjWait`] +codetoanalyze/java/starvation/ObjWait.java, ObjWait.waitOnMainWithExcessiveTimeout2Bad():void, 37, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ObjWait.waitOnMainWithExcessiveTimeout2Bad()`, locks `this.o` in `class ObjWait`] codetoanalyze/java/starvation/ObjWait.java, ObjWait.waitOnMainWithExcessiveTimeout2Bad():void, 38, STARVATION, no_bucket, ERROR, [`void ObjWait.waitOnMainWithExcessiveTimeout2Bad()`,calls `wait` on `this.o` in `class ObjWait`] +codetoanalyze/java/starvation/ObjWait.java, ObjWait.indirectWaitOnMainWithoutTimeoutBad():void, 46, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ObjWait.indirectWaitOnMainWithoutTimeoutBad()`, locks `this.lock` in `class ObjWait`] codetoanalyze/java/starvation/ObjWait.java, ObjWait.indirectWaitOnMainWithoutTimeoutBad():void, 46, STARVATION, no_bucket, ERROR, [[Trace 1] `void ObjWait.indirectWaitOnMainWithoutTimeoutBad()`, locks `this.lock` in `class ObjWait`,[Trace 2] `void ObjWait.lockAndWaitOnAnyWithoutTimeoutBad()`, locks `this.lock` in `class ObjWait`, locks `this.x` in `class ObjWait`,calls `wait` on `this.x` in `class ObjWait`] +codetoanalyze/java/starvation/ObjWait.java, ObjWait.indirectWaitSameLockOnMainOk():void, 62, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ObjWait.indirectWaitSameLockOnMainOk()`, locks `this.y` in `class ObjWait`] codetoanalyze/java/starvation/Parameters.java, Parameters.otherWaySyncOnParamBad(java.lang.Object):void, 20, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void Parameters.otherWaySyncOnParamBad(Object)`, locks `x` in `class java.lang.Object`, locks `this` in `class Parameters`,[Trace 2] `void Parameters.oneWaySyncOnParamBad(Object)`, locks `this` in `class Parameters`,Method call: `void Parameters.syncOnParam(Object)`, locks `x` in `class java.lang.Object`] codetoanalyze/java/starvation/Parameters.java, Parameters.oneWayEmulateSyncBad():void, 34, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void Parameters.oneWayEmulateSyncBad()`, locks `this` in `class Parameters`,Method call: `void Parameters.emulateSynchronized(Parameters)`, locks `this.someObject` in `class Parameters`,[Trace 2] `void Parameters.anotherWayEmulateSyncBad()`, locks `this.someObject` in `class Parameters`, locks `this` in `class Parameters`] codetoanalyze/java/starvation/Parameters.java, Parameters.anotherWayEmulateSyncBad():void, 39, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void Parameters.anotherWayEmulateSyncBad()`, locks `this.someObject` in `class Parameters`, locks `this` in `class Parameters`,[Trace 2] `void Parameters.oneWayEmulateSyncBad()`, locks `this` in `class Parameters`,Method call: `void Parameters.emulateSynchronized(Parameters)`, locks `this.someObject` in `class Parameters`] @@ -89,20 +99,36 @@ codetoanalyze/java/starvation/StrictModeViolation.java, StrictModeViolation.viol codetoanalyze/java/starvation/StrictModeViolation.java, StrictModeViolation.violateStrictModeBad():void, 39, STRICT_MODE_VIOLATION, no_bucket, ERROR, [`void StrictModeViolation.violateStrictModeBad()`,calls `boolean File.setWritable(boolean)`] codetoanalyze/java/starvation/SuppLint.java, SuppLint.onUiThreadBad():void, 25, STARVATION, no_bucket, ERROR, [`void SuppLint.onUiThreadBad()`,calls `Object Future.get()`] codetoanalyze/java/starvation/ThreadCalls.java, ThreadCalls.sleepOnUIThreadBad():void, 17, STARVATION, no_bucket, ERROR, [`void ThreadCalls.sleepOnUIThreadBad()`,calls `void Thread.sleep(long)`] +codetoanalyze/java/starvation/ThreadCalls.java, ThreadCalls.indirectSleepOnUIThreadBad():void, 24, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ThreadCalls.indirectSleepOnUIThreadBad()`, locks `this.lock` in `class ThreadCalls`] codetoanalyze/java/starvation/ThreadCalls.java, ThreadCalls.indirectSleepOnUIThreadBad():void, 24, STARVATION, no_bucket, ERROR, [[Trace 1] `void ThreadCalls.indirectSleepOnUIThreadBad()`, locks `this.lock` in `class ThreadCalls`,[Trace 2] `void ThreadCalls.lockAndSleepOnNonUIThread()`, locks `this.lock` in `class ThreadCalls`,Method call: `void ThreadCalls.sleepOnAnyThreadOk()`,calls `void Thread.sleep(long)`] codetoanalyze/java/starvation/ThreadCalls.java, ThreadCalls.joinOnUIThreadBad(java.lang.Thread):void, 40, STARVATION, no_bucket, ERROR, [`void ThreadCalls.joinOnUIThreadBad(Thread)`,calls `void Thread.join()`] +codetoanalyze/java/starvation/ThreadCalls.java, ThreadCalls.indirectJoinOnUIThreadBad():void, 59, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ThreadCalls.indirectJoinOnUIThreadBad()`, locks `this.joinLock` in `class ThreadCalls`] codetoanalyze/java/starvation/ThreadCalls.java, ThreadCalls.indirectJoinOnUIThreadBad():void, 59, STARVATION, no_bucket, ERROR, [[Trace 1] `void ThreadCalls.indirectJoinOnUIThreadBad()`, locks `this.joinLock` in `class ThreadCalls`,[Trace 2] `void ThreadCalls.lockAndSleepOnNonUIThread(Thread)`, locks `this.joinLock` in `class ThreadCalls`,Method call: `void ThreadCalls.joinOnAnyThreadOk(Thread)`,calls `void Thread.join()`] +codetoanalyze/java/starvation/ThreadDeadlock.java, ThreadDeadlock.noParallelismAOk():void, 18, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ThreadDeadlock.noParallelismAOk()`, locks `this.lockA` in `class ThreadDeadlock`] +codetoanalyze/java/starvation/ThreadDeadlock.java, ThreadDeadlock.noParallelismBOk():void, 24, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ThreadDeadlock.noParallelismBOk()`, locks `this.lockA` in `class ThreadDeadlock`] +codetoanalyze/java/starvation/ThreadDeadlock.java, ThreadDeadlock.noParallelismBOk():void, 25, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ThreadDeadlock.noParallelismBOk()`, locks `this` in `class ThreadDeadlock`] codetoanalyze/java/starvation/ThreadDeadlock.java, ThreadDeadlock.annotatedUiThreadBad():void, 35, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void ThreadDeadlock.annotatedUiThreadBad()`, locks `this` in `class ThreadDeadlock`, locks `this.lockB` in `class ThreadDeadlock`,[Trace 2] `void ThreadDeadlock.annotatedWorkerThreadBad()`, locks `this.lockB` in `class ThreadDeadlock`, locks `this` in `class ThreadDeadlock`] +codetoanalyze/java/starvation/ThreadDeadlock.java, ThreadDeadlock.annotatedUiThreadBad():void, 36, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ThreadDeadlock.annotatedUiThreadBad()`, locks `this.lockB` in `class ThreadDeadlock`] codetoanalyze/java/starvation/ThreadDeadlock.java, ThreadDeadlock.annotatedWorkerThreadBad():void, 42, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void ThreadDeadlock.annotatedWorkerThreadBad()`, locks `this.lockB` in `class ThreadDeadlock`, locks `this` in `class ThreadDeadlock`,[Trace 2] `void ThreadDeadlock.annotatedUiThreadBad()`, locks `this` in `class ThreadDeadlock`, locks `this.lockB` in `class ThreadDeadlock`] codetoanalyze/java/starvation/ThreadDeadlock.java, ThreadDeadlock.assertOnUIThreadBad():void, 52, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void ThreadDeadlock.assertOnUIThreadBad()`, locks `this` in `class ThreadDeadlock`, locks `this.lockC` in `class ThreadDeadlock`,[Trace 2] `void ThreadDeadlock.assertOnBackgroundThreadBad()`, locks `this.lockC` in `class ThreadDeadlock`, locks `this` in `class ThreadDeadlock`] +codetoanalyze/java/starvation/ThreadDeadlock.java, ThreadDeadlock.assertOnUIThreadBad():void, 54, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ThreadDeadlock.assertOnUIThreadBad()`, locks `this.lockC` in `class ThreadDeadlock`] codetoanalyze/java/starvation/ThreadDeadlock.java, ThreadDeadlock.assertOnBackgroundThreadBad():void, 60, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void ThreadDeadlock.assertOnBackgroundThreadBad()`, locks `this.lockC` in `class ThreadDeadlock`, locks `this` in `class ThreadDeadlock`,[Trace 2] `void ThreadDeadlock.assertOnUIThreadBad()`, locks `this` in `class ThreadDeadlock`, locks `this.lockC` in `class ThreadDeadlock`] codetoanalyze/java/starvation/ThreadDeadlock.java, ThreadDeadlock.notAnnotatedBadA():void, 71, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void ThreadDeadlock.notAnnotatedBadA()`, locks `this` in `class ThreadDeadlock`, locks `this.lockD` in `class ThreadDeadlock`,[Trace 2] `void ThreadDeadlock.notAnnotatedBBad()`, locks `this.lockD` in `class ThreadDeadlock`, locks `this` in `class ThreadDeadlock`] codetoanalyze/java/starvation/ThreadDeadlock.java, ThreadDeadlock.notAnnotatedBBad():void, 77, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void ThreadDeadlock.notAnnotatedBBad()`, locks `this.lockD` in `class ThreadDeadlock`, locks `this` in `class ThreadDeadlock`,[Trace 2] `void ThreadDeadlock.notAnnotatedBadA()`, locks `this` in `class ThreadDeadlock`, locks `this.lockD` in `class ThreadDeadlock`] +codetoanalyze/java/starvation/ThreadSensitivity.java, ThreadSensitivity.conditionalAssertMainThread_Bad(boolean):void, 16, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ThreadSensitivity.conditionalAssertMainThread_Bad(boolean)`, locks `this.monitorA` in `class ThreadSensitivity`] codetoanalyze/java/starvation/ThreadSensitivity.java, ThreadSensitivity.conditionalAssertMainThread_Bad(boolean):void, 16, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void ThreadSensitivity.conditionalAssertMainThread_Bad(boolean)`, locks `this.monitorA` in `class ThreadSensitivity`, locks `this.monitorB` in `class ThreadSensitivity`,[Trace 2] `void ThreadSensitivity.conditionalAssertMainThread_Bad(boolean)`, locks `this.monitorB` in `class ThreadSensitivity`, locks `this.monitorA` in `class ThreadSensitivity`] +codetoanalyze/java/starvation/ThreadSensitivity.java, ThreadSensitivity.conditionalAssertMainThread_Bad(boolean):void, 17, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ThreadSensitivity.conditionalAssertMainThread_Bad(boolean)`, locks `this.monitorB` in `class ThreadSensitivity`] codetoanalyze/java/starvation/ThreadSensitivity.java, ThreadSensitivity.conditionalAssertMainThread_Bad(boolean):void, 22, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void ThreadSensitivity.conditionalAssertMainThread_Bad(boolean)`, locks `this.monitorB` in `class ThreadSensitivity`, locks `this.monitorA` in `class ThreadSensitivity`,[Trace 2] `void ThreadSensitivity.conditionalAssertMainThread_Bad(boolean)`, locks `this.monitorA` in `class ThreadSensitivity`, locks `this.monitorB` in `class ThreadSensitivity`] +codetoanalyze/java/starvation/ThreadSensitivity.java, ThreadSensitivity.conditionalIsMainThread_Ok():void, 35, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ThreadSensitivity.conditionalIsMainThread_Ok()`, locks `this.monitorC` in `class ThreadSensitivity`] +codetoanalyze/java/starvation/ThreadSensitivity.java, ThreadSensitivity.conditionalIsMainThread_Ok():void, 36, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ThreadSensitivity.conditionalIsMainThread_Ok()`, locks `this.monitorD` in `class ThreadSensitivity`] +codetoanalyze/java/starvation/ThreadSensitivity.java, ThreadSensitivity.conditionalIsUiThread_Ok():void, 44, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ThreadSensitivity.conditionalIsUiThread_Ok()`, locks `this.monitorD` in `class ThreadSensitivity`] +codetoanalyze/java/starvation/ThreadSensitivity.java, ThreadSensitivity.conditionalIsUiThread_Ok():void, 45, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ThreadSensitivity.conditionalIsUiThread_Ok()`, locks `this.monitorC` in `class ThreadSensitivity`] codetoanalyze/java/starvation/ThreadSensitivity.java, ThreadSensitivity.conditionalNegatedIsMainThread_Bad():void, 55, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void ThreadSensitivity.conditionalNegatedIsMainThread_Bad()`, locks `this.monitorE` in `class ThreadSensitivity`, locks `this.monitorF` in `class ThreadSensitivity`,[Trace 2] `void ThreadSensitivity.conditionalNegatedIsMainThread_Bad()`, locks `this.monitorF` in `class ThreadSensitivity`, locks `this.monitorE` in `class ThreadSensitivity`] +codetoanalyze/java/starvation/ThreadSensitivity.java, ThreadSensitivity.conditionalNegatedIsMainThread_Bad():void, 60, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ThreadSensitivity.conditionalNegatedIsMainThread_Bad()`, locks `this.monitorF` in `class ThreadSensitivity`] codetoanalyze/java/starvation/ThreadSensitivity.java, ThreadSensitivity.conditionalNegatedIsMainThread_Bad():void, 60, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void ThreadSensitivity.conditionalNegatedIsMainThread_Bad()`, locks `this.monitorF` in `class ThreadSensitivity`, locks `this.monitorE` in `class ThreadSensitivity`,[Trace 2] `void ThreadSensitivity.conditionalNegatedIsMainThread_Bad()`, locks `this.monitorE` in `class ThreadSensitivity`, locks `this.monitorF` in `class ThreadSensitivity`] +codetoanalyze/java/starvation/ThreadSensitivity.java, ThreadSensitivity.conditionalNegatedIsMainThread_Bad():void, 61, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void ThreadSensitivity.conditionalNegatedIsMainThread_Bad()`, locks `this.monitorE` in `class ThreadSensitivity`] codetoanalyze/java/starvation/ThreadSensitivity.java, ThreadSensitivity.confusedAssertBad(boolean,boolean):void, 78, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void ThreadSensitivity.confusedAssertBad(boolean,boolean)`, locks `this.monitorG` in `class ThreadSensitivity`, locks `this.monitorH` in `class ThreadSensitivity`,[Trace 2] `void ThreadSensitivity.confusedAssertBad(boolean,boolean)`, locks `this.monitorH` in `class ThreadSensitivity`, locks `this.monitorG` in `class ThreadSensitivity`] codetoanalyze/java/starvation/ThreadSensitivity.java, ThreadSensitivity.confusedAssertBad(boolean,boolean):void, 83, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void ThreadSensitivity.confusedAssertBad(boolean,boolean)`, locks `this.monitorH` in `class ThreadSensitivity`, locks `this.monitorG` in `class ThreadSensitivity`,[Trace 2] `void ThreadSensitivity.confusedAssertBad(boolean,boolean)`, locks `this.monitorG` in `class ThreadSensitivity`, locks `this.monitorH` in `class ThreadSensitivity`] codetoanalyze/java/starvation/ThreadSensitivity.java, ThreadSensitivity.FP_confusedAssertOk(boolean):void, 99, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void ThreadSensitivity.FP_confusedAssertOk(boolean)`, locks `this.monitorI` in `class ThreadSensitivity`, locks `this.monitorJ` in `class ThreadSensitivity`,[Trace 2] `void ThreadSensitivity.FP_confusedAssertOk(boolean)`, locks `this.monitorJ` in `class ThreadSensitivity`, locks `this.monitorI` in `class ThreadSensitivity`] codetoanalyze/java/starvation/ThreadSensitivity.java, ThreadSensitivity.FP_confusedAssertOk(boolean):void, 106, DEADLOCK, no_bucket, ERROR, [[Trace 1] `void ThreadSensitivity.FP_confusedAssertOk(boolean)`, locks `this.monitorJ` in `class ThreadSensitivity`, locks `this.monitorI` in `class ThreadSensitivity`,[Trace 2] `void ThreadSensitivity.FP_confusedAssertOk(boolean)`, locks `this.monitorI` in `class ThreadSensitivity`, locks `this.monitorJ` in `class ThreadSensitivity`] +codetoanalyze/java/starvation/UiLock.java, UiLock.lockOnUiThreadWarning():void, 12, LOCK_ON_UI_THREAD, no_bucket, WARNING, [`void UiLock.lockOnUiThreadWarning()`, locks `this` in `class UiLock`]