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

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

public static void main(String[] args)

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

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

Комментарии (2)


  1. nikolz
    30.10.2024 17:15

    Подобное и подробнее на хабре написали 7 лет назад

    https://habr.com/ru/articles/345120/


    1. vlaas22 Автор
      30.10.2024 17:15

      Спасибо за ссылку! Действительно, довольно подробная статья. Там углубление в работу Looper (о чём я осознанно не стал писать в своей статье) и запуск Activity. У меня же больше про процесс Zygote и вызов метода main в нём. Надеюсь, статья вышла полезной!