3

This all started with this error when running instrumentation tests:

java.lang.NoSuchMethodError: No static method closeQuietly(Ljava/net/ServerSocket;)V in class Lokhttp3/internal/Util; or its super classes (declaration of 'okhttp3.internal.Util' appears in /data/app/com.example-vKdPJoTLl49ntRbZfsRBqQ==/base.apk!classes2.dex)
at okhttp3.mockwebserver.MockWebServer$2.execute(MockWebServer.java:333)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)

I went looking into the generated test.apk to see what was present/missing in dex files.

First thing I noticed is that the test apk has two .dex files. Why? I'm not using multidex (and IIRC multidex doesn't work on test apks anyways). I then added up the two "referenced method counts" and sure enough I'm over the 65k limit. So is AGP auto-multi-dexing my test apk?

classes.dex classes2.dex

Furthermore I see the "missing" method in the first dex.

Why is it listed as a "reference" not a "defined" method? It's not like there is an OkHttp Util class provided by the framework.

In the initial crash, it said it can't find method in classes2.dex. Why is it looking in classes2.dex? Why not look in both?

I'm keeping everything in my test apk (using proguard but keeping everything) (maybe this explains the +65k ref methods). So why is this getting stripped/screwed with in the first place.

UPDATE:

It turns out this method was needed in my app .apk (not the test .apk). When I updated my proguard rules for the app apk everything worked. I still don't know why this class is needed in-app?

tir38
  • 9,810
  • 10
  • 64
  • 107

2 Answers2

0

java.lang.NoSuchMethodError:

No static method closeQuietly(java.net.ServerSocket) in class okhttp3.internal.Util;

method closeQuietly(java.net.ServerSocket) might not be in use.

to explicitly keep it:

-keep class okhttp3.internal.Util {
    public static void closeQuietly(java.net.ServerSocket);
}
Community
  • 1
  • 1
Martin Zeitler
  • 1
  • 19
  • 155
  • 216
  • I don't understand. Doesn't the crash I'm seeing mean the method is used? If its not in use as you suggest, how would keeping them make a difference? Why would I keep all three overloads of the `closeQuietly` method? – tir38 Nov 13 '18 at 16:44
  • @tir38 the constructor with the `ServerSocket` might not have been kept by `includedescriptorclasses` and that's why my example is a rule which should explicitly keep one more constructor. – Martin Zeitler Nov 14 '18 at 15:22
0

I don't know how I didn't know this but apparently multidex is enabled by default on API 21+

https://developer.android.com/studio/build/multidex#mdex-on-l

Therefore, if your minSdkVersion is 21 or higher multidex is enabled by default, and you do not need the multidex support library.

So yeah, this is normal. What might be happening is that the class is just not in the first dex file.

tir38
  • 9,810
  • 10
  • 64
  • 107