2013-07-18 24 views
25

Dalvik對單個.dex文件中的方法數量(約65,536個)有着衆所周知的限制。我的問題是,繼承(但未覆蓋)方法是否違反此限制。繼承的方法是否違反Android中的Dex方法限制?

爲了使事情具體,假設我有:

public class Foo { 
    public int foo() { 
    return 0; 
    } 
} 

public class A extends Foo { } 
public class B extends Foo { } 
public class C extends Foo { } 

對於65536方法限制的目的,這是否算不算添加一個方法,或添加4? (或者,我猜,要把事情弄清楚,這是否算作1種方法或52種方法,考慮到java.lang.Object也帶來了12種方法)。

作爲背景,我得到了一些具有一定共性的生成類的不平凡數目,並且我也碰到了方法限制,所以我想知道是否值得嘗試抽象其中的一些爲了購買一些時間而進入一個階級階層。

+1

由於您可以更改方法的可見性,因此需要對它們全部進行計數是否合理? [在這裏查看dex格式](http://www.retrodev.com/android/dexformat.html)。 –

+2

retrodev鏈接是對dex文件格式的預發佈版本的可悲的過時的反向工程。嘗試以獲得更權威和最新的源代碼。 – danfuzz

+0

404 dex-format.html –

回答

15

如果曾經被引用(調用),則繼承但未覆蓋的方法僅計入方法限制。

在您的例子,假設你有下面的一段代碼

public class main { 
    public static void main(String[] args) { 
     Foo foo = new A(); 
     foo.foo(); 
    } 
} 

在這種情況下,你是指Foo.foo(),它已經有一個參考,由於明確的定義。假設這5個類是dex文件中唯一的類,那麼總共有2個方法引用*。一個用於main.main(String []),另一個用於Foo.foo()。

相反,假設你有下面的代碼

public class main { 
    public static void main(String[] args) { 
     A a = new A(); 
     a.foo(); 

     B b = new B(); 
     b.foo(); 

     C c = new C(); 
     c.foo(); 
    } 
} 

在這種情況下,由於每個子類foo的方法實際上是引用,它們會佔用你的方法限制。你的dex文件將有5個方法引用*。

  • main.main(字符串[])
  • Foo.foo()
  • A.foo()
  • B.foo()
  • C.foo()

* 這個計數並不十分準確,它沒有考慮添加到幕後每個類的構造函數方法。每個構造函數都調用它的超類的構造函數,所以我們也引用了Object構造函數,每種情況下總共有6個附加的方法引用,分別給出了8和11的方法計數。


如果有疑問,你可以嘗試在各種場合,利用baksmali的原始轉儲功能,看看在DEX文件的方法列表實際上包含。

例如

javac *.java 
dx --dex --output=temp.dex *.class 
baksmali -N -D temp.dump temp.dex 

,然後在轉儲文件,尋找 「method_id_item節」。這是64k限制適用的方法引用列表。

+2

不要構造函數也算作方法引用嗎?那麼這不會增加示例中方法引用的數量嗎? – snrlx

+0

@nvrmnd,是的。這是一個好點。我會相應地更新答案。謝謝! – JesusFreke

+0

.SO文件或JNI代碼中的方法是否會計入此限制? – skygeek