27

My team and I have inherited a large Android project from another team. The whole application with all the included libraries is reported to have around 35000 methods. We now have the task to implement a new service in the app where we need to use Protocol Buffers.

The problem is that the generated .jar file with all the required .proto files creates another couple of 35000 methods, that's 70000 methods. And if you are not aware, the Android compiler has a limitation of 65536 methods per .dex file. We are clearly over that limit and we are getting the following error trying to compile the app:

Unable to execute dex: method ID not in [0, 0xffff]: 65536
Conversion to Dalvik format failed: Unable to execute dex: method ID not in [0, 0xffff]: 65536

Yes, the application architecture should probably be restructured but that will take time. And for now we are trying to figure out a solution to work around this problem temporarily.

Any suggestions?

rfgamaral
  • 16,546
  • 57
  • 163
  • 275
  • If your app contains that many methods (and you can't get rid of some of them) the solution will probably have to be splitting up the app into smaller parts that can be built into separate dex files. See [this blogpost](http://android-developers.blogspot.se/2011/07/custom-class-loading-in-dalvik.html) for an example of how to do this. – Michael Mar 15 '13 at 16:10
  • The Facebook team just posted a message regarding this exact issue, the other day. https://www.facebook.com/notes/facebook-engineering/under-the-hood-dalvik-patch-for-facebook-for-android/10151345597798920 – Rawkode Mar 15 '13 at 16:07
  • 2
    @Rawkode: the Facebook issue was due to an undersized "LinearAlloc" buffer in older versions of Android (froyo, gingerbread). The 64K method reference limit is baked into the Dalvik instructions themselves. – fadden Mar 15 '13 at 22:42
  • See this post [http://stackoverflow.com/questions/15209831/unable-to-execute-dex-method-id-not-in-0-0xffff-65536][1] [1]: http://stackoverflow.com/questions/15209831/unable-to-execute-dex-method-id-not-in-0-0xffff-65536 – sonida Nov 20 '14 at 19:56

7 Answers7

12

You can use another DEX file. This is how you do it:

http://android-developers.blogspot.co.il/2011/07/custom-class-loading-in-dalvik.html

Udinic
  • 3,014
  • 2
  • 25
  • 32
  • 4
    Here is a script for counting the number of methods in each jar: https://gist.github.com/toms972/c83504df2da1176a248a – Tom Susel Jul 28 '14 at 09:14
  • 1
    The linked post is a bit outdated, it shows how to load multiple DEX files in an Ant based project. It also uses the DexClassLoader directly, a thing which is no longer required since android.support.multidex helps you with that and it's available in the support library (revision 21). Detailed explanation of how to integrate MultiDex into your app is here: https://www.contentful.com/blog/2014/10/30/android-and-the-dex-64k-methods-limit/ – woot Oct 30 '14 at 14:03
  • similar to @TomSusel script, we wrote a small gradle plugin that gives you a deeper insight on your method count and where it comes from on each build - https://github.com/KeepSafe/dexcount-gradle-plugin – philipp Jul 31 '15 at 16:27
7

Enable Proguard (http://developer.android.com/tools/help/proguard.html) to remove unused methods. The protobuf generator creates thousands of methods that are never actually used.

Micro-protobuffers (https://code.google.com/p/micro-protobuf/) may also be useful.

fadden
  • 51,356
  • 5
  • 116
  • 166
  • 1
    I've been looking into using proguard for this but I'm not sure how to enable it for debug/run configuration builds within Eclipse. Any hints on this? – rfgamaral Mar 17 '13 at 14:53
  • There are some posts on stackoverflow that may be helpful, such as http://stackoverflow.com/questions/4732656/enabling-proguard-in-eclipse-for-android . – fadden Mar 17 '13 at 16:02
  • 4
    I can't seem to find anything on that question that mentions using proguard with the debug/run configurations withing Eclipse... – rfgamaral Mar 17 '13 at 16:22
4

Square had similar issues and they built Wire to deal with the method explosion caused by protobufs. They claim to have killed 10,000 methods.

Abhay Buch
  • 4,548
  • 1
  • 21
  • 26
4

In versions of Google Play services prior to 6.5, you had to compile the entire package of APIs into your app. In some cases, doing so made it more difficult to keep the number of methods in your app (including framework APIs, library methods, and your own code) under the 65,536 limit.

From version 6.5, you can instead selectively compile Google Play service APIs into your app. For example, to include only the Google Fit and Android Wear APIs, replace the following line in your build.gradle file:

compile 'com.google.android.gms:play-services:6.5.87'

with these lines:

compile 'com.google.android.gms:play-services-fitness:6.5.87'
compile 'com.google.android.gms:play-services-wearable:6.5.87'

for more reference, you can click here

akshay
  • 5,811
  • 5
  • 39
  • 58
1

If this is the first use of Protocol buffers, you could look at alternative JavaME implementations i.e.

there are others listed in Third party add ons. If have not used any of them, but they seem to be smaller and do not have all the methods created by the standard protocol buffers.

Bruce Martin
  • 10,358
  • 1
  • 27
  • 38
1

We've recently added Nano Protobufs to Android which significantly reduces the number of methods generated.

0

If you are using eclipse this is the easiest work around Click Here!

mboy
  • 744
  • 7
  • 17