Считаются ли унаследованные методы ограничением метода Dex в Android?

У Dalvik есть хорошо известное ограничение на количество методов, которое может быть в одном .dex файле (около 65 536 из них). Мой вопрос заключается в том, учитываются ли унаследованные (но не переопределенные) методы в этом ограничении или нет.

Чтобы сделать вещи конкретными, предположим, что у меня есть:

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

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

С учетом ограничения в 65 536 методов считается ли это добавлением одного метода или добавлением 4 методов? (Или, я думаю, чтобы довести все до логического завершения, это считается за 1 метод или 52 метода, учитывая, что java.lang.Object также приносит 12 методов).

В качестве фона у меня есть нетривиальное количество сгенерированных классов с некоторой общностью, и я также сталкиваюсь с ограничением метода, поэтому мне интересно, стоит ли пытаться абстрагировать некоторые из них в класс иерархии, чтобы выиграть время.


person Adrian Petrescu    schedule 18.07.2013    source источник
comment
Поскольку вы можете изменить видимость метода, разве не имеет смысла подсчитывать их все? см. здесь формат dex.   -  person Sotirios Delimanolis    schedule 18.07.2013
comment
Ссылка Retrodev ведет к крайне устаревшему реверс-инжинирингу предварительной версии формата файла dex. Попробуйте ‹source.android.com/devices/tech/dalvik/dex- format.html› как более авторитетный и актуальный источник.   -  person danfuzz    schedule 19.07.2013
comment
404 на dex-format.html   -  person Jon Shemitz    schedule 25.09.2013
comment
@JonShemitz: Просто удалите завершающий > из строки URL. Он должен был добавить пробел там.   -  person Adrian Petrescu    schedule 25.09.2013
comment
Хорошо, спасибо. source.android.com/devices/tech/dalvik/dex-format. html работает.   -  person Jon Shemitz    schedule 26.09.2013


Ответы (1)


Унаследованный, но не переопределенный метод учитывается в ограничении методов только в том случае, если на него когда-либо ссылаются (вызывают).

В вашем примере допустим, что у вас есть следующий фрагмент кода

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 (Строка [])
  • Фу.фу()
  • А.фу()
  • Б.фу()
  • C.foo()

* Этот подсчет не совсем точен, он не учитывает методы конструктора, которые добавляются к каждому классу за кулисами. Каждый конструктор вызывает конструктор своего суперкласса, поэтому у нас также есть ссылка на конструктор Object, всего 6 дополнительных ссылок на методы в каждом случае, что дает количество методов 8 и 11 соответственно.


Если вы сомневаетесь, вы можете опробовать различные сценарии и использовать функцию необработанного дампа baksmali, чтобы увидеть, что на самом деле содержит список методов в файле dex.

e.g.

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

А затем в файле дампа ищем раздел «method_id_item». Это список ссылок на методы, к которым применяется ограничение в 64 КБ.

person JesusFreke    schedule 18.07.2013
comment
Разве конструкторы тоже не считаются ссылками на методы? Так не увеличит ли это количество ссылок на методы в ваших примерах? - person snrlx; 19.07.2013
comment
@nvrmnd, да. Это хороший момент. Я обновлю ответ соответственно. Спасибо! - person JesusFreke; 19.07.2013
comment
Учитываются ли когда-либо методы внутри файлов .SO или кода JNI до этого предела? - person skygeek; 30.10.2014
comment
В методе JNI нет ничего особенного с точки зрения dex, кроме того факта, что он имеет собственный флаг доступа и не имеет реализации. Так что да, список идентификаторов методов в файле dex включает все методы jni, объявленные (или вызываемые) в файле dex. - person JesusFreke; 30.10.2014