Чтобы получить ответы, которые мы должны ходить через .Dex Format. В нашем случае наиболее интересной является массив method_ids
:
список идентификаторов методов. Это идентификаторы для всех методов , на которые ссылается данный файл, независимо от того, указан ли он в файле. Этот список должен быть отсортирован, где определяющий тип (по type_id
индексом) является крупный заказ, имя метода (по string_id
индексом) является промежуточным порядка и способа-прототипа (по proto_id
индекса) является несовершеннолетним заказ. Список не должен содержать дубликатов записей.
Вне зависимости от того факта, что количество записей массива хранятся в виде 32-разрядного целого числа без знака (см method_ids_size
поля) на практике этого массив не может содержать более 65536
записи. Это связано с тем, что операнд method_id
команды dex invoke-xxxx
- это 16-битный объект и должен быть действительным индексом в method_ids
. В результате записи с индексами больше 65535
были бы недоступны по байт-коду. Все это приводит к известной проблеме «64K Methods».
Так, как говорят документы - method_ids
имеет по одной записи на каждый метод, определенный этим dex
, а также для внешних, которые передаются кодом определенных методов.
Следовательно, каждый раз, когда вы добавляете код, как:
public native void foo();
к одному из ваших классов - Вы получаете одну дополнительную запись в method_ids
. Это также относится к объявлениям методов abstract
. Затем, каждый раз, когда вы добавляете реализацию некоторого регулярного метода, как:
public void baz() {
/* ... */
}
вы получаете один новый рекорд для себя и записей baz()
для всех методов, на которые ссылается baz()
и не добавляются к method_ids
еще.
Исходный код не влияет на содержание dex
, так как все источники C/C++ скомпилированы в машинный код, который распространяется через файлы .so
. Они используют формат ELF, который имеет свои собственные ограничения и абсолютно независим от DEX.