2013-07-18 10 views
25

Dalvik hat diese bekannte Beschränkung auf die Anzahl der Methoden, die es in einer einzigen .dex Datei haben kann (etwa 65.536 von ihnen). Meine Frage ist, ob geerbte (aber nicht überschriebene) Methoden gegen dieses Limit zählen oder nicht.Bezahlen vererbte Methoden gegen das Dex-Methodenlimit in Android?

Um die Dinge konkret zu machen, nehme ich habe:

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

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

Für die Zwecke der 65.536 Verfahren zu begrenzen, hat diese Zählung als eine Methode hinzufügen oder 4 Hinzufügen? (Oder, denke ich, um die Dinge zu ihrer logischen Schlussfolgerung zu bringen, zählt das als 1 Methode oder 52 Methoden, wenn man bedenkt, dass java.lang.Object 12 Methoden mitbringt).

Als Hintergrund habe ich eine nicht-triviale Anzahl von generierten Klassen mit einigen Gemeinsamkeiten, und ich stoße auch gegen das Methodenlimit, also frage ich mich, ob es sich lohnt zu versuchen, einige davon zu abstrahieren in eine Klassenhierarchie, um Zeit zu gewinnen.

+1

Da Sie die Sichtbarkeit der Methode ändern können, wäre es nicht sinnvoll, dass sie alle zählen müssten? [Siehe hier für Dex-Format] (http://www.retrodev.com/android/dexformat.html). –

+2

Der Retrodev-Link ist ein wohlüberholtes Reverse-Engineering einer Vorabversion des Dex-Dateiformats. Probieren Sie für eine autoritativere und aktuellere Quelle aus. – danfuzz

+0

404 auf dex-format.html –

Antwort

15

Eine vererbte aber nicht überschriebene Methode zählt nur gegen die Methode Grenze, wenn es jemals referenziert wird (genannt).

In Ihrem Beispiel, lassen Sie uns sagen, dass Sie das folgende Stück Code

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

In diesem Fall haben Sie beziehen sich auf Foo.foo(), die bereits eine Referenz hat, aufgrund der expliziten Definition. Unter der Annahme, dass diese 5 Klassen die einzigen Klassen in der Dex-Datei sind, haben Sie insgesamt 2 Methodenreferenzen *. Eine für main.main (String []) und eine für Foo.foo(). Statt

, sagen wir, Sie den folgenden Code

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(); 
    } 
} 

In diesem Fall haben, da die Foo-Methode für jede Unterklasse tatsächlich Bezug genommen wird, werden sie gegen Ihre Methode Limit zählen. Ihre Dex-Datei enthält 5 Methodenreferenzen *.

  • main.main (String [])
  • Foo.foo()
  • A.foo()
  • B.foo()
  • C.foo()

* Diese Anzahl ist nicht ganz genau, berücksichtigt nicht die Konstruktormethoden, die hinter den Kulissen zu jeder Klasse hinzugefügt werden. Jeder Konstruktor ruft den Konstruktor seiner Superklasse auf, daher haben wir auch einen Verweis auf den Object-Konstruktor für insgesamt 6 zusätzliche Methodenreferenzen in jedem Fall, was eine Methodenzahl von 8 bzw. 11 ergibt.


Im Zweifelsfall können Sie verschiedene Szenarien ausprobieren und baksmali des rohe Dump Funktion nutzen, was die Methodenliste in der dex-Datei tatsächlich enthält.

z.B.

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

Und dann, in der Dump-Datei, suchen Sie nach "method_id_item Abschnitt". Dies ist die Liste der Methodenreferenzen, auf die das 64k-Limit angewendet wird.

+2

Nicht auch Konstruktoren als Methodenreferenzen? Würde das nicht die Anzahl der Methodenreferenzen in Ihren Beispielen erhöhen? – snrlx

+0

@nvrmnd, ja. Das ist ein guter Punkt. Ich werde die Antwort entsprechend aktualisieren. Vielen Dank! – JesusFreke

+0

Haben Methoden innerhalb von .SO-Dateien oder JNI-Code jemals dieses Limit? – skygeek