robolectric/robolectric — pull request #1401 by ndahlquist (2014-11-26 04:32:23+00:00)
Title: Remove un-necessary synchronization in ShadowWrangler.

https://github.com/robolectric/robolectric/issues/1100

ShadowWrangler has the following mutable members which may be affected by the decrease in synchronization:
- shadowMap: Not modified after the constructor.
- metaShadowMap: Accesses are synchronized within getMetaShadow.
- planCache: Race condition introduced. A cached value may now be overwritten. It is not clear that atomicity of writes is necessary here.
- shadowConfigCache: Race condition introduced. A cached value may now be overwritten. It is not clear that atomicity of writes is necessary here.

```
Found one Java-level deadlock:
=============================
"pool-6-thread-1":
waiting to lock monitor 0x00007f9eb0003148 (object 0x00000007dc5feba8, a org.robolectric.bytecode.ShadowWrangler),
which is held by "Test worker"
"Test worker":
waiting to lock monitor 0x00007f9f040045e8 (object 0x0000000780e10d90, a java.lang.Class),
which is held by "Thread-305"
"Thread-305":
waiting to lock monitor 0x00007f9eb0003148 (object 0x00000007dc5feba8, a org.robolectric.bytecode.ShadowWrangler),
which is held by "Test worker"

Java stack information for the threads listed above:
===================================================
"pool-6-thread-1":
at org.robolectric.bytecode.ShadowWrangler.methodInvoked(ShadowWrangler.java)
- waiting to lock <0x00000007dc5feba8> (a org.robolectric.bytecode.ShadowWrangler)
at org.robolectric.bytecode.RobolectricInternals.methodInvoked(RobolectricInternals.java:47)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java)
at com.snapchat.android.database.table.CashFeedItemTable$2.doInBackground(CashFeedItemTable.java:296)
at com.snapchat.android.database.table.CashFeedItemTable$2.doInBackground(CashFeedItemTable.java:293)
at android.os.ShadowAsyncTaskBridge.doInBackground(ShadowAsyncTaskBridge.java:14)
at org.robolectric.shadows.ShadowAsyncTask$BackgroundWorker.call(ShadowAsyncTask.java:149)
at org.robolectric.util.SimpleFuture.run(SimpleFuture.java:52)
- locked <0x00000007dc5c1830> (a org.robolectric.shadows.ShadowAsyncTask$1)
at org.robolectric.shadows.ShadowAsyncTask$3.run(ShadowAsyncTask.java:111)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
"Test worker":
at java.lang.Class.initAnnotationsIfNecessary(Class.java:3175)
- waiting to lock <0x0000000780e10d90> (a java.lang.Class for org.robolectric.shadows.ShadowLooper)
at java.lang.Class.getAnnotation(Class.java:3137)
at org.robolectric.bytecode.ShadowWrangler.getShadowedClass(ShadowWrangler.java:188)
at org.robolectric.bytecode.ShadowWrangler.calculatePlan(ShadowWrangler.java:122)
at org.robolectric.bytecode.ShadowWrangler.methodInvoked(ShadowWrangler.java:80)
- locked <0x00000007dc5feba8> (a org.robolectric.bytecode.ShadowWrangler)
at org.robolectric.bytecode.RobolectricInternals.methodInvoked(RobolectricInternals.java:47)
at android.os.Looper.getMainLooper(Looper.java)
at com.snapchat.android.model.chat.ChatConversation.(ChatConversation.java:210)
at com.snapchat.android.model.chat.ChatConversation.(ChatConversation.java:197)
at com.snapchat.android.model.chat.ChatConversationTest.setup(ChatConversationTest.java:56)
at sun.reflect.GeneratedMethodAccessor121.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:236)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:158)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:86)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:49)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:69)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:48)
at sun.reflect.GeneratedMethodAccessor55.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:105)
at sun.reflect.GeneratedMethodAccessor54.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:355)
at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.java:64)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
"Thread-305":
at org.robolectric.bytecode.ShadowWrangler.getShadowConfig(ShadowWrangler.java)
- waiting to lock <0x00000007dc5feba8> (a org.robolectric.bytecode.ShadowWrangler)
at org.robolectric.bytecode.ShadowWrangler.getShadowClassName(ShadowWrangler.java:383)
at org.robolectric.bytecode.ShadowWrangler.createShadowFor(ShadowWrangler.java:349)
at org.robolectric.bytecode.ShadowWrangler.initializing(ShadowWrangler.java:73)
at org.robolectric.bytecode.RobolectricInternals.initializing(RobolectricInternals.java:42)
at android.os.Looper.$$robo$init(Looper.java)
at android.os.Looper.(Looper.java)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at org.robolectric.internal.ReflectionHelpers.callConstructorReflectively(ReflectionHelpers.java:102)
at org.robolectric.bytecode.RobolectricInternals.newInstanceOf(RobolectricInternals.java:16)
at org.robolectric.Robolectric.newInstanceOf(Robolectric.java:344)
at org.robolectric.Robolectric$Reflection.newInstanceOf(Robolectric.java:1410)
at org.robolectric.shadows.ShadowLooper.createLooper(ShadowLooper.java:42)
at org.robolectric.shadows.ShadowLooper.access$000(ShadowLooper.java:24)
at org.robolectric.shadows.ShadowLooper$1.create(ShadowLooper.java:36)
at org.robolectric.shadows.ShadowLooper$1.create(ShadowLooper.java:34)
at org.robolectric.util.SoftThreadLocal$1.initialValue(SoftThreadLocal.java:8)
at org.robolectric.util.SoftThreadLocal$1.initialValue(SoftThreadLocal.java:6)
at java.lang.ThreadLocal.setInitialValue(ThreadLocal.java:160)
at java.lang.ThreadLocal.get(ThreadLocal.java:150)
at org.robolectric.util.SoftThreadLocal.get(SoftThreadLocal.java:13)
- locked <0x00000007dc6001c8> (a org.robolectric.shadows.ShadowLooper$1)
at org.robolectric.shadows.ShadowLooper.myLooper(ShadowLooper.java:80)
- locked <0x0000000780e10d90> (a java.lang.Class for org.robolectric.shadows.ShadowLooper)
at sun.reflect.GeneratedMethodAccessor15.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.robolectric.bytecode.ShadowWrangler$ShadowMethodPlan.run(ShadowWrangler.java:507)
at android.os.Looper.myLooper(Looper.java)
at android.database.sqlite.SQLiteDatabase.$$robo$$SQLiteDatabase_ab15_isMainThread(SQLiteDatabase.java:390)
at android.database.sqlite.SQLiteDatabase.isMainThread(SQLiteDatabase.java)
at android.database.sqlite.SQLiteDatabase.$$robo$$SQLiteDatabase_ab15_getThreadDefaultConnectionFlags(SQLiteDatabase.java:381)
at android.database.sqlite.SQLiteDatabase.getThreadDefaultConnectionFlags(SQLiteDatabase.java)
at android.database.sqlite.SQLiteProgram.$$robo$$SQLiteProgram_e9aa___constructor__(SQLiteProgram.java:58)
at android.database.sqlite.SQLiteProgram.(SQLiteProgram.java:41)
at android.database.sqlite.SQLiteStatement.(SQLiteStatement.java:31)
at android.database.sqlite.SQLiteDatabase.$$robo$$SQLiteDatabase_ab15_insertWithOnConflict(SQLiteDatabase.java:1467)
at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java)
at com.snapchat.android.database.table.ClearedChatIdsTable.insert(ClearedChatIdsTable.java:87)
at com.snapchat.android.database.table.ClearedChatIdsTable.insert(ClearedChatIdsTable.java:75)
at com.snapchat.android.database.table.ClearedChatIdsTable$1.run(ClearedChatIdsTable.java:68)
at java.lang.Thread.run(Thread.java:745)

Found 1 deadlock.
```