I was doing code review and told someone to remove a private method that was only used once. They said that it didn't matter since dex count wouldn't get increased by private method references. Is this true? I wasn't able to find an answer with a simple google search.
2 Answers
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.

- 19,784
- 5
- 65
- 68
They said that it didn't matter since dex count wouldn't get increased by private method references. Is this true?
I am going to assume that you are worried about the 64K DEX method reference limit. In this case, the reviewee is correct: whether this code is wrapped in a method or not has no impact.
The "method reference" of relevance in "the 64K DEX method reference limit" refers to one DEX referring to a method in another DEX. In conventional Android projects, there are two DEXes of relevance: yours and the framework's. How many methods your own code is divided into does not matter. What matters is how many methods of the framework you are referencing (where by "you" I mean your code plus any library modules and JARs you are including).
When you enable multidex on a project, you are splitting your code into more than one DEX file. Each can refer to 64K methods in other DEX files. Here, though, "other DEX files" refers to both the framework DEX and the other DEX files of your own app created by multidex. However, AFAIK, multidex does not split a single class across DEX files. Since this is a private
method, it could only be referenced by another method in the same class, and so both methods should be in the same DEX file. Hence, even in this case, having the private method would not add to the DEX method reference count of the DEX containing that method.
Based on JesusFreke's comments, I retract my original position. Defining a private method will increase the DEX method reference count.
That being said, on a one-off basis, worrying about inlining an individual method, just to reduce the DEX method reference count, is premature optimization IMHO. If you are bumping up towards the DEX method reference limit (and Android Studio's APK Analyzer can help you determine this), worry first about "trimming the fat" in libraries. Otherwise, worry about maintainability. Now, it may be that removing the method actually helps with that (e.g., it's a two-line method, not worth pulling out separately). But if there is maintainability value in having the method, leave it alone.

- 986,068
- 189
- 2,389
- 2,491
-
I understand part of where you're going but I'll need a little more clarification. I read in another post that a class with 65536 empty methods would still hit the dex limit, how does dex affect this? Going by this logic, this class should be in it's own dex file and not have any references. – Tiensi Nov 22 '16 at 18:56
-
@Tiensi: "I read in another post that a class with 65536 empty methods would still hit the dex limit" -- I am not aware that this is the case. Though, in truth, I suspect that a class with 64K methods might fail to compile, as there's probably some compiler limit that you'll hit first. "Going by this logic, this class should be in it's own dex file and not have any references" -- correct. – CommonsWare Nov 22 '16 at 18:57
-
@CommonsWare "The method reference of relevance ... refers to one DEX referring to a method in another DEX" This is incorrect. There is no difference between an intra-dex and an inter-dex method reference. But beyond that, just the fact that the method (private or otherwise) is defined in a dex file adds a method reference for that method to the dex file. – JesusFreke Nov 22 '16 at 23:11
-
@JesusFreke: OK. How can I reconcile what you're saying with what Andy Fadden wrote in that SO answer that I linked to from my answer? – CommonsWare Nov 22 '16 at 23:15
-
I think you're misreading what he said. It looks like you're reading more into the paragraph that starts with "I'd like to point out that the limitation is on the number of methods referenced, not the number of methods defined.". This was meant only as an example to illustrate the fact that methods that are referenced from external dex files are *also* included in the list of method references. The set of "methods referenced" and "methods defined" are not mutually exclusive -- the difference is set of methods referenced from external dex files. – JesusFreke Nov 22 '16 at 23:20
-
A relevant quote from https://source.android.com/devices/tech/dalvik/dex-format.html - "method identifiers list. These are identifiers for all methods referred to by this file, whether defined in the file or not. " – JesusFreke Nov 22 '16 at 23:31