java.lang.NoSuchFieldError: Companion when in a kotlin only module / kotlin("jvm") plugin
See original GitHub issueI have a modularised project, where the api layer is separated into its own module. As this has no dependency on the Android SDK, I have made it a kotlin only module. This has the kotlin jvm plugin as shown below in the build file. This results in a java.lang.NoSuchFieldError: Companion error when I try to use MockWebServer (only this, everything else works fine).
Using kotlin dsl in the build file, the build.gradle.kts file looks like this:
plugins {
kotlin("jvm")
kotlin("kapt")
}
dependencies {
implementation(kotlin("stdlib"))
implementation("com.squareup.retrofit2:retrofit:2.7.0")
implementation("com.squareup.retrofit2:converter-moshi:2.7.0")
implementation("com.squareup.moshi:moshi-kotlin:1.9.2")
implementation("com.squareup.okhttp3:logging-interceptor:4.4.0")
testImplementation("com.squareup.okhttp3:mockwebserver:4.4.0")
testImplementation("junit:junit:4.13")
kapt("com.squareup.moshi:moshi-kotlin-codegen:2.7.0")
// There are various other libraries, but I'm including the only ones I feel are relevant
// in case my problem is to do with conflicting versions of libraries
}
And here is the snippet of my unit test. The line where I instantiate MockWebServer() fails with the NoSuchFieldError: Companion:
class LoginServiceTest {
private val mockWebServer: MockWebServer = MockWebServer()
And the stack trace:
java.lang.NoSuchFieldError: Companion
at okhttp3.internal.Util.<clinit>(Util.kt:69)
at okhttp3.mockwebserver.MockWebServer.<init>(MockWebServer.kt:101)
at com.mobilleo.data.webapi.service.core.user.LoginServiceTest.<init>(LoginServiceTest.kt:29)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:250)
at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:260)
at org.junit.runners.BlockJUnit4ClassRunner$2.runReflectiveCall(BlockJUnit4ClassRunner.java:309)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Process finished with exit code 255
After various experiments, I have discovered the following:
- Rolling back the okhttp3 libraries to version 3.x.x removes this error, but then I lose a lot of needed features of okhttp3 that I need, for interceptors, authenticators etc. etc.
- I believe retrofit uses okhttp3 3.14, however prior to me trying to use MockWebServer, I had no issue with the okttp3:logging-interceptor using 4.4.0
- When I switch the module to a kotlin android module, it works as expected. So changing build file to the following:
Working build.gradle.kts:
plugins {
id("com.android.library")
kotlin("android")
kotlin("kapt")
}
android {
compileSdkVersion(29)
// etc. etc. Android config, that all seems a bit pointless just to get MockWebServer working
My instinct tells me it’s some difference between the way kotlin android compiles the Kotlin, with Companion objects or static methods etc., compared with when just using the kotlin jvm compiler, but I confess to not knowing enough about what happens ‘under the hood’ with all this.
Issue Analytics
- State:
- Created 4 years ago
- Comments:6 (1 by maintainers)
Top GitHub Comments
@vinnorman I ran into
java.lang.NoSuchFieldError: Companion
as well. My situation was that I was using a certain version of okhttp in my project, but I have another dependency that internally it was using a different version of okhttp (so 2 different versions). I ended up using gradle’sdependencyInsight
to track down the different versions.Usage:
cd
into your subproject and run:gradle -q dependencyInsight --dependency okhttp3
Sample Output:
com.squareup.okhttp3:okhttp:3.10.0 -> 4.4.1
From there you can try excluding a dependency or forcing a particular version in your gradle file
I get the same error adding this dependency:
implementation("com.squareup.okhttp3:okhttp:4.4.0")
Also doesn’t explain why it works on kotlin(“android”) and not kotlin(“jvm”).Any ideas?