보통 자바개발 서적들의 1장에 자바란? 같이 자바 language의 개요와 JVM에 대해 간략하게 나오지만..
그 마져도 대충 읽고 넘어갔었던 것 같다.
JVM의 내부를 모른다 해도, JVM이 어떤 형태로 동작하는지의 내부 동작원리를 알고 있다면 조금더 이해도 높은 개발은 물론이고 나아가서 만드는 프로그램의 성능을 더 높일수 있을 것이다. (리플렉션(Reflection)과 클래스 로더(Class Loader)를 이해하는데 도움도 됨)
그래서 이번장에는 JVM에 대해 정리해보려 한다.
자바가 다른 프로그래밍 언어와 확연히 구별되는 특징은 "Write once, run everywhere" (한번 작성하면, 어디서든 실행된다.) 라고 할수있다.
다른 언어의 경우 OS에서 제공하는 라이브러리들을 가져와서 써야하고 각 OS의 특성에 맞게 다시 개발하여야하는 문제점이 있었다.
이러한 문제점을 해결하기위해서 자바 프로그램은 JVM이라는 일종의 가상 서버에서 동작하도록 설계되었다.
그러므로 개발자들은 더이상 OS를 신경쓰지 않아도 되고, 공통된 라이브러리를 이용해서 개발에만 집중하는 것이 가능해졌다.
즉 자바언어는 JVM과 소통하고 JVM은 여러 OS들과 소통한다. (맥에서 개발한다면 맥용 JVM을 설치하면되고 윈도우에서 사용한다면 윈도우용 JVM을 설치하면된다) [Java language - JVM - OS]
JVM 내부구조.
JVM의 내부 구조를 큰형태로 분리해보면 클래스 로더 서스 시스템(Class Loader Subsystem), 실행 데이터 영역(Runtime Data Area) 그리고 실행 엔진(Execution Engine)으로 나눌수 있다.
1.클래스 파일
클래스 파일은 개발자가 만들거나 이미 만들어진 프로그램을 의미한다. 개발자가 개발하는 자바 프로그램은 .java 이며 이파일이 자바 컴파일러에서 컴파일 과정을 거치면 .class 파일이 생성된다.
이렇게 컴파일 과정을 거쳐 생성된 클래스 파일은 JVM에서 실행 가능하다. JAVA 프로그램은 하나 혹은 그 이상의 클래스 파일들로 구성이 되고 이들 클래스 파일이 서로 유기적으로 동작하면서 프로그램은 자기의 기능을 수행하게 된다.
2.클래스 로더 서브 시스템
자바 클래스파일은 위의 그림에서와 같이 OS에서 직접 동작하지 않고 JVM위에서 동작한다.
JVM은 실행할 클래스 파일을 읽고, JVM 메모리에 올려놓는 과정이 필요한데 이 과정을 클래스 로딩이라고 한다. 그리고 이 작업은 JVM의 클래스 로더 서브 시스템이 담당한다. 클래스 로더 서브 시스템을 줄여서 클래스 로더라고 부르며 클래스 로더는 다음과 같은 과정으로 JVM메모리에 클래스 파일을 로딩한다.
1. JVM에서 실행할 클래스 파일의 내부 구조를 분석한다.
어떤 메소드가 있는지 어떤변수가 선언되어 있는지 그리고 각각의 성격은 어떤지 모두 분석한다.
2. 분석된 내용을 바탕으로 성격에 따라 구분하고 각각 JVM의 적합한 메모리 영역에 데이터를 올려놓는다.
3. 분류된 데이터는 JVM의 특별한 메모리 영역에 저장되어 있다가 클래스가 실행되면 JVM의 실행 영역의
힙 메모리로 복사된다. 그리고 시스템 리소스를 활용해서 클래스를 실행 시킨다.
클래스를 분석하는 과정에서 클래스 로더는 자바 언어의 기능 중 하나인 리플렉션 기법을 사용하여 컴파일된 클래스의 내부를 분석한다.
자바는 클래스를 동적으로 로딩할 수 있는 구조를 가지고 있고 이를 동적 로딩(Dynamic loading)이라 한다.
프로그램을 실행하는 도중에 새로운 클래스를 로딩할 수 있음을 의미한다. 클래스 파일을 로딩하는 시점에 따라서 다음과 같이 나뉠 수 있다.
1. 로드타임 동적 로딩 : 프로그램 실행 초기에 클래스를 로딩하는 것.
2. 런타임 동적 로딩 : 프로그램 실행 중간에도 클래스를 로딩하는 것.
3.실행 데이터 영역
클래스 로더로부터 분석된 데이터를 저장하고 실행 도중 필요한 데이터를 저장하는 영역.
메모리에 올라간 클래스, 객체, 변수들이 저장되는 곳으로 크게 다섯개 영역(메소드,스택,힙,레지스터,네이티브메소드)으로 구분되어있다.
1. 메소드 영역
클래스 로더에 의해서 로딩된 클래스가 저장되는 곳.
클래스는 메소드와 클래스 변수로 구성되어 있는데 이를 클래스의 메타 정보라고 한다. JVM에서 클래스를 실행하면
메소드 영역에서 클래스 정보를 복사하고 힙 영역에서 메모리를 할당하여 실행한다.
JVM 메모리 영역중 가장 먼저 데이터가 저장되는 영역이다.
2. 스택 영역
클래스 실행은 곧 메소드 호출을 의미한다. 또한 메소드는 다른 메소드를 호출할 수 있다.
호출된(실행된) 메소드 정보가 저장되는 곳, 실행이 끝나면 저장된 정보는 삭제된다.
메소드가 실행될 때마다 저장되는 메소드 정보에는 매개변수, 지역변수, 복귀주소 등이있다.
이 영역에서는 스택을 데이터 관리 방법으로 사용한다(LIFO) 때문에 메소드의 호출정보나 호출 순서 등을 추적하기 편리하다.
3. 힙 영역
JVM의 실행 데이터 영역중 가장 중요한 역할을 담당한다.
객체는 클래스가 실행될 때 생성되서 힙 영역에 저장된다. (객체가 생성되면 힙영역에 할당됨) 그러므로 힙 영역은
JVM에서 가장 중요한 데이터를 저장함과 동시에 매우 세밀한 관리가 이뤄지는 곳이다.
힙 영역은 다시 여러개의 영역(Young, Permanent, Old)으로 나눠져있고 클래스 파일이 실행 되면 메소드 영역에서
클래스 정보를 복사하여 힙 영역에 실행할 클래스를 위한 메모리를 할당한다. 즉 힙 영역은 동적으로
데이터가 생성되고 소멸되는 영역이다. 그래서 JVM 성능 향상을 위해서 튜닝이 가능한 영역이기도 하다.
3-1. Young Generation
Young 영역은 다시 Eden, Servivor1, Servivor 2 영역으로 나뉜다.
이름에서 추측되듯이 각 영역들은 얼마나 데이터를 오랫동안 저장하고 있어야 하는지에 따라서 구분된다.
Young 영역은 프로그램 내부에 어떤 코드가 실행되면서 새롭게 생긴 데이터가 저장되는 부분이고, Young 영역의
데이터가 계속해서 사용되면 Old 영역으로 이동하게 된다. 그리고 Permanent 영역은 클래스에 대한 정보가
저장되는 곳이다.
JVM은 데이터의 목적과 수명에 따라서 저장 영역을 달리하여 관리하고 있다.
Young 영역에 저장된 데이터의 사용이 끝나고 일정 시간 동안 사용되지 않으면 그 데이터는 지워진다.
이때 힙 영역의 데이터를 지우는 것은 JVM의 일부분인 가비지 컬렉터(GC)다.
* 가비지 컬렉터가 데이터를 삭제하는 알고리즘은 힙의 세부 영역에 따라서 다르게 적용. (수행되는 빈도와 지우는 속도)
Young영역에 사용되는 가비지 컬렉터는 자주 그리고 빠르게 수행되는 알고리즘(Young영역 데이터 저장과 삭제 빈번)
3-2. Old Generation
빈번하게 사용되는 데이터가 Young 영역에서 Old 영역으로 이동.
Young 영역과 비교했을 때 Old 영역에서는 오랫동안 데이터가 보관된다.
Old 영역에서 실행되는 가비지 컬렉터의 알고리즘은 Young 영역보다 수행 횟수가 적으며 속도도 느리다.
(저장되는 기간이 길어짐)
3-3. Permanent Generation
클래스들의 정보가 저장되는 영역.
JVM에서 클래스 정보를 바탕으로 메모리 위에 객체를 빠르게 생성하기 위해 저장하는 곳.
힙 영역을 이렇게 세 가지 영역으로 나눠서 데이터를 저장하는 이유는
첫째. 보다 효율적으로 데이터를 관리하기 위함 - 자주 사용되는 데이터는 더 오랫동안 보관하여 전체적인 효율성 증대.
둘째. 가비지 컬렉터가 실행되는 동안에 발생하는 STW(Stop The World)를 줄이기 위해서다.
* STW : 가비지 컬렉터가 실행되는 동안 JVM의 다른 기능들이 잠시 멈추는 것을 의미. (가비지 컬렉터가 데이터를
지우는데 누군가 다시 그 데이터를 참조하려 할때 문제가 발행할수도 있기 때문)
따라서 STW가 자주 발생하면 그만큼 프로그램 실행 시간이 늘어나고 이는 성능 저하의 원인이됨.
4. 레지스터 영역
현재 JVM이 수행할 명령어의 주소를 저장하는 메모리 공간. (개발자가 특별히 개입할 필요가 없는 영역)
5. 네이티브 메소드 스택 영역
OS의 시스템 정보, 리소스를 사용하거나 접근하기 위한 코드로 보통 C, C++로 작성한다.
이러한 매개변수나 지역변수 등의 네이티브 메소드를 위한 영역으로 이에 대한 정보가 저장된다.
자바 프로그램과 OS 사이에 JVM이 존재하기 때문에 자바는 시스템에 직접 접근하기 어려운 형태다.
하지만 JNI(Java Native Interface) API를 사용하면 자바 프로그램에서 OS 시스템에 대한 접근이 가능하다.
이때 사용되는 네이티브 메소드들에 대한 정보가 네이티브 메소드 스택 영역에 저장된다.
참조.
자바를 다루는 기술.
'JAVA > 기본이 중요하지.' 카테고리의 다른 글
래퍼 클래스(wrapper class) (6) | 2016.05.23 |
---|---|
JDK 와 JRE 의 차이점. (0) | 2016.05.10 |
자바 언어 (java language) (4) | 2016.05.04 |
java null 키워드로 메모리 효율적으로 관리하기. (2) | 2016.05.04 |
댓글