자바 가상 머신


JVM; Java Virtual Machine.

1 개요

Java로 개발한 프로그램을 컴파일하여 만들어지는 Java 바이트코드를 실행시키기 위한 가상의 기계. Java 언어와 함께 썬마이크로시스템즈사에서 개발하였으며 썬마이크로시스템즈오라클에 인수되면서 현재는 오라클이 Java 명칭을 비롯하여 모든 권한을 행사하고 있다.

JVM은 플랫폼 독립적으로, JVM이 실행 가능한 환경이라면 어디서든 Java 프로그램이 실행될 수 있도록 한다. 즉, Java의 모토인 Write once, Run anywhere는 JVM을 통해 가능한 것이다. 하지만 특정 운영체제의 특수한 기능을 호출하거나 하드웨어를 제어하는 등의 일은 JVM으로 할 수 없으며, JNI 같은 Native 코드를 호출하기 위한 인터페이스를 거쳐야 한다.

.NET Framework와 함께 가상 머신 언어 시장을 사실상 양분하고 있다.

2 종류

오라클이 소유한 두 종류의 JVM으로 썬마이크로시스템즈에서 개발된 HotSpot, BAE 시스템에서 개발된 JRockit이 있으며 클린 룸 구현에는 KafeeIBM사의 IBM J9가 있다. 윈도, 리눅스등의 환경에서는 대부분 HotSpot이 사용되지만, IBM AIX를 운영체제로 사용하는 경우 IBM J9가 널리 사용된다.

구글 안드로이드 프로그램은 자바를 사용하여 개발하지만, 안드로이드에 있는 Dalvik 가상 머신은 자바 바이트코드는 전혀 실행하지 못하므로 엄밀하게 말하면 JVM은 아니다. 다만 자바 바이트코드를 한 번 변환해서 Dalvik용 코드로 만들고 그걸 실행한다. 좀 바보같긴 하지만, JVM을 포함한 자바의 여러 부분에 걸린 특허를 피하기 위해 내놓은 꼼수. 다만 결국 썬을 인수한 오라클이 소송을 걸었다. 안드로이드가 잘 나가는 걸 본 썬은 독립 회사였을 때에 재주는 썬이 넘고 돈은 구글이 벌어서 배는 무지 아팠지만 공돌이의 정으로 참고 있었다고 한다. 구글이나 썬은 공돌이 회사의 대표격이었으니. 반면 오라클은 문화적으로 봤을 때 전통적인 양복 회사에 가까워서 그딴거 상관 없던 모양.

3 구조

파일:JVM-Architecture.gif

4 성능

바이트코드는 실제의 기계에서 직접 실행되는 것이 아니라 JVM의 해석 단계를 거쳐 실행되므로 Java로 개발된 프로그램은 같은 기능의 Native 언어[1]보다 실행 속도가 느리다. 과거에는 바이트코드를 순수하게 인터프리트 하여 매우 느렸으나 현재에는 Just-In-Time 컴파일을 구현하여 Native 언어들의 성능을 따라잡고 있다.

JVM은 고도로 추상적인 머신이며 구조가 표준화 되어 있으며, 메모리의 접근을 프로그래밍 언어 차원에서 통제하고 있으므로 매우 공격적인 최적화가 가능하다. 즉, 순수한 연산 등 일부 기능에 대해서는 Native 언어보다 더 우월한 성능을 보여 주기도 한다.[2] 하지만 JIT 컴파일 시간, 가비지 컬렉션을 위한 시간 등이 필요하므로 Native 언어와 완전히 동일할 수는 없다.[3]

4.1 가비지 컬렉션 (GC)

JVM은 가비지 컬렉션을 수행하여 할당되었다가 더 이상 쓰이지 않는 메모리를 자동으로 회수한다. Full GC(전체 가비지 컬렉션)의 경우 프로그램 수행을 일시 정지(Stop-the-World) 시켜놓고 할 수밖에 없는데[4], 또 이게 자바 프로그램이 규칙적이지도 않고 이유도 없이 뚝뚝 끊긴다는 악명을 떨치는데 공헌했다. 대규모 서비스의 운영 시 Full GC는 성능에 상당히 심각한 영향을 주므로 최대한 줄이는 방향으로 개선되고 있다.

GC의 상세한 동작 과정에 대해서는 다음 문서를 참고할 것: [1]

5 JVM 기반 언어

이름Java가 들어있지만 JVM은 자신이 무슨 언어를 실행하는지 전혀 관심이 없다. 형식만 올바로 지켜서 만들어졌다면 자바가 아니라 자바 바이트코드를 만드는 다른 언어도 얼마든지 실행할 수 있는 것.

JVM의 플랫폼 독립성과 준수한 성능, 그리고 Java 코드와의 손쉬운 상호작용 등의 특징으로 인하여 JVM을 기반으로 하는 Java 이외의 언어들도 많이 개발 되어 있다.

5.1 기존 언어의 JVM 구현

5.2 JVM을 위한 새로운 언어

6 관련 문서

  1. C(프로그래밍 언어), C++, Rust, Go
  2. C 등의 Native 언어는 특정 플랫폼에 맞춰서 컴파일 되므로 호환성을 위해 성능을 포기해야 하는 경우가 있다.
  3. 이 부분이 매우 중요해서 JVM이나 .NET CLR 등 가상머신 기반에서 벤치마크를 돌릴 때는 1~5회 정도 웜업을 한 후에 측정한다.
  4. 일반 프로그램 입장에서는 자기가 돌아가다가 가비지 컬렉션이 분별없이 끼어들면 자기가 쓰던 메모리가 갑자기 멋대로 바뀌었다고 볼 수밖에 없다. 일반 프로그램을 안 멈춰놓고 가비지 컬렉션 작업을 하다가 순서가 꼬이기라도 하면 프로그램 오류 확정.