6

A sample app for library has ~67k methods. It has multidex enabled to overcome the 65k method limit. Unfortunately with multidex enabled the app crashes on VerifyError when trying to inject EndpointAdapter in main activity.

This issue doesn't occur when the app is proguarded and the multidex is disabled, so it must be caused by multidex and Dagger 1 problems.

I'm sure EndpointAdapter is in the main dex file, but some classes generated by Dagger are located in the second dex file generated by multidex. This issue occurs on devices with API < 21 (eg. on genymotion with KitKat 4.4.4).

Any idea why it crashes with VerifyError?

FATAL EXCEPTION: main
Process: pl.toro.libsample.debug, PID: 11775
java.lang.VerifyError: pl/toro/lib/network/EndpointAdapter
    at java.lang.Class.getDeclaredConstructors(Native Method)
    at java.lang.Class.getDeclaredConstructors(Class.java:574)
    at dagger.internal.loaders.ReflectiveAtInjectBinding.getConstructorsForType(ReflectiveAtInjectBinding.java:232)
    at dagger.internal.loaders.ReflectiveAtInjectBinding.create(ReflectiveAtInjectBinding.java:168)
    at dagger.internal.FailoverLoader.getAtInjectBinding(FailoverLoader.java:74)
    at dagger.internal.Linker.createBinding(Linker.java:224)
    at dagger.internal.Linker.linkRequested(Linker.java:141)
    at dagger.ObjectGraph$DaggerObjectGraph.getInjectableTypeBinding(ObjectGraph.java:309)
    at dagger.ObjectGraph$DaggerObjectGraph.inject(ObjectGraph.java:279)
    at pl.toro.lib.app.BaseApplication.inject(BaseApplication.java:135)
    ...

Here's output of the MultiDex tag

VM with version 1.6.0 does not have multidex support
install
MultiDexExtractor.load(/data/app/pl.toro.libsample.debug-1.apk, false)
Detected that extraction must be performed.
Extraction is needed for file /data/data/pl.toro.libsample.debug/code_cache/secondary-dexes/pl.toro.libsample.debug-1.apk.classes2.zip
Extracting /data/data/pl.toro.libsample.debug/code_cache/secondary-dexes/pl.toro.libsample.debug-1.apk.classes-1477675005.zip
Renaming to /data/data/pl.toro.libsample.debug/code_cache/secondary-dexes/pl.toro.libsample.debug-1.apk.classes2.zip
Extraction success - length /data/data/pl.toro.libsample.debug/code_cache/secondary-dexes/pl.toro.libsample.debug-1.apk.classes2.zip: 187777
load found 1 secondary dex files
install done

EDIT

I've switched to Dagger 2 and this issue is resolved as of now. Dagger 2 no longer uses reflection which is the major factor of this issue.

tomrozb
  • 25,773
  • 31
  • 101
  • 122
  • Does EndpointAdapter have a constructor that takes a parameter in the secondary dex? Also, can you confirm that this error happens after the classloader is patched? – Jeff Bowman Aug 06 '15 at 22:59
  • I'll have to check it. It have `@Inject` annotated constructor with 2 dependencies but I'm not sure in which dex the dependencies are. By 'patched' you mean after the MultiDex is initialized and prints "install done" log? – tomrozb Aug 07 '15 at 07:47
  • Yeah, that's what I'm checking, that Multidex finished successfully. Last question, what version of the Android SDK are you using? – Jeff Bowman Aug 07 '15 at 17:18
  • MultiDex installs without problems I think, I'll attach full output of MultiDex tag to the question soon. I'm targeting API 22, but the min SDK is set to 15. – tomrozb Aug 09 '15 at 09:54
  • Could it be part of the [annotation resolution issue on line 56 here](https://android.googlesource.com/platform/dalvik/+blame/6e28e4323f0cb0df9caeaaf603399af0c35c840e/dx/src/com/android/multidex/MainDexListBuilder.java)? [This bug here](http://code.google.com/p/android/issues/detail?id=78144) describes the error, with a verification-related (but not identical) trace. – Jeff Bowman Aug 09 '15 at 17:34
  • I'm not using the flag mentioned on line 56 of the file. Finally I've switched to Dagger 2 and the issue is resolved as of now. I'm sure there's some mix of problems between reflection (used by Dagger 1) and MultiDex which has no idea that some classes are needed in the main dex, because these classes are used by reflection. Thanks Jeff for help. – tomrozb Aug 09 '15 at 21:49

1 Answers1

0

As pointed out in this blog post[1], are you creating the dagger graph after installing the multi-dex. So in MultiDexApplication#attachBaseContext after the call to super (or calling MultiDex.install() yourself).

[1] https://developers.soundcloud.com/blog/congratulations-you-have-a-lot-of-code-remedying-androids-method-limit-part-2

Jeroen
  • 3,399
  • 1
  • 22
  • 25
  • Sorry but I don't understand. What after call to super? – tomrozb Oct 12 '15 at 11:34
  • Sorry, if you subclassed `MultiDexApplication` then you need to create the Dagger graph in `attachBaseContext` after you called `super.attachBaseContext()`. Does that make sense? – Jeroen Oct 13 '15 at 03:08
  • Are you sure? Is it called after `onCreate` or before? I'm not using Dagger 1 any more so we need somebody else to confirm this solves the problem. – tomrozb Oct 13 '15 at 20:31
  • 1
    Hmm, I think you are right. attachBaseContext() is always called before onCreate. So it seems my answer is wrong. – Jeroen Oct 13 '15 at 22:22