JVM (Java Virtual Machine) 메모리 구조

Posted by lib oimb
2018. 6. 25. 16:15 JAVA

JVM(Java Virtual Machine)은 자바 바이트 코드를 실행할 수 있는 주체이다. 구현시 인터프리터, JIT 컴파일 방식이 일반적이나 자바 프로세서 처럼 하드웨어와 소프트웨어를 혼합해 구현하는 경우도 있다.


자바 바이트코드는 플랫폼에 독립적이며 모든 자바 가상머신은 자바 가상 머신 규격에 정의된 대로 자바 바이트 코드를 실행한다.



(JVM 아기텍처 구요도)


- JAVA Source : 사용자가 작성한 JAVA 코드

- JAVA Compiler : JAVA 코드를 Byte Code로 변환시켜주는 기능

- Class Loader : Class파일을 메모리(Runtime Data Area)에 적재하는 기능

- Execution Engine : Byte Code를 실행 가능하게 해석해주는 기능

- Runtime Data Area : 프로그램을 수행하기 위해 OS에서 할당 받은 메모리 공간




하나씩 자세하게 살펴 보면


첫 번째 클래스 영역(매서드 영역)


1. 클래스 정보

- 클래스의 속성이 class 인지 interface 인지를 구분한다. 

- 클래스의 Super Class의 전체 이름 ( 여기서 interface 와 Object class 는 제외한다. 인터페이스는 인터페이스만이 상속 가능하며 Object는 최상위 클래스)

2. Static 변수

- Class Variable 이라고도 부른다.

- 모든 객체가 공유 할 수 있고, 객체 생성 없이 접근 가능하다.

3. 변수 정보

- 메서드의 이름 리턴타입 , 매개변수 , 접근제어자에 대한 정보

4. 상수 풀

- 클래스에서 사용된 상수를 저장하는 곳(중복시 기존의 상수 사용)

- symbolic reference ( 해당 객체가 존재하는 Heap영역으로 가기위한 객체의 이름 ,

Symbolic Reference는 참고하는 클래스의 특정 메모리 주소를 참조 관계로 구성한 것이 아니라 참조하는 대상의 이름만을 지칭한 것이다. Class 파일이 JVM에 올라가게 되면 Symbolic Reference는 그 이름에 맞는 객체의 주소를 찾아서 연결하는 작업을 수행한다. 실제 메모리 주소가 아니라 이름만을 가진다.)


5.  메소드 정보 

- 메서드의 이름, 리턴타입 ,매개변수 , 접근제어자에 대한 정보


public class JVM {

public static int a = 1;


public static void main(String[] args) {

AreaClass areaClass = new AreaClass();

System.out.println(a);
System.out.println("A 변경");
areaClass.chageA();
System.out.println(a);
}
}
class AreaClass {
void chageA() {
JVM.a=3;
}
}

결과:

1

A 변경

3



두 번째 스택 영역


- Last In First Out (LIFO)

- 메서드 호출 시마다 각각의 스택프레임(그 메서드만을 위한 공간)이 생성

- 메서드 안에서 사용되어지는 값들 저장, 호출된 메서드의 매개변수, 지역변수, 리턴 값 및 연산 시 일어나는 값들을 임시로 저장

- 메서드 수행이 끝나면 프레임별로 삭제

package kr.his.topic1;

public class JVM {
public static void main(String[] args) {
try {
System.out.println("stack 시작");
stack1();
System.out.println("stack 끝");
} catch (Exception e) {
e.printStackTrace();
}

}

static void stack1() {
System.out.println("stack1()");
stack2();
}
static void stack2() {
System.out.println("stack2()");
stack3();
}
static void stack3() {
System.out.println("stack3()");
int k=3/0;
}

}

결과:

stack 시작

stack1()

stack2()

stack3()

java.lang.ArithmeticException: / by zero

at kr.his.topic1.JVM.stack3(JVM.java:25)

at kr.his.topic1.JVM.stack2(JVM.java:21)

at kr.his.topic1.JVM.stack1(JVM.java:17)

at kr.his.topic1.JVM.main(JVM.java:7)



세 번째 힙 영역




- new 연산자로 생성된 객체와 배열을 저장하는 공간

- 클래스 영역에 로드된 클래스만 생성가능

- Garbage Collector를 통해 메모리 반환


1. Permanent Generation

- 생성된 객체들의 정보의 주소 값이 저장된 공간


2. New Area

- Eden : 객체들이 최초로 생성되는 공간

- Suvivor : Eden에서 참조되는 객체들이 저장되는 공간


3. Old Area 

- New Area 에서 일정시간이상 참조되고 있는 객체들이 저장되는 공간

public class JVM {
public static void main(String[] args) {
AreaHeap areaHeap = new AreaHeap();
areaHeap.call();
areaHeap=null;
if (areaHeap==null)
System.out.println("Garbage Collector 수행");
}
}
class AreaHeap{
void call(){
System.out.println("호출");
}
}

결과: 

호출

Garbage Collector 수행


네 번째 Native method stack area


- 자바 외의 다른 언어에서 제공되는 메서드들이 저장 되는공간


다섯 번째 PC Register


- Thread가 생성 될 때마다 생성되는 공간

- Thread가 어떤 부분을 어떤 명령으로 실행할 지에 대한 기록

- 현재 실행되는 부분의 명령과 주소를 저장


 


JVM의 메모리 영역 외에 추가적으로 Garbage Collection에 대해서 보면



- 참조되지 않은 객체들을 탐색 후 삭제

- 삭제된 객체의 메모리를 반환

- Heap 메모리의 재사용


 


① Minor Garbage Collection

 


i) New 영역에서 일어나는 Garbage Collection

ii) Eden영역에 객체가 가득 차게 되면 첫 번째 Garbage Collection 발생

iii) Survivor1 영역에 값 복사

iv) Survivor1 영역을 제외한 나머지 영역의 객체들을 삭제

v) Eden영역과 Survivor1영역의 메모리가 기준치 이상일 경우, Eden 영역에 생성된

객체와 Survivor1영역에 있는 객체 중 참조되고 있는 객체가 있는지 검사

vi) 참조되고 있는 객체를 Survivor2 영역에 복사

vii) Surviver2 영역을 제외한 영역의 객체들을 삭제

viii) 일정시간이상 참조되고 있는 객체들을 Old영역으로 이동

ix) 반복


 


② Major Garbage Collection (Full Garbage Collection)


 


i) Old영역에 있는 모든 객체들을 검사

ii) 참조되지 않은 객체들을 한꺼번에 삭제

iii) Minor Garbage Collection에 비해 시간이 오래 걸리고 실행 중 프로세스가 정지



이 댓글을 비밀 댓글로
    • 호이짜
    • 2018.06.27 14:12
    팩트 위주로 글을 쓴 느낌이 강합니다.
    개조식으로 보고서 식으로 쓴느낌이라 눈에 들어오지 않네요. 설명하는 느낌으로 다음번에는 글을 적어주면 좋을 것 같습니다.