Does the Android Art Runtime Have the Same Method Limit Limitations as Dalvik

Does the Android ART runtime have the same method limit limitations as Dalvik?

The issue is not with the Dalvik runtime nor the DEX file format, but with the current set of Dalvik instructions. Specifically, the various method invocation methods, which look like this:

invoke-kind {vC, vD, vE, vF, vG}, meth@BBBB

B: method reference index (16 bits)

You can reference a very large number of methods in a DEX file, but you can only invoke the first 65536, because that's all the room you have in the method invocation instruction.

I'd like to point out that the limitation is on the number of methods referenced, not the number of methods defined. If your DEX file has only a few methods, but together they call 70,000 different externally-defined methods, you're going to exceed the limit.

One way to fix this is to add additional instructions that take wider method references. An approach called "jumbo opcodes" was implemented and released in Android 4.0 (ICS), but was never fully put into action, and was later removed from the tree. (I occasionally see posts here with error messages from "dx" that reference jumbo ops, or from developers who stumbled over them.)

Note this is not the problem solved by the Facebook hack. That's due to a fixed-size buffer for holding class/method/field meta-data. There's no method-specific limit there; you can blow out the buffer by having lots of fields.

My understanding is that the current implementation of ART handles the same set of instructions that Dalvik does, so the situation will be no different.

Do I need to code things differently for ART vs Dalvik?

ART is a different runtime for Android applications. All android apps run inside of a virtual machine, much like java code runs in the Java VM.

Classically, when you compiled an Android app, it would compile to Dalvik byte code, designed to run in the Dalvik runtime (virtual machine).

In Android Kitkat though, Google introduced a new experimental runtime called Android Runtime, or ART. This is a different virtual machine, a re-implementaton of the runtime for Android applications to help fix some of the fundamental flaws in the original design.

ART offers several advantages over Dalvik:

  • Ahead-of-time (AOT) compilation
  • Improved garbage collection
  • Development and debugging improvements
    • Support for sampling profiler
    • Support for more debugging features
    • Improved diagnostic detail in exceptions and crash reports

It should also help with things like the DEX limit.

As to your question, you do not need to do anything as a developer. Google has said plainly that "Dalvik must remain the default runtime or you risk breaking your Android implementations and third-party applications".

Google has announced at Google I/O 2014 that in the Android "L" release and beyond, that ART will replace Dalvik.

Does 64K method limitation in Android Dex include Private and Protected as well?

From the docs you've pasted - it doesn't qualify 'the total number of methods' with a specific visibility like 'public', because it includes all of them.

So the answer is all methods contribute towards the dex count, regardless of their visibility.

How to solve the issue with Dalvik compiler limitation on 64K methods?

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

How to shrink code - 65k method limit in dex

It looks like Google has finally implementing a workaround/fix for surpassing the 65K method limit of dex files.

About the 65K Reference Limit

Android application (APK) files contain
executable bytecode files in the form of Dalvik Executable (DEX)
files, which contain the compiled code used to run your app. The
Dalvik Executable specification limits the total number of methods
that can be referenced within a single DEX file to 65,536, including
Android framework methods, library methods, and methods in your own
code. Getting past this limit requires that you configure your app
build process to generate more than one DEX file, known as a multidex
configuration.

Multidex support prior to Android 5.0

Versions of the platform prior to Android 5.0 use the Dalvik runtime
for executing app code. By default, Dalvik limits apps to a single
classes.dex bytecode file per APK. In order to get around this
limitation, you can use the multidex support library, which becomes
part of the primary DEX file of your app and then manages access to
the additional DEX files and the code they contain.

Multidex support for Android 5.0 and higher

Android 5.0 and higher uses a runtime called ART which natively
supports loading multiple dex files from application APK files. ART
performs pre-compilation at application install time which scans for
classes(..N).dex files and compiles them into a single .oat file for
execution by the Android device. For more information on the Android
5.0 runtime, see Introducing ART.

See: Building Apps with Over 65K Methods


Multidex Support Library

This library provides support for building
apps with multiple Dalvik Executable (DEX) files. Apps that reference
more than 65536 methods are required to use multidex configurations.
For more information about using multidex, see Building Apps with Over
65K Methods.

This library is located in the /extras/android/support/multidex/
directory after you download the Android Support Libraries. The
library does not contain user interface resources. To include it in
your application project, follow the instructions for Adding libraries
without resources.

The Gradle build script dependency identifier for this library is as
follows:

com.android.support:multidex:1.0.+ This dependency notation specifies
the release version 1.0.0 or higher.


You should still avoid hitting the 65K method limit by actively using proguard and reviewing your dependencies.

Do private methods increase Dex Count in Android?

The 64k limit is a limit on the number of unique method references in a dex file. A method reference consists of a specific class name, the method name and the method prototype, and is created when you either invoke a method or declare/define/override a method.

So yes, defining a new private method will add a method reference to the dex file.


For more information, see: https://source.android.com/devices/tech/dalvik/dex-format.html and https://source.android.com/devices/tech/dalvik/dalvik-bytecode.html, which are the main references for the dex format.

The "method reference list" is a sorted list of method_id_items in the dex file. e.g. look for "method_ids" in the "File layout" section of dex-format.html. And further down the page, method_id_item is defined as consisting of a class reference, a method name and a method prototype.

The class_data_item section is used to define the methods and fields that are defined by the class. The "direct_methods" and "virtual_methods" lists are lists of indexes into the method_ids list - which requires that a reference for that method exists in the method_ids list.

And in dalvik-bytecode.html, the invoke-* instructions use a method index to refer the method to invoke.

Interestingly, the method reference list itself is defined with a 32-bit size value (search for "method_ids_size" in dex-format.html). So the list of method references itself can be as large as 4294967296 entries.

However, the problem comes when you need to reference any of these methods. The invoke-* instructions only use 16 bits to encode the method index.

Additionally, the method references in the class_data item can be up to the full 32 bits. So you could theoretically have definitions of methods past the 64k limit in a dex file, as long as you never actually tried to invoke them from within that dex file. But they could still be invoked from another dex file.

Using Art instead of Dalvik to compile

Of particular note is the suggestion of making a minSdkVersion 21 dev build - this allows you to generate multi-dex output incrementally in the new ART format, making for a much faster development iteration cycle (at least on Android 5.0 devices).

That's wrong and should read roughly

Of particular note is the suggestion of using Android Build Tools 21.1 and higher together with the Multidex Support Library - this allows you to use multiple dex files in the dex format which hasn't changed at all, making for unchanged development.

The problem of the dex format is that it can't contain more than 65536 methods. The solution is to simpliy split the output into multiple dex files. There are 2 problems we had in the past

  • the dx tool was not capable to produce multiple dex files
  • it's very complicated to use multiple dex files on a device since devices load only 1 dex file and the code in the other ones has to be loaded somehow manually.

Build tools 21 solve the first problem, you can simply generate multiple dex files by just adding the -multi-dex flag to the compile options.

The multidex support library solves the second problem. It tells those devices how to load additional dex files. And the ART runtime on Lollipop and above (4.4 had ART too but can't do the same) is capable of using multiple files without being told how to do so.

Also relevant is the official Building Apps with Over 65K Methods document.

Does the R.java file declarations consume spaces from the 64K limit?

The R class and its subclasses don't have normal methods, but they do typically have a no-op constructor method, and possibly also a static constructor method which is used to initialize some of the fields that can't be initialized statically in the dex file.

So, assuming you have roughly 10 classes counting the R class and its various subclasses (R.string, R.layout, etc.), you'll end up with about 10-20 additional method references.



Related Topics



Leave a reply



Submit