在Docker容器中运行时零星的Robolectrictesting失败

我正试图将我们的Android团队转移到基于云的CI解决scheme上。 公司内的其他部门已经完成了这项任务,并且我们有一个企业团队许可证,利用安装了Docker的Linux EC2。 整个公司都使用TC,虽然CircleCI等是很好的select,但我正在探索使用我们自己的TC解决scheme。

到目前为止,它已经很好,并使用Amazon ECR我们托pipe了我们的Docker镜像,其中安装了所需的Android SDK,Gradle和Java组件。 我们的构build大部分时间都是好的,但是由于运行一些Robolectrictesting案例时出现错误,我们的实际本地代理仍然失败。 有没有人见过这个?

java.lang.NoClassDefFoundError: java.lang.NoClassDefFoundError: Landroid/content/res/Resources; java.lang.NoClassDefFoundError: Landroid/content/res/Resources; at java.lang.Class.getDeclaredFields0(Native Method) at java.lang.Class.privateGetDeclaredFields(Class.java:2583) at java.lang.Class.getDeclaredFields(Class.java:1916) at org.junit.runners.model.TestClass.getSortedDeclaredFields(TestClass.java:77) at org.junit.runners.model.TestClass.scanAnnotatedMembers(TestClass.java:70) at org.junit.runners.model.TestClass.<init>(TestClass.java:57) at org.junit.runners.ParentRunner.createTestClass(ParentRunner.java:88) at org.junit.runners.ParentRunner.<init>(ParentRunner.java:83) at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:65) at org.robolectric.internal.SandboxTestRunner$HelperTestRunner.<init>(SandboxTestRunner.java:242) at org.robolectric.RobolectricTestRunner$HelperTestRunner.<init>(RobolectricTestRunner.java:467) at org.robolectric.RobolectricTestRunner.getHelperTestRunner(RobolectricTestRunner.java:319) at org.robolectric.internal.SandboxTestRunner$2.evaluate(SandboxTestRunner.java:188) at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:109) at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:36) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.robolectric.internal.SandboxTestRunner$1.evaluate(SandboxTestRunner.java:63) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:114) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:57) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:66) at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32) at org.gradle.internal.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:109) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:377) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54) at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.ClassNotFoundException: couldn't load android.content.res.Resources at org.robolectric.internal.bytecode.SandboxClassLoader.getByteCode(SandboxClassLoader.java:165) at org.robolectric.internal.bytecode.SandboxClassLoader.maybeInstrumentClass(SandboxClassLoader.java:108) at org.robolectric.internal.bytecode.SandboxClassLoader.findClass(SandboxClassLoader.java:101) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 48 more Caused by: java.util.zip.ZipException: invalid LOC header (bad signature) at java.util.zip.ZipFile.read(Native Method) at java.util.zip.ZipFile.access$1400(ZipFile.java:60) at java.util.zip.ZipFile$ZipFileInputStream.read(ZipFile.java:717) at java.util.zip.ZipFile$ZipFileInflaterInputStream.fill(ZipFile.java:419) at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:158) at java.io.FilterInputStream.read(FilterInputStream.java:133) at java.io.FilterInputStream.read(FilterInputStream.java:107) at org.robolectric.util.Util.copy(Util.java:21) at org.robolectric.util.Util.readBytes(Util.java:38) at org.robolectric.internal.bytecode.SandboxClassLoader.getByteCode(SandboxClassLoader.java:163) ... 52 more 

一个粗略的谷歌指向腐败jar子,但这使我感到困惑,因为Docker环境是“新鲜的”,并在每个生成(当caching未启用时,它不是)。 与这个堆栈相关的Robolectrictestingconfiguration是;

 @Config(constants = BuildConfig.class, sdk = 21) @RunWith(CustomRobolectricRunner.class) public class ResourcesTest {...} 

可能不是最好的testing,但是更多的testing失败了。 Docker镜像有Android SDK 21(正如另一篇文章中提到的那样)。

(a)如何certificate或反驳它是“损坏的jar子”(我认为是Robolectricjar子?)和(b)采取补救措施?

正在使用的Dockerfile可以在这里查看。

所以,我自己的CircleCI 2.0版本在解决scheme从testing版本gradle后开始出现类似的错误,并且在诊断和修正这个版本的时候,它让我回答这个问题。 这是一个记忆问题。 容器内存不足,不能正常运行。 还有一些其他的信号是这样,我已经开始使用JAVA_OPTS / GRADLE_OPTS设置。 最后指定明确不使用守护进程并控制JVM的叉号解决了它;

 --no-daemon --max-workers 2 

这个线程还有Docker + Java + Gradle + Android会遇到的内存问题。 有点痛苦,但值得。