Reputation: 227
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.
Upvotes: 4
Views: 625
Reputation: 20282
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.
Upvotes: 6
Reputation: 1007349
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.
Upvotes: 2