Главный метод Android-приложения

Привет! Я Саша, старший Android-разработчик в Авито, ранее работал в Яндексе и Kaspersky. Пишу о разработке и всём, что с ней связано, в своем телеграм-канале. Сейчас поговорим немного про главный метод и про процесс Android-приложения.

Если вы когда-нибудь писали «Hello World» на Java (или любом другом C-подобном языке), то наверняка делали это в статическом методе main. Этот метод вызывается в JVM и является точкой входа любой Java программы.

public static void main(String[] args)

Но при разработке приложений для Android вы возможно, как и я до недавнего времени, ни разу метод main не встречали. Создается ощущение, что его вообще не существует, а при нажатии на иконку в лаунчере наши Application и Activity создаются какими-то волшебными гномами, спрятанными в устройстве.

На самом деле метод main в Android все-таки есть, и содержится он в классе ActivityThread. Но давайте по порядку.

ActivityThread

Что это за зверь такой? Неужели каждая Activity работает на особом потоке? Конечно нет, просто ActivityThread-ом разработчики Android SDK решили назвать главный (Main) поток приложения. Да, нейминг вводит в заблуждение, но так уж повелось ¯\_(ツ)_/¯

Теперь — что же делает метод main в ActivityThread-е. Тут всё прозаично: он настраивает главный поток и инициализирует его Looper. Проще говоря, на главном потоке запускается бесконечный цикл, в котором и выполняется код приложения — создаются Activity, отображаются View и т.д. Про Looper уже написано множество статей, не буду пересказывать их — подробнее можно почитать, например, тут и тут.

Собственно, так я и наткнулся на объявления метода main — лазил по сорсам Looper-а и решил найти место, где инициализируется MainLooper. Но дальше может возникнуть вопрос — кто же вызывает метод ActivityThread.main при запуске приложения? И тут в дело вступает…

Zygote

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

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

При запуске очередного приложения Zygote создает полную копию себя, которая и будет являться процессом данного приложения. Делает он это с помощью системного вызова fork. При этом оригинальный Zygote продолжает крутить бесконечный цикл, а вот его копия выходит из цикла и вызывает тот самый ActivityThread.main, тем самым запуская приложение.

Процесс запуска приложения

Процесс запуска приложения

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

Заключение

Итак, главный метод в Android-приложениях хоть и скрыт от наших глаз, но играет очень важную роль в системе. Он находится в классе ActivityThread, запускается Zygote и сам запускает MainLooper приложения.

Механизм работы Zygote позволяет оптимизировать запуск приложений, но обладает и недостатками. Например — раз этот процесс является базовым для всех приложений, то можно заразить его трояном, который затем прорастет в каждое приложение. Так работает один из самых страшных троянов в Android — Triada. А делать он может всё что угодно — например, перехватывать и читать ваши смс. Вывод банальный — не стоит устанавливать на устройство приложения из сомнительных источников.

© Habrahabr.ru