Существует как минимум пять технологий, которые делают Android именно тем, чем мы привыкли его видеть: виртуальная машина, система многозадачности, сервисы Google, IPC-механизм Binder и ядро Linux. Каждая из этих подсистем имеет свою историю развития, свои причины появления и наделяет Android присущими ему широкими возможностями. Мы в подробностях поговорим о каждой из них и покажем, почему Android — это нечто гораздо большее, чем мобильная ОС.
Принято считать, что в основе Android лежит Java. Дескать, именно поэтому ОС такая требовательная к процессору и оперативной памяти. На самом деле все намного сложнее. Java (а теперь и Kotlin) — это действительно официальный язык Android. Но Java — это не только язык, но и среда исполнения.
В случае обычной Java, разработанной компанией Sun (теперь уже Oracle), приложения компилируются в специальный промежуточный байт-код, который затем исполняет виртуальная машина. Самые ранние версии виртуальной машины делали это путем интерпретации: ВМ читала байт-код, анализировала записанные в нем инструкции и исполняла их.
Это медленный метод исполнения (на каждую инструкцию ВМ могли уходить десятки и сотни машинных инструкций), поэтому позднее появился так называемый JIT-компилятор (Just In Time compiler). С его помощью виртуальная машина могла на лету перегонять байт-код в машинные инструкции, что существенно подняло скорость его исполнения, но повысило расход оперативной памяти: в памяти теперь необходимо хранить не только байт-код, но и полученные из него машинные инструкции плюс метаданные, позволяющие выполнять оптимизации.
Кроме того, при разработке виртуальной машины Джеймс Гослинг решил использовать стековый дизайн виртуальной машины, как простой и универсальный. Но существует более эффективный в скорости исполнения байт-кода и потребления оперативной памяти дизайн виртуальной машины — регистровый.
Именно такая регистровая виртуальная машина (под названием Dalvik) использовалась в первых версиях Android. Благодаря отсутствию JIT-компилятора она была очень нетребовательной к оперативной памяти, а регистровый дизайн позволял исполнять приложения достаточно быстро даже в режиме интерпретации.
Однако в Android 2.2 Google все-таки реализовала JIT-компилятор и долго хвасталась графиками многократного прироста производительности. На деле же скорость возросла незначительно, все самые требовательные к ресурсам API Android и так были реализованы на C++, который исполнялся напрямую на процессоре. Почти все тяжеловесные игры также использовали код на C/C++ и других компилируемых в машинные инструкции языках.
В Android 5.0 Google пошла еще дальше и заменила Dalvik на AOT-компилятор (Ahead Of Time compiler) под названием ART. В теории такой компилятор позволяет избавиться от виртуальной машины как сущности и переводить приложение в машинные инструкции еще на этапе установки. На деле же получалось так, что не весь байт-код можно было одним махом сконвертировать в инструкции процессора, и результирующий код мог содержать как машинные инструкции, так и байт-код старого доброго Dalvik. И со всей этой мешаниной продолжала разбираться виртуальная машина.
AOT-компилятор также проигрывал JIT-компилятору в возможностях оптимизации машинного кода. У него просто не было достаточно информации о поведении приложения и особенностях его работы; ее можно было получить, только запустив приложение. И он существенно замедлял установку приложений и первый запуск операционной системы.
Чтобы это исправить, в Android 7 Google решила использовать гибридный JIT/AOT-компилятор. Сразу после установки приложение исполняется с использованием JIT-компилятора, но во время работы от зарядки смартфон перегоняет приложение в машинные инструкции с помощью AOT-компилятора, который может учитывать информацию, накопленную в процесс исполнения приложения.
А теперь вопрос: зачем Google нужны были все эти заморочки с Java и виртуальными машинами, когда можно было пойти по пути Apple и использовать обычный, компилируемый в машинные инструкции язык, который не страдает от проблем с жором оперативки и производительности?
Ответов на этот вопрос как минимум два.
1. Портабельность. Помнишь слоган Java: «Написано однажды — работает везде»? А ведь это не маркетинговый булшит, это чистая правда. Ты можешь скачать любое когда-либо написанное на Java приложение и запустить его на любой полноценной виртуальной машине Java независимо от операционной системы, архитектуры процессора и фазы луны. Оно просто работает.
Тем же принципом руководствовались разработчики Android. Неважно, на каком процессоре основан смартфон, неважно, смартфон это или телевизор. Приложение, написанное для Android, будет на нем работать без всяких перекомпиляций и модификаций (если, конечно, оно не использует машинный код на C/C++).
Мало того — разработчику даже не нужно задумываться о поддержке более эффективных инструкций, появившихся в новых процессорах, за него это сделает виртуальная машина.
2. Надежность. Java — это высокоуровневый язык со сборщиком мусора, не позволяющий адресовать память напрямую и не требующий самостоятельного освобождения выделенной памяти. Это значит, что многие типы атак, включая buffer overflow и use after free, против приложений на Java не могут быть реализованы. В крайнем случае виртуальная машина просто убьет приложение (как это нередко происходит при выходе за границы массива, например). Именно поэтому в Android в целом находят меньше уязвимостей, чем в iOS, полностью написанной на небезопасных языках C, C++ и Objective-C. И это одна из причин, почему Apple понадобился язык Swift, на котором она начала переписывать компоненты ОС и стоковые приложения.
Java — один из самых популярных языков в мире, поэтому у Android-разработчиков изначально был доступ к огромному количеству Java-библиотек и сниппетов, кода, которые можно задействовать в приложении.
Подводя итог: Java и виртуальная машина были правильным выбором. И хотя сейчас набирает обороты язык Kotlin, он полностью совместим с Java на уровне байт-кода. А это значит, что для его поддержки на стороне ОС не нужно делать ничего. Приложения просто работают.
Cтатьи из последних выпусков журнала можно покупать отдельно только через два месяца после публикации. Чтобы читать эту статью, необходимо купить подписку.
Подписка позволит тебе в течение указанного срока читать ВСЕ платные материалы сайта, включая эту статью. Мы принимаем оплату банковскими картами, электронными деньгами и переводами со счетов мобильных операторов. Подробнее о подписке
1 год5590 р. Экономия 1400 рублей! |
1 месяц700 р. 25-30 статей в месяц |
Уже подписан?
Читайте также
Последние новости