JVM, DVM, ART 이해하기

Charlezz
8 min readDec 18, 2019

--

안드로이드를 처음 막 배우기 시작한 꼬꼬마시절
왜 구글이 왜 자바를 선택했고, 자바의 바이트코드가 무엇이며, 왜 폰에서 Dalvik과 ART를 선택하라는 거지???

궁금했지만 누구하나 시원하게 알려주지 않았던 기억이 있어, 오늘은 안드로이드가 실행되는 환경의 내부를 좀 알아보고자 한다.

JVM(Java Virtual Machine)

JVM은 자바 바이트 코드를 실행할 수 있는 주체이다. 자바 바이트 코드는 플랫폼에 독립적이며, JVM의존적으로 실행된다.
즉 플랫폼에 맞춰 소스코드를 빌드할 필요없이, 한번의 빌드로 여러 플랫폼에서 실행할 수 있다. (WORA : Write Once and Run Anywhere)

예를들어 하나의 A.java라는 소스 파일을 가지고 있고 이를 java 컴파일러에 의해 바이트코드로 변경하여 A.class파일로 만들었다고 가정하자. 이는 윈도우즈, 맥, 리눅스 어느 플랫폼이라도 JVM만 동작되는 환경이라면 새로 컴파일 할 필요없이 A.class를 실행할 수 있다.

JVM의 특성은 다음과 같다

  • 스택 기반의 가상 머신
  • 단일 상속형태의 객체 지향 프로그래밍을 가상 머신 수준에서 구현
  • 포인터를 지원하되 C와 같이 주소 값을 임의로 조작이 가능한 포인터 연산이 불가능
  • 가비지 컬렉션 사용
  • 모든 기본 타입의 정의를 명확히 함으로써 플랫폼 독립성 보장
  • 데이터 흐름 분석에 기반한 자바 바이트코드 검증기를 통해 스택 오버 플로, 명령어 피연산자의 타입 규칙 위한, 지역 변수의 초기화 전 사용 , 필드 접근 규칙 위반 등 많은 문제를 실행 전에 검증하여 실행 시 안전을 보장하고 별도의 부담을 줄여줌
    명령어에서 스택에서 가져올 피연산자의 타입을 명령어에 지정

DVM(Dalvik Virtual Machine)

DVM은 안드로이드 애플리케이션을 실행할 수 있는 가상 머신이다. 모바일 기기 특성상 베터리 수명, 컴퓨팅 파워 및 메모리가 데스크탑 환경에 비해 열악하다. 그렇기 때문에 모바일 기기 환경에 맞게 최적화 되어 나온 가상머신이 바로 DVM이다.

앞의 이미지는 APK가 만들어지는 과정을 설명하고 있다. JVM에서 실행되는 자바 바이트 코드로 변환되는 동일한 과정을 거치지만 마지막 두단계가 다르다.
Dex컴파일러는 class파일을 dex파일로 변경하여 DVM에서 실행가능하게 만든다. 여러개의 class파일이 하나의 dex파일로 변경되며 최종적으로 dex, 리소스를 포함한 기타 라이브러리 등이 압축되어 APK(Android application package)가 완성된다.

JVM은 단일 인스턴스로 여러 애플리케이션에서 공유되어 사용되지만 DVM은 다중 인스턴스로 실행되도록 설계되었기 때문에 좀 더 효율적으로 운영되고, 애플리케이션에 자체적인 VM인스턴스가 제공된다.

구글에서 처음 DVM을 선택한 이유

빠르다

안드로이드에서 DVM을 사용하는 가장 큰 이유중 하나는 JVM이 사용한 스택 기반 모델 대신 레지스터 기반 모델을 사용한다는 점이다. 스택 기반 모델은 많은 메모리를 요구하며 안드로이드에서는 빠른 성능을 낼수 없다. 레지스터 기반 모델은 적은 메모리 사용을 요구하기 때문에 빠르게 동작이 가능하다.

라이센스 문제

구글에서는 오픈소스로 제공될 안드로이드에서 JVM을 사용할 경우에 발생할 수 있는 라이센스와 관련된 문제를 피하기 위해 새로운 가상머신이 필요했다. JVM은 공짜지만 GPL라이센스이며 안드로이드와 관련된 내용들은 Apache 라이센스가 대다수였기 때문에 JVM은 적합하지 않았다.
(하지만 일부 자바 API 사용에 대해 오라클에 고소를 당했고, 결국 패소 했다.)

Dalvik은 안녕, 이제는 ART

ART(Android Runtime)는 안드로이드 애플리케이션 런타임 환경으로 새로운 디버깅 기능과 좀 더 정확한 고수준의 애플리케이션 프로파일링 기능을 제공한다. 그보다도 구글이 DVM에서 ART로 변경한 진짜 이유는 바로 압도적인 퍼포먼스 개선이다. 내부적으로 이를 이해하려면 우선 컴파일러 언어인터프리터 언어의 차이를 알아야한다.

Compiler vs Interpreter

컴파일러 언어와 인터프리터언어의 가장 큰 차이점은 컴파일을 수행하는 시점이다. 런타임 전에 컴파일을 수행하면 컴파일언어이고, 런타임에 컴파일을 수행하면 인터프리터 언어이다.

컴파일러 언어는 미리 컴파일을 해두기 때문에 빠른 실행속도라는 이점을 얻는 대신 플랫폼 종속성과 디스크 공간 활용이 단점이다. 대표적으로 C,C++, C# 등이 컴파일러 언어에 속하고, 인터프리티 언어는 런타임 중에 한줄한줄 해석하며 실행하기 때문에 상대적으로 컴파일러 언어보다 느리지만 코드 변경시 즉시 실행이 가능하다는 장점이 있다. 대표적으로 자바스크립트, HTML, 파이썬, SQL, 루비 등이 인터프리티 언어에 속한다.

자바의 경우 javac(컴파일러)를 통해 컴파일을 하게 되고, 그 결과로 바이트코드를 얻기 때문에 컴파일러 언어이지만, VM(가상머신)에서 바이트 코드를 다시 기계어로 변환한다는 점에서 인터프리터 언어의 특징도 가지고 있다.

DVM과 ART의 컴파일러 (JIT vs AOT)

JIT(Just In Time)은 Android 2.2 버전(Froyo)부터 적용된 DVM 내부의 컴파일러다. 애플리케이션을 바이트 코드를 가상머신에서 기계어로 번역한 결과를 캐쉬에 저장하기 때문에 다시 해당 바이트 코드를 실행해야 하는 경우 캐쉬의 내용을 불러오기 때문에 퍼포먼스가 개선되었지만 별도의 메모리 캐시가 필요하다는 점에서 일반적인 인터프리터 방식보다는 더 많은 메모리 공간이 필요하다.

AOT ART 내부의 컴파일러로써 DVM의 JIT와는 달리 애플리케이션이 설치되는 시점에 애플리케이션 전체 바이트 코드를 기계어로 번역한다. 그렇기 때문에 설치시간이 오래걸린다는 단점이 있지만, 런타임에서 바이트 코드를 해석하는 시간을 제거했기 때문에 전체적인 퍼포먼스가 좋아진고 베터리 수명이 향상되게 된다.

참조:

https://towardsdatascience.com/jvm-vs-dvm-b257229d18a2

https://namu.wiki/w/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C%20%EB%9F%B0%ED%83%80%EC%9E%84

https://developer.android.com/guide/practices/verifying-apps-art?hl=ko

https://source.android.com/devices/tech/dalvik?hl=ko

https://oain.tistory.com/113

https://blog.mindorks.com/what-are-the-differences-between-dalvik-and-art

https://stackoverflow.com/questions/31957568/what-is-difference-between-dvm-and-art-why-dvm-has-been-officially-replaced-wi

https://www.journaldev.com/23464/android-runtime-dvm-vs-art-aot-vs-jit

https://android.jlelse.eu/closer-look-at-android-runtime-dvm-vs-art-1dc5240c3924

https://pdfs.semanticscholar.org/72e9/152086f81253846c4ddbe9369aab8732abb6.pdf

https://brunch.co.kr/@mystoryg/81

https://m.blog.naver.com/PostView.nhn?blogId=tmondev&logNo=220644439927&proxyReferer=https%3A%2F%2Fwww.google.com%2F

--

--