Android runtime source code

Как устроен билд APK файла внутри

Процесс создания APK и компиляции кода

Рассматриваемые темы

  • Архитектура процессоров и необходимость для виртуальной машины
  • Понимание Java виртуальной машины
  • Компиляция исходного кода
  • Виртуальная машина Андроид
  • Процесс компиляции в .dex файл
  • ART против Dalvik
  • Описание каждой части билд процесса
  • Исходный код
  • Файлы ресурсов
  • AIDL файлы
  • Модули библиотек
  • AAR библиотеки
  • JAR библиотеки
  • Android Asset Packaging Tool
  • resources.arsc
  • D8 и R8
  • Dex и Multidex
  • Подписывание APK файла
  • Ссылки

Понимание флоу процесса билда APK файла, среда исполнения и компиляция кода
Этот пост нацелен быть отправной точкой для разработчиков, чтобы они ближе познакомились с билд процессом и созданием APK файла.

Архитектура процессоров и зачем нужна виртуальная машина

Андроид после того как вышел в 2007 году претерпел множество изменений связанный с билд процессом, средой исполнения и улучшениями производительности.

У андроида много удивительных характеристик и одна из них разные архитектуры процессоров такие как ARM64 и x86

Невозможно скомпилировать код, который поддерживает каждую архитектуру. Вот именно поэтому используется Java виртуальная машина.

Понимание Java виртуальной машины

JVM это виртуальная машина, позволяющая устройству запускать код, который скомпилирован в Java байткод

Используя JVM, вы избавляетесь от проблемы с разной архитектурой процессоров.

JVM предоставляет переносимость и она позволяет запускать Java код в виртуальной среде, вместо того, чтобы запускать его сразу «на железе»

Но JVM была создана для систем с большими мощностями по ресурсам, а наш андроид имеет сравнительно мало памяти и заряда батареи.

По этой причине Google создал адаптированную под андроид виртуальную машину, которая называется Dalvik.

Компилируем исходный код

Наш исходный Java код для андроида компилируется в класс файл .class с байткодом с помощью javac компилятора и запускается на JVM

Для котлина есть kotlinc компилятор, который делает совместимый с Java байткод.

Байткод — это набор инструкций, который выполняется на целевом устройстве.

Java байткод — это набор инструкций для Java виртуальной машины.

Андроид виртуальная машина

Каждое андроид приложение работает на своей виртуальной машине. С версий 1.0 до 4.4, это был Dalvik. В андроид 4.4, вместе с Dalvik, Google представил в качестве эксперимента новый андроид runtime, который назывался ART

Сгенерированный класс файл .class содержит JVM Java байткод.

Но у андроида есть свой собственный оптимизированный формат байткода, который называется Dalvik bytecode — это просто инструкции машинного кода для процессора также как и JVM байткод.

Комплияция в .dex файл

Во время компиляции происходит конвертация .class класс файл и .jar библиотеки в один classes.dex файл, который содержит Dalvik байткод.

Команда dx превращает все .class и .jar файлы в один classes.dex файл, который написан с форматом Dalvik байткода.

Dex — это аббревиатура с английского — Dalvik Executable.

ART против Dalvik

C версии 4.4 андроид мигрировал на ART. ART также работает с .dex файлом.

Преимущество ART над Dalvik проявляется в том, что приложения запускаются быстрее, потому что весь DEX байткод транслируется в машинный код во время установки, не нужно дополнительного времени на компиляцию в рантайме.

ART и Dalvik совместимы, так что приложения разработанные для Dalvik должны работать и на ART.

Компиляция Dalvik (JIT- just in time) имела такие минусы как — быстрая трата батареи, лаги в приложениях и плохой перформанс. В Dalvik трансляция происходит только когда это нужно. Мы открываем новый экран и только в этот момент происходит трансляция, за счет этого установка происходит быстрее, но при этом проседает перформанс.

Читайте также:  Проводник с темами для андроид

Это причина по которой Google сделал Android Runtime (ART).

ART — основан на AOT (ahead of time) компиляции, она происходит до того как приложение запустится.

В ART компиляция происходит во время установки приложения. Это ведет к более долгому времени установки, но уменьшает трату батареи и избавляет от лагов, которые были на Dalvik.

Несмотря на то, что Dalvik был заменен на ART, .dex формат файлов еще используется

В андроид 7.0 JIT вернулся. Гибридная среда сочетает фичи как от JIT компиляции так и
от ART

Среда запуска байткода это очень важная часть андроида и она вовлечена в процесс запуска и установки приложения

Каждый этап описанного процесса

Source Code (Исходный код)

Это Java и Kotlin файлы в src пакете.

Resource Files

Файлы находящиеся в директории с ресурсами

AIDL Files

AIDL — аббревиатура Android Interface Definition Language, позволяет вам описать интерфейс межпроцессорного взаимодействия.

AIDL — может использоваться между любыми процессами в андроиде.

Library Modules

Модули библиотек содержат Java или Kotlin классы, компоненты андроида и ресурсы.

Код и ресурсы бибилотеки компилируются и пакуются вместе с приложением.

Поэтому модуль библиотеки может считаться компайл тайм артефактом.

AAR Libraries

Андроид библиотеки компилируются в AAR — android archive файл, который вы можете использовать как зависимость для вашего android app модуля.

AAR файлы могут содержать андроид ресурсы и файл манифеста, что позволяет вам упаковать туда общие ресурсы такие как layouts и drawables в дополнение к Java или Kotlin классам и методам.

JAR Libraries

JAR это Java библиотека и в отличие от AAR она не может содержать андроид ресурсы и манифесты.

Android Asset Packaging Tool

AAPT2 — аббревиатура (Android Asset Packaging Tool) — компилирует манифест и файлы ресурсов в один APK.

Этот процесс разделен на два шага компиляцию и линковку Это улучшает производительность так как если вы поменяете один файл, вам нужно компилировать только его и прилинковать к остальным файлам командой ‘link’

AAPT2 может компилировать все типы андроид ресурсов, таких как drawables и XML файлы.

При вызове AAPT2 для компиляции, туда передается по одному ресурсному файлу на каждый вызов

Затем APPT2 парсит файл и генерирует промежуточный бинарный файл с расширением .flat

Фаза линковки склеивает все промежуточные файлы сгенерированные в фазе компиляции и дает нам на выход один .apk файл. Вы также можете сгенерировать R.java файл и правила для proguard в это же время.

resources.arsc

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

APK содержит AndroidManifest, бинарные XML файлы и resources.arsc

resource.arsc содержит всю мета информацию о ресурсах, такую как индексы всех ресурсов в пакете

Это бинарный файл и APK который может быть запущен. APK который вы обычно создаете и запускаете не сжат и может быть использован просто посредством размещения в памяти.

R.java файл это выходной файл вместе с APK ему назначен уникальный id, который позволяет Java коду использовать ресурсы во время компиляции.

arsc это индекс ресурса который используется во время запуска приложения

D8 и R8

Начиная с андроид студии 3.1 и далее, D8 был сделан дефолтным компилятором.

D8 производит более маленькие dex файлы с лучшей производительностью, если сравнивать со старым dx.

R8 используется для компиляции кода. R8 это оптимизированная версия D8

D8 играет роль конвертера класс файлов в Dex файлы, а также производит дешугаринг функций из Java 8 в байткод, который может быть запущен на андроиде

R8 оптимизирует dex байткод. Он предоставляет такие фичи как оптимизация, обфускация, удаление ненужных классов.

Обфускация уменьшает размер вашего приложения укорачивая названия классов, методов и полей.

Читайте также:  Календарь дни рождения для android

Обфускация имеет и другие преимущества для предотвращения реверс инжиниринга, но основная цель уменьшить размер.

Оптимизация уменьшает размер Dex файла путем переписывания ненужных частей кода и инлайнинга.

С помощью дешугаринга мы можем использовать удобные фичи языка Java 8 на андроиде.

Dex and Multidex

R8 дает на выходе один DEX файл, который называется classes.dex

Если количество методов приложения переваливает за 65,536, включая подключенные библиотеки, то произойдет ошибка при билде

Источник

Android изнутри: сравнение Dalvik и ART

Привет, Хабр! Около полугода назад я публиковал подробный «гайд» по JVM. Пост, в целом, зашел, а в комментариях спросили, не планируется ли “чего-то по андроиду”. Наконец, у меня дошли руки.

В этом посте поговорим о среде выполнения в Android. В частности, я постараюсь кратко, но емко изложить, чем отличается ART и Dalvik, и как со временем улучшились средства разработки в Android. Тема явно не новая, но, надеюсь, придется кстати тем, кто только начинает вникать. Кому интересно — добро пожаловать под кат.

Виртуальная машина

Сначала, давайте разберемся чем отличается JVM от DVM.

Java Virtual Machine — виртуальная машина, способная выполнять байт-код Java независимо от базовой платформы. Она опирается на принцип “Write once, run anywhere”. Байт-код Java может быть запущен на любой машине, способной поддерживать JVM.

Компилятор Java преобразует .java файлы в class-файлы (байт-код). Байт-код передается JVM, который компилирует его в машинный код для исполнения непосредственно на CPU.

  • Имеет стековую архитектуру: в качестве структуры данных, куда помещаются и хранятся методы, используется стек. Он работает по схеме LIFO или “Last in — First Out” или “Последним вошел, первым вышел”.
  • Может запускать только class-файлы.
  • Использует JIT-компилятор.

Dalvik Virtual Machine (DVM) — виртуальная Java машина, разработанная и написанная Дэном Борнштейном (англ. Dan Bornstein) и другими, как часть мобильной платформы Android.

Можно сказать, что Dalvik — это среда для выполнения компонентов операционной системы Android и пользовательских приложений. Каждый процесс выполняется в своём, изолированном адресном пространстве. Когда пользователь запускает приложение (либо операционная система запускает один из своих компонентов), ядро виртуальной машины Dalvik (Zygote Dalvik VM) создает отдельный, защищенный процесс в общей памяти, в котором непосредственно разворачивается VM, как среда для запуска приложения. Другими словами, изнутри Android выглядит как набор виртуальных машин Dalvik, в каждой из которых исполняется приложение.

  • Использует архитектуру на основе регистров: структура данных, куда помещаются методы, основана на регистрах процессора. За счет отсутствия операций POP и PUSH, команды в регистровой виртуальной машине выполняются быстрее аналогичных команд стековой виртуальной машины.
  • Исполняет байт-код собственного формата: Android dexer (о нем поговорим ниже) преобразует class-файлы в формат .dex, оптимизированные для выполнения на Dalvik VM. В отличие от class-файла, dex-файл содержит сразу несколько классов.

Подробно об архитектуре DVM можно почитать тут.

Android Dexer

Разработчики Android знают, что процесс преобразования Java байткода в .dex байткод для Android Runtime является ключевым шагом в создании APK. Компилятор dex в основном работает “под капотом” в повседневной разработке приложений, но он напрямую влияет на время сборки приложения, на размер файла .dex и производительность во время выполнения.

Как уже упоминалось, сам dex-файл содержит сразу несколько классов. Повторяющиеся строки и другие константы, используемые в нескольких файлах классов, включаются только для экономии места. Байт-код Java также преобразуется в альтернативный набор команд, используемый DVM. Несжатый dex-файл обычно на несколько процентов меньше по размеру, чем сжатый архив Java (JAR), полученный из тех же файлов .class.

Изначально, class-файлы преобразовывались в dex-файлы с помощью встроенного DX-компилятора. Но начиная с Android Studio 3.1 и далее, компилятором по умолчанию стал D8. По сравнению с DX-компилятором, D8 компилирует быстрее и выводит dex-файлы меньшие по размеру, при этом обеспечивая более высокую производительность приложения во время исполнения. Полученный таким образом байт-код dex подвергается минификации с помощью open-source утилиты ProGuard. В итоге, мы получаем тот же dex-файл, но только меньше. Далее этот dex-файл используется для сборки apk и, наконец, для развертывания на устройстве Android.

Читайте также:  Звук уведомления без уведомления андроид

Но следом за D8 в 2018 году пришел R8, который, по сути, является тем же D8, только с дополнениями.

При работе с Android Studio 3.4 и Android Gradle 3.4.0 plugin или выше, Proguard больше не используется для оптимизации кода во время компиляции. Вместо этого плагин работает по умолчанию с R8, который сам выполняет Code shrinking, Optimisation и Obfuscation. Хотя R8 предлагает только подмножество функций, предоставляемых Proguard, он позволяет совершить процесс преобразования Java байт-кода в dex-байт-код единоразово, что еще больше сокращает время сборки.

R8 и сокращение кода

Как правило, приложения используют сторонние библиотеки, такие как Jetpack, Gson, Google Play Services. Когда мы используем одну из этих библиотек, часто в приложении используется только малая часть каждой отдельной библиотеки. Без Code shrinking, весь код библиотеки сохраняется в вашем приложении.

Бывает так, что для улучшения читаемости и удобства поддержки приложения разработчики используют подробный код. Например, могут быть использованы значимые имена переменных и шаблон проектирования для того, чтобы другим было удобнее разобраться в коде. Но шаблоны, как правило, приводят к бОльшему объему кода, чем это необходимо.

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

В качестве примера, ниже преведены цифры из доклада Shrinking Your App with R8, который был представлен на Android Dev Summit ’19:

А вот так выглядело сравнение эффективности R8 на этапе выпуска бета-версии (взято из источника Android Developers Blog):


Детальнее можно ознакомиться в оф документации и докладе.

ART vs DVM в Android

DVM была спроектирована именно для мобильных устройств и использовалась как виртуальная
машина для запуска андроид приложений вплоть до Android 4.4 Kitkat.

Начиная с этой версии, ART был представлен как среда выполнения, а в Android 5.0 (Lollipop) ART полностью заменил Dalvik.

Основное явное отличие ART от DVM состоит в том, что ART использует AOT компиляцию, а DVM — JIT компиляцию. Не так давно ART начал использовать гибрид AOT и JIT. Далее разберем это чуть подробнее.

  • Использует JIT компиляцию: всякий раз при запуске приложения,
  • компилируется та часть кода, которая необходима для выполнения приложения. Остальная часть кода компилируется динамически. Это замедляет запуск и работу приложений, но уменьшает время установки.
  • Ускоряет загрузку устройства, поскольку кеш приложения создается во время выполнения.
  • Приложения, работающие на DVM, требуют меньше памяти, чем те, которые работают на ART.
  • Уменьшает резерв батареи, увеличивая нагрузку на CPU.
  • Dalvik является “устаревшим” и не используется на андроид версиях выше 4.4.

  • Использует AOT компиляцию, то есть компилирует весь код во время установки приложения. Это ускоряет запуск и работу приложений, но требует большего времени установки.
  • Замедляет загрузку устройства, так как кеш создается во время первой загрузки.
  • Ввиду использования подхода AOT компиляции, требует больше памяти в сравнении с приложениями на DVM.
  • Увеличивает резерв батареи, сокращая работу процессора из-за отсутствия компиляции при выполнении приложений.
  • Улучшенная Garbage Collection или сборка мусора. Во времена использования Dalvik, сборщики мусора должны были осуществить 2 прохода по куче (heap), что и приводило к плохому UX. В случае с ART, такой ситуации нет: он чистит кучу один раз для консолидации памяти.

И небольшая схема Dalvik vs ART:

JIT + AOT в ART

Среда выполнения Android (ART), начиная с Android 7, включает компилятор JIT с профилированием кода. JIT-компилятор дополняет AOT компилятор и повышает производительность во время выполнения, экономит место на диске и ускоряет обновления приложений и системы.

Происходит это по следующей схеме:


Вместо того, чтобы запускать AOT-компиляцию каждого приложения на этапе установки, он запускает приложение под управлением виртуальной машины, используя JIT-компилятор (почти так же, как в Android

Источник

Оцените статью