CS

[JAVA] 자바 런타임 환경의 이해

자바 개발 키트(Java Development Kit, JDK), 자바 가상 머신(Java Virtual Machine, JVM), 자바 런타임 환경(Java Runtime Environment, JRE)은 자바 애플리케이션을 개발하고 실행하기 위한 자바 플랫폼의 3대 구성 요소다. JDK과 JVM에 대해서는 별도로 소개할 것이며, 이번 기사에서는 자바의 런타임 환경인 JRE에 대해 알아보자.


Credit: Michael Hicks(CC BY 2.0)

런타임 환경은 다른 소프트웨어를 실행하기 위해 고안되는 일종의 소프트웨어다. 자바용 런타임 환경인 JRE에는 자바 클래스 라이브러리(Java class libraries)와 자바 클래스 로더(Java class loader), 자바 가상 머신(Java Virtual Machine)이 포함된다.

- 클래스 로더는 올바르게 클래스를 로드해 코어 자바 클래스 라이브러리에 연결하는 역할을 한다.
- JVM은 자바 애플리케이션이 디바이스 또는 클라우드 환경에서 실행되는 데 필요한 리소스를 확보하도록 보장하는 역할을 한다.
- JRE는 주로 다른 구성 요소의 컨테이너이며 각 구성 요소의 활동을 조율하는 역할을 한다.

이제 각 구성 요소의 상호 작용 방식에 대해 좀더 깊게 알아보자.

 

JDK, JRE, JVM 설치하기
JDK를 다운로드하면 항상 호환 버전의 JRE가 포함되고 JRE에는 기본 JVM이 포함된다. JRE를 JDK와 별개로 다운로드할 수 있고 다양한 JVM 중에서 선택도 가능하지만 대부분의 구현에서는 기본값이 무난하다. 특히 자바를 처음 시작하는 경우 기본값을 사용하는 것이 좋다. 

 
런타임 환경이란
소프트웨어 프로그램을 실행하기 위해서는 실행할 환경이 필요하다. 런타임 환경은 프로그램 실행을 위해 클래스 파일을 로드하고 메모리 및 기타 시스템 리소스에 대한 액세스를 확보한다. 과거에는 대부분의 소프트웨어가 운영체제를 런타임 환경으로 사용했다.

프로그램은 해당 프로그램이 위치한 컴퓨터 내에서 실행됐지만 리소스 액세스는 운영체제 설정에 의존했다. 여기서 리소스란 메모리, 프로그램 파일, 종속성 등이다. 자바 런타임 환경은 적어도 자바 프로그램에 있어서는 이런 틀을 완전히 바꿔 놓았다.

 
자바의 WORA
"한 번 쓰고 모든 곳에서 실행한다(Write Once, Run Anywhere, WORA)"는 자바의 원칙은 처음 등장 당시 혁신적이었지만 지금은 대부분의 소프트웨어 시스템에서 표준으로 이 방식을 채택하고 있다.

 
자바 런타임 환경
소프트웨어는 시스템 하드웨어 위에 위치하는 일련의 계층으로 볼 수 있다. 각 계층은 그 위의 계층이 사용하거나 필요한 서비스를 제공한다. 자바 런타임 환경은 컴퓨터 운영체제 위에서 실행되면서 자바를 위한 부가적인 서비스를 제공하는 소프트웨어 계층이다.

JRE는 다양한 운영체제의 요철을 매끄럽게 다듬어 자바 프로그램이 거의 모든 운영체제에서 수정 없이 실행될 수 있도록 한다. 또한 운영체제를 기반으로 그 이상의 부가가치 서비스를 제공하기도 한다. 자동 메모리 관리(Automatic memory management)는 프로그래머가 메모리 할당과 재할당을 수동으로 조작할 필요가 없게 해주는 JRE의 가장 중요한 서비스 중 하나다.

간단히 말해 JRE는 자바 프로그램을 위한 일종의 메타 운영체제다. 추상화의 전형적인 사례로, 기반 운영체제를 자바 애플리케이션 실행을 위한 일관적인 플랫폼으로 추상화한다.

 
JRE와 JVM의 상호작용
자바 가상 머신은 라이브 자바 프로그램 실행을 담당하는 실행 소프트웨어 시스템이다. JRE는 자바 코드를 받아서 필요한 라이브러리와 결합한 다음 이 코드를 실행할 JVM을 시작하는 온디스크 시스템이다.

JRE에는 자바 프로그램 실행에 필요한 라이브러리와 소프트웨어가 포함된다. 예를 들어 자바 클래스 로더는 자바 런타임 환경의 일부다. 이 중요한 소프트웨어는 컴파일된 자바 코드를 메모리로 로드하고 적절한 자바 클래스 라이브러리에 이 코드를 연결한다.

앞서 언급한 계층의 시각에서 보면 JVM은 JRE에 의해 생성된다. 패키지 관점에서 보면 그림과 같이 JRE에 JVM이 포함된다.


Credit: Matthew Tyson

 
JRE 설치 및 사용하기
JRE에는 개념적인 측면이 있지만 실제 환경에서는 자바 프로그램 실행을 목적으로 컴퓨터에 설치되는 소프트웨어일 뿐이다. 개발자는 주로 자바 프로그램을 개발하고 실행하는 데 사용되는 플랫폼 구성 요소인 JDK, JVM을 다룬다. JRE는 자바 애플리케이션을 실행할 수 있게 해준다는 측면에서 자바 애플리케이션 사용자와 좀더 관계가 깊다.

대부분 자바가 설치된 상태로 컴퓨터가 제공되는데 JRE도 여기에 포함된다. 수동으로 설치하거나 업그레이드해야 하는 경우, 오라클에서 최신 JRE 버전을 다운로드할 수 있다.

 
JRE 버전
자바 런타임 환경은 자바의 각 새로운 버전에 맞춰 업데이트되며 버전 번호는 자바 플랫폼 버전 시스템을 따른다. 예를 들어 JRE 1.8은 자바 8을 실행한다. JDK 패키지는 선택의 폭이 넓지만(엔터프라이즈 에디션, 스탠다드 에디션 등) JRE는 그렇지 않다.

대부분의 컴퓨터는 어떤 방식으로 개발됐든 관계없이 모든 자바 애플리케이션을 실행할 수 있는 자바 SE용으로 개발된 JRE를 실행한다. 대부분의 모바일 디바이스에는 자바 ME용 JRE가 기본으로 제공된다. 이 JRE는 모바일 디바이스에 사전 설치되며 따로 다운로드는 할 수 없다.

JRE가 설치되면 명령줄에서 java -version을 입력해 설치된 버전을 확인할 수 있다. POSIX 시스템에서는 which java를 사용해 설치된 위치를 확인할 수 있다.

 
데브옵스와 JRE
JRE는 개발 단계에서는 운영체제 또는 IDE에서 프로그램을 실행할 뿐이므로 별로 눈에 띄지 않는다. 데브옵스와 시스템 관리 부문에서는 모니터링과 구성에 사용되므로 JRE의 역할이 조금 더 두드러진다.

기본적으로 JRE는 자바 애플리케이션의 특성을 구성하고 조작하는 데 사용할 수 있는 "노브(knobs)"를 제공한다. 시스템 관리의 꽃인 메모리 사용이 대표적인 예다. 메모리 사용은 항상 중요하지만 클라우드 구성에서는 특히 핵심적인 요소다. 또한 데브옵스는 클라우드 기반의 기술이다. 데브옵스 환경에서 작업하거나 데브옵스로의 진출에 관심이 있다면 자바 메모리의 작동 원리와 JRE에서 이를 모니터링하는 방법을 알아 두는 것이 좋다.

 
데브옵스 또는 시스템 관리란
데브옵스는 새로운 용어지만 데브옵스가 기술하는 내용, 즉 개발과 운영 간의 상호운용성은 수십 년 전부터 중요한 개념이었다. 이런 면에서 보면 데브옵스는 운영 또는 시스템 관리라고 불렀던 부분을 더 새롭게 표현하는 용어에 불과하다. 시스템 관리와 마찬가지로 데브옵스의 중요한 측면은 소프트웨어 실행에 필요한 시스템을 관리하는 것이다. JRE 관리는 자바 애플리케이션을 실행하는 시스템 관리의 일부분이다.
 

자바 메모리와 JRE
자바 메모리는 힙(Heap), 스택(Stack), 메타스페이스(Metaspace, 과거에는 펌젠(permgen)이라고 했음)의 세 가지 구성 요소로 이뤄진다.

- 메타스페이스는 자바가 클래스 정의와 같이 프로그램에서 변화하지 않는 정보를 저장하는 장소다.
- 힙 공간은 자바가 변수 내용을 저장하는 장소다.
- 스택 공간은 자바가 함수 실행 및 변수 참조를 저장하는 장소다.
 

자바 8의 메모리 관리
자바 8 이전까지는 메타스페이스 대신 펌젠이라는 용어가 사용됐다. 메타스페이스는 펌젠보다 훨씬 더 멋진 이름이라는 점 외에 개발자가 자바 메모리 공간을 다루는 방식에 있어서도 큰 변화를 가져왔다. 이전에는 java -XX:MaxPermSize 명령을 사용해 펌젠 공간의 크기를 모니터링했다.

자바 8부터는 프로그램의 메타 수요에 따라 자바가 자동으로 메타스페이스의 크기를 늘린다. 또한 자바 8에는 메타스페이스 크기를 제한하는 데 사용할 수 있는 새로운 플래그, MaxMetaspaceSize가 도입됐다. 다른 두 가지 메모리 옵션인 힙과 스택은 자바 8에서도 이전과 동일하다.
 

힙 공간 구성하기
힙 공간은 자바 메모리 시스템에서 가장 동적인 부분이다. -Xms  -Xmx 플래그를 사용해 힙의 시작 크기와 늘어날 수 있는 한도 크기를 지정할 수 있다. 자바 메모리 관리에서는 특정 프로그램의 필요에 맞게 이런 플러그를 튜닝하는 방법을 이해하는 것이 중요하다.

이상적인 구성은 가장 효율적인 가비지 수집을 달성할 만큼의 힙 크기다. 즉, 프로그램을 실행하기에 충분한 메모리를 허용하되 필요 이상으로 커지지 않도록 하는 것이다.
 

스택 공간 구성하기
스택 공간은 함수 호출과 변수 참조가 대기열에 들어가는 장소다. 스택 공간은 자바 프로그램에서 두 번째로 악명높은 오류인 스택 오버플로 예외의 원천이다(1위 오류는 널 포인터 예외).

스택 오버플로 예외는 스택이 너무 많이 예약되어 스택 공간이 바닥난 상황을 나타낸다. 일반적으로 스택 오버플로는 하나 이상의 메소드가 순환 형식으로 상호 호출하면서 스택 내에 함수 호출 수가 끊임없이 증가할 때 발생한다.

-Xss 스위치를 사용해 스택 시작 크기를 구성한다. 이후 스택은 프로그램 요구에 따라 동적으로 증가한다.
 

자바 애플리케이션 모니터링
애플리케이션 모니터링은 JVM의 기능이지만 JRE는 모니터링에 필요한 기준인 구성 옵션을 제공한다. 재바 애플리케이션 모니터링을 위한 툴은 고전적인 툴(예를 들어 유닉스의 top 명령)부터 오라클 인프라 모니터링과 같은 세밀한 원격 모니터링 솔루션에 이르기까지 다양하다.

실행 중인 JVM 검사를 위한 비주얼VM(VisualVM)과 같은 시각적 프로파일러 옵션도 있다. 이런 툴을 사용해 핫스팟, 메모리 누출을 추적하고 시스템의 전체적인 메모리 소비를 감시할 수 있다.
 

결론
자바 런타임 환경은 JVM에서 실행하기 위한 자바 애플리케이션을 로드하는 온디스크 프로그램이다. JRE는 자바 개발 키트를 다운로드할 때 기본적으로 포함되며 각 JRE에는 코어 자바 클래스 라이브러리, 자바 클래스 로더, 자바 가상 머신이 포함된다.

특히 클라우드와 데브옵스 환경에서 JVM, JDK, JRE가 어떻게 상호작용하는지를 이해하면 도움이 된다. JRE는 전통적인 자바 애플리케이션 개발보다는 클라우드 및 데브옵스 환경의 모니터링 및 구성에서 더 중요한 역할을 한다. editor@itworld.co.kr