Android 64k method limit in Xamarin

Last week, the nightly build of my Android project failed all of a sudden. It was apparently related to the 64k method limit than Android poses for DEX-files. I wasn’t aware how much impact the NuGet packages have on that method count. I want to show you my journey to resolving this issue.

64k method limit

Android apps run on Dalvik or ART (Android Runtime), depending on the Android version you use. Dalvik has a few limitations, including the 64k method limit. In a DEX-file (which stands for Dalvik Executable), you can only reference the first 65,536 methods. If you exceed that limit you get the following build error in Xamarin:

Tool exited with code: 2.
/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/Android/Xamarin.Android.Common.targets : error : trouble writing output: Too many field references: 74105; max is 65536.

My app itself was only consuming 2500 methods of the total. So the rest was added through NuGet packages. The biggest method consumers were the Android support libraries (40503 methods), Google for Analytics (19930 methods) and Firebase for notifications (7258 methods).

ProGuard

You use ProGuard to remove unused classes, fields and methods. So it can be used to work around the 64k limit. It essentially shrinks your app.

You can enable ProGuard at the project settings:

The ProGuard option can be found in the Android Build section of the Android project settings

Click to enlarge

There is a quirk though: if you enable it and build again, you are most likely to run into this exception:

java.io.IOException: Can’t read [/Library/Frameworks/Xamarin.Android.framework/Versions/7.2.0-7/lib/xbuild-frameworks/MonoAndroid/v7.0/mono.android.jar] (Can’t process class [android/app/ActivityTracker.class] (Unsupported class version number [52.0] (maximum 51.0, Java 1.7)))

Updating ProGuard

Update: as mentioned in the comments, updating ProGuard is no longer required since Xamarin.Android v7.3 was released as part of the Xamarin release 15.2. It now bundles its own up-to-date copy of ProGuard (v5.3.2). Xamarin.Android v7.3 has been released as a stable on May 10th 2017.

This is caused by Xamarin.Android v7.0 (see the release notes), which requires JDK 1.8 if you target Android API 24+. So, the fix is to update ProGuard to the latest version on your build machine.

You can find ProGuard at the Android SDK location. You can find the SDK location in Xamarin Studio under Preferences > Projects > SDK Locations > Android. On my MacOS environment, the SDK is found here:

/Users/<username>/Library/Developer/Xamarin/android-sdk-macosx

At that location, in the tools directory you can find proguard. Simply rename the proguard directory and replace it with the contents of the latest version of ProGuard that you can find on Sourceforge.

Multi-Dex to the rescue

In case ProGuard doesn’t get you far enough, you can enable Multi-Dex in the project settings. It splits up the DEX-files, so this prevents them from going over the 64k limit.

You can enable Multi-Dex in the project settings, at the same location where you found ProGuard:

The Multi-Dex option can be found in the Android Build section of the Android project settings

Click to enlarge

Keep in mind that you should first try to resolve the issue with ProGuard. Only enable Multi-Dex if you really need to. This is a warning that is also shown in the info icon in Xamarin Studio.

TL;DR

When you run into the 64k limit, you can use ProGuard and Multi-Dex to resolve the issue. Make sure to update ProGuard when you use Xamarin.Android 7.2 or lower and target API level 24+.

Share on social media
Share on FacebookTweet about this on TwitterShare on LinkedIn
  • I think newer versions of Xamarin distributes its own version of ProGuard so you don’t need to upgrade the one bundled with the Android SDK anymore.

    • Tim Klingeleers

      Hi Tomasz, thanks for commenting.
      You are correct that Xamarin Android 7.3 now bundles its own copy of ProGuard. This has just crossed my post I guess (stable release date seems to be May 10th). Release notes for version 7.3 can be found here. I’ll update the post accordingly!