Co się dzieje, gdy uruchamiasz aplikację na Androida?

Paweł Dedio Programowanie 2019-04-06

Witajcie ponownie — jakiś czas temu opowiadałem Wam, co się dzieje, gdy kompilujemy nasz kodDzisiaj przejdziemy sobie do powiązanej rzeczy, mianowicie do tego, co się dzieje, gdy uruchamiamy zainstalowaną aplikację na Androida na naszym urządzeniu.

Co to jest proces?

google procesor

Na początku krótka definicja, która przyda nam się w dalszej części artykułu. Proces jest czymś w rodzaju specjalnego kontenera, który przechowuje wszystkie informacje o danej aplikacji. Zazwyczaj każdy program działa w osobnym procesie. Dodatkowo jedna aplikacja może posiadać więcej niż jeden proces. Każdy taki kontener posiada swój unikalny identyfikator oznaczany jako PID (z angielskiego process identifier). Zarządzaniem procesami zajmuje się system operacyjny, a konkretniej jego jądro. To ono pilnuje, aby każdy proces mógł poprawnie wykonywać swoje zadania oraz miał dostęp do odpowiedniej ilości pamięci. Każdy proces ma przydzieloną osobną przestrzeń pamięciową, w której może zapisywać wszelkie potrzebne informacje, takie jak zmienne, wyniki działań i tak dalej. Inne procesy nie mają bezpośredniego dostępu do tych danych.

W skład każdego procesu mogą wchodzić wątki, czyli takie jakby procesy w procesie. Z tą różnicą, że wątki współdzielą pamięć przydzieloną dla konkretnego procesu. Większość aplikacji, które znamy, posiada jeden proces oraz kilka wątków działających w ramach tego procesu.

 

Typy procesów w androidzie

System Android wyróżnia 4 typy procesów, na podstawie których ustala priorytety ich wykonywania. Ja również wymienię je według priorytetu, od najwyższego do najniższego.

  • Proces będący na pierwszym planie (foreground process) – to proces związany z aplikacją, której obecnie używa użytkownik. Najczęściej jest to proces należący do aktualnie uruchomionej aplikacji.
  • Widoczny proces (visible process) – to proces nieco podobny do tego z poprzedniego punktu. Z tą różnicą, że proces widoczny należy do aplikacji, która jest widoczna, lecz to nie na niej obecnie skupia się użytkownik. Może to być na przykład jedna z aplikacji uruchomiona w trybie podzielnego ekranu. Również aplikacja robiąca coś w tle może być zaliczana do widocznych, o ile o jej działaniu informujemy użytkownika za pomocą powiadomienia (na przykład odtwarzacze muzyczne).
  • Proces należący do serwisu (service process) – to proces serwisu — specjalnego komponentu służącego do wykonywania długotrwałych działań, bez potrzeby blokowania użytkownika. Przeważnie procesy tego typu należą do aplikacji, które wykonują jakieś operacje, bez graficznej informacji dla użytkownika (nie ma żadnych powiadomień).
  • Proces znajdujący się w pamięci podręcznej (cached process) – procesy niepasujące do poprzednio wymienionych kategorii trafiają na specjalną listę znajdującą się w pamięci podręcznej. Jeśli użytkownik powróci po pewnym czasie do jakieś aplikacji, Android przywraca jej proces z pamięci podręcznej, dzięki czemu nie ma potrzeby tworzenia nowego procesu, a cała operacja trwa bardzo szybko. Jednak procesy będące na tej liście są pierwszymi kandydatami do likwidacji w sytuacji, gdy braknie nam pamięci. Lista jest posortowana według kolejności, w jakich używaliśmy aplikacje. Tak więc w przypadku braku pamięci, system najpierw będzie usuwał procesy należące do aplikacji, których nie używaliśmy przez bardzo długi okres.

 

Jak wygląda uruchomienie aplikacji?

Warto wiedzieć, ile czasu grasz lub przeglądasz Facebooka

Odcinek o kompilacji aplikacji zakończyliśmy informacją, że kod napisany w Javie lub Kotlinie zostaje zamieniony na kod bajtowy zapisany w plikach z rozszerzeniem dex. Jednak taki kod nadal nie jest zbyt czytelny dla procesora, ponieważ procesor jest takim urządzeniem, które praktycznie potrafi dodawać tylko liczby binarne. Moglibyśmy tłumaczyć nasz kod bezpośrednio do kodu maszynowego z pominięciem kodu bajtowego, lecz musielibyśmy dokładnie wiedzieć, na jakim typie urządzenia będzie wykonywana nasza aplikacja.

Pamiętacie odcinek, o tym, dlaczego aplikacje na Androida zajmują coraz więcej miejsca? Mogliście zobaczyć tam folder z bibliotekami natywnymi. W ich przypadku działa to dokładnie w taki sposób — ich kod jest gotowy do uruchomienia bezpośrednio na procesorze, przez co musimy posiadać kilka ich wersji, w zależności na jakiej architekturze działa urządzenie. To samo musielibyśmy robić ze standardowym kodem Javy, jeśli chcielibyśmy kompilować go bezpośrednio do kodu maszynowego.

Dlatego potrzebujemy jakiegoś narzędzia, które jest w stanie na bieżąco tłumaczyć kod bajtowy na kod maszynowy, dostosowując go jednocześnie do procesorów różnego typu. Na szczęście istnieje takie narzędzie i nazywa się ono maszyna wirtualna. To właśnie ona obsługuje pliki dex i przetwarza je na instrukcje zrozumiałe dla naszego urządzenia, dzięki czemu możemy zobaczyć aplikację działającą zgodnie z intencjami jej twórcy.

 

Dalvik — czyli ucieczka przed Oracle

Wszystkie aktualizacje Androida dbają o bezpieczeństwo Twojego urządzenia

Google do Androida mógłby wykorzystać maszynę wirtualną Javy, lecz w przypadku urządzeń mobilnych trzeba opłacać specjalną licencję. W celu ominięcia tego wymogu Google postanowił stworzyć swoją własną maszynę wirtualną. Jej źródła są całkowicie otwarte, więc każdy może do nich zajrzeć.

Dalvik do zamiany kodu bajtowego na maszynowy korzysta z kompilacji typu just in time (JIT). Co oznacza, że za każdym razem, gdy uruchamialiśmy jakąś aplikację, Dalvik musiał wykonać kompilację części jej kodu bajtowego. W miarę, gdy docieraliśmy do kolejnych elementów aplikacji, kolejne porcje kodu były kompilowane do kodu maszynowego. Łatwo zauważyć, że mamy do czynienia z lekkim marnotrawstwem zasobów, ponieważ wykonujemy te same operacje przy każdym uruchomieniu. Na szczęście obecnie nie mamy tego problemu, o czym dowiecie się w następnym akapicie.

Wróćmy jeszcze do sprawy sporu Google i Oracle. Początkowo twórcy Androida chcieli się dogadać z firmą Sun Microsystems — twórcą Javy, aby używać standardowych bibliotek oraz ich maszyny wirtualnej. Sun zaproponował licencję za kwotę pomiędzy 30 a 50 milionów dolarów. Ta cena była akceptowalna przez Google, lecz Sun dodatkowo zażądał większego wpływu na kierunki rozwoju Androida, co było nie do przyjęcia przez jego twórców. Wobec tego, tak jak już wspomniałem wcześniej, Google zdecydował się na coś w rodzaju przepisania części bibliotek Javy na nowo i utworzenie własnej maszyny wirtualnej, która była wstanie interpretować ten kod. Jak można się domyślić, nie spodobało się to Oracle — firmie, która kupiła Sun Microsystems. Uważają oni, że Google tak naprawdę ukradł ich kod, dlatego od kilku lat w sądzie toczy się dość głośna sprawa mająca rozstrzygnąć, kto tak naprawdę ma rację.

 

ART — następca Dalvika

ART jest skrótem od Android Runtime, co możemy przetłumaczyć jako środowisko uruchomieniowe Androida. Został on wprowadzony jako domyślna maszyna wirtualna w Androidzie 5.0 Lollipop. W ART Google zmienił nieco podejście, jeśli chodzi o kompilacje kodu bajtowego na maszynowy. Obecnie cała procedura odbywa się już w momencie instalacji aplikacji i jest to tak zwana kompilacja ahead of time (AOT). Taka zmiana wydłużyła nieco sam proces instalacji, lecz tym samym zredukowała czas potrzebny na każdorazowe uruchomienie programu. Dodatkowo według twórców Androida, taka zmiana zredukowała również zużycie energii, co przełożyło się na dłuższy czas pracy naszych smartfonów.

W odróżnieniu od Dalvika, ART lepiej radzi sobie z zarządzeniem pamięcią RAM, co pozwoliło na lepsze współdziałanie kilku aplikacji jednocześnie. Dodatkowo w ART programiści mają dostęp do wielu przydatnych narzędzi monitorujących aplikację. Możemy na bieżąco sprawdzać użycie zasobów, wymusić zwolnienie pamięci i wiele innych.

Co ciekawe, od Androida 7.0 Nougat ART używa zarówno kompilacji JIT, jak i AOT. Wszystko w celu zapewnienia jak najlepszej wydajności. Zasadniczo podczas działania ART korzysta z plików z rozszerzeniem oat, w których zapisany jest kod maszynowy, stworzony w momencie instalacji aplikacji. Jednak tak jak już wspominałem, wydłuża to nieco moment instalacji, dlatego Sklep Play pomija ten proces, gdy aktualizuje kilka aplikacji jednocześnie. W takiej sytuacji ART nie odnajdzie pliku oat odpowiedniego dla danej aplikacji, wobec czego musi wykonać kompilację w momencie uruchomienia aplikacji.

 

Zbierzmy wszystko do kupy

Podsumujmy co tak właściwie dzieje się w momencie kliknięcia, na ikonkę aplikacji. Po pierwsze system tworzy nowy proces, dedykowany tej aplikacji, wraz z odpowiednią ilością pamięci oraz dostępem do czasu procesora. Następnie Android ART sprawdza, czy mamy dostęp do pliku oat, zawierającego kod maszynowy. Jeśli nie, to ART rozpoczyna proces kompilacji kodu bajtowego na kod maszynowy. Jeśli mamy już dostęp do takiego kodu, ART zaczyna wykonywać instrukcje w nim zawarte, co oznacza uruchomienie wybranej przez nas aplikacji. W przypadku braku pamięci, Android przegląda uruchomione procesy i zabija te, które mają najniższy priorytet.

 

Uff, udało nam się dotrzeć do końca. Dzisiaj było nieco dłużej i trochę bardziej technicznie. Za tydzień będzie nieco lżej, bo napiszę wam, co chciałbym zobaczyć w Androidzie R. Do zobaczenia!

Zapraszam również na największe w Polsce forum dla programistów Android. Jeśli macie pytania odnośnie do kariery programisty — zapraszam do działu Kariera programowanie. Zachęcam również do przejrzenia działu Praca oraz zlecenia dla programistów — być może to właśnie tam znajdziesz swoją pierwszą pracę.

Pozostałe odcinki serii o programowaniu.





x