Java Virtual Machine

최근 수정 시각:

파일:나무위키프로젝트.png
이 문서는 나무위키 컴퓨터 프로젝트에서 다루는 문서입니다.
해당 프로젝트 문서를 방문하여 도움이 필요한 문서에 기여하여 주세요!

1. 개요2. 종류3. 구조4. 성능
4.1. 가비지 컬렉션 (GC)
5. JVM 기반 언어
5.1. 기존 언어의 JVM 구현5.2. JVM 기반의 언어
6. 관련 문서

1. 개요[편집]

Java로 개발한 프로그램을 컴파일하여 만들어지는 바이트코드를 실행시키기 위한 가상머신. JRE(Java Runtime Environment)에 포함되어 있으며, Java 컴파일러가 프론트엔드를 담당한다면 Java 가상 머신은 코드 최적화와 백엔드를 담당한다. Java와 함께 썬 마이크로시스템즈에서 개발되었으며 썬이 오라클에 인수된 후 현재는 오라클이 Java 명칭을 비롯하여 모든 권한을 행사하고 있다. Java 소스 코드는 javac 컴파일러를 거쳐 바이트코드로 변환되며, 이 바이트코드는 JRE에 들어있는 java classloader에 의해 JVM으로 적재되고 JVM은 적재된 바이트코드를 JIT 컴파일 방식으로 실행한다.

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

Java 가상머신이라고 해서 Java 바이트코드만 인식하는 것은 아니다. 이 바이트코드를 Java가 아닌 다른 언어들[1]을 가지고도 생성할 수 있기 때문이다. 따라서 지금의 Java 가상머신은 Java만을 위한 것이라고 생각하면 안 된다. 이름이 Java 가상머신이다 보니 Java에 종속된 게 아닌가 생각할 수도 있지만 그렇지도 않다. Java 가상머신은 코틀린 코드를 컴파일해도 읽을 수도 있고 스칼라 코드를 컴파일해도 읽을 수 있다. 단, 기본이 Java를 위해서 만들어졌기 때문에 Java 소스 코드와 컴파일된 바이트코드는 비교적 직관적으로 연결되지만, 코틀린이나 스칼라의 경우 Java와의 호환성을 고려하긴 했어도 상대적으로는 비직관적이며 필연적으로 Java를 공부해야 한다는 단점이 있다.

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

2. 종류[편집]

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

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

3. 구조[편집]

파일:JVM-Architecture.gif

4. 성능[편집]

바이트코드는 실제의 기계에서 직접 실행되는 것이 아니라 JVM의 해석 단계를 거쳐 실행되므로 Java로 개발된 프로그램은 같은 기능의 네이티브 언어[2]보다 실행 속도가 느리다. 과거에는 바이트코드를 순수하게 인터프리트하여 매우 느렸으나 현재는 JIT 컴파일의 도입과 하드웨어의 발전으로 눈꼽만큼 성능이 개선되었다.

JVM은 추상적인 머신이며, 메모리의 접근을 가상 머신 차원에서 관리하고 있으므로 런타임에 최적화가 가능하다. 매우 극단적이고 특수한 상황을 가정하면 극히 일부 기능에 대해서는 네이티브 언어보다 더 우월한 성능을 보여 주기도 한다. 하지만 JIT 컴파일 시간, 가비지 컬렉션을 위한 시간 등이 필요하므로 근본적인 한계가 있다.[3]

4.1. 가비지 컬렉션 (GC)[편집]

JVM은 가비지 컬렉션을 수행하여 할당되었다가 더 이상 쓰이지 않는 메모리를 자동으로 회수한다. Full GC(전체 가비지 컬렉션)의 경우 프로그램 수행을 일시 정지(Stop-the-World) 시켜놓고 할 수밖에 없는데[4], 또 이게 Java 프로그램이 규칙적이지도 않고 이유도 없이 뚝뚝 끊긴다는 악명을 떨치는데 공헌했다. 대규모 서비스의 운영 시 Full GC는 성능에 상당히 심각한 영향을 주므로 프로그래머의 GC 튜닝이 필수로 들어간다. 즉, Java는 GC 덕분에 메모리 관리를 신경쓰지 않아도 된다는 걸 표방한 언어였으나 아이러니하게도 GC의 존재로 인하여 메모리 관리를 신경써야만 하는 언어가 된 것이다.

JVM 모니터링 클라이언트 VisualVM[5]과 그 플러그인 Visual GC를 설치하면 가비지 컬렉팅 상황을 시각적으로 확인할 수 있다. # VisualVM 디렉토리의 etc 폴더에 가면 visualvm.conf라는 파일이 있는데, 이 파일에 적혀 있는 visualvm_jdkhome 항목의 주석(#)을 제거한 후 JDK 폴더의 경로를 적으면 자신이 원하는 버전의 JDK로 모니터링이 가능하다.

GC의 상세한 동작 과정에 대해서는 이 문서를 참고할 것.

5. JVM 기반 언어[편집]


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

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

5.1. 기존 언어의 JVM 구현[편집]

5.2. JVM 기반의 언어[편집]

6. 관련 문서[편집]

[1] Kotlin이나 Scala, Groovy 같은 언어들[2] C, C++, Rust, Go[3] 이 부분이 매우 중요해서 JVM이나 .NET CLR 등 가상머신 기반에서 벤치마크를 돌릴 때는 1~5회 정도 웜업을 한 후에 측정한다.[4] 일반 프로그램 입장에서는 자기가 돌아가다가 가비지 컬렉션이 분별없이 끼어들면 자기가 쓰던 메모리가 갑자기 멋대로 바뀌었다고 볼 수밖에 없다. 일반 프로그램을 안 멈춰놓고 가비지 컬렉션 작업을 하다가 순서가 꼬이기라도 하면 프로그램 오류 확정.[5] 넷빈즈를 기반으로 만들어져 있다.