Привет! Я Саша, старший 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. А делать он может всё что угодно - например, перехватывать и читать ваши смс. Вывод банальный – не стоит устанавливать на устройство приложения из сомнительных источников.
Автор: vlaas22