Programming language/Java

[Java]JVM 메모리 구조

  • -
반응형

자바의 장점은 OS에 영향을 받지 않는다는 것이 아닐까 생각한다.

자바로 작성된 프로그램은 JVM만 있다면 실행이 가능하다.

 

JVM(Java Virtual Machine)

JVM이란 Java Virtual Machine(자바 가상 머신)의 약자로 자바와 OS 사이의 중계자 역할을 한다.

JVM은 자바 바이트 코드(Byte Code)를 OS에 맞게 해석해준다. 이것이 자바가 OS로부터 독립적이고 JVM에 종속적이게 되는 이유이다.

(바이트 코드는 기계어가 아니기 때문에 OS에서 바로 실행되지 않고 JVM이 OS가 바이트 코드를 이해할 수 있도록 해석해 주는 것이다)

 

JVM의 메모리 구조는 아래와 같다.

 

 

 

① Javac(Java compiler)

: 프로그램이 실행되면 Javac(Java compiler)는 java 파일을 class 파일이라는 자바 바이트 코드로 변환시켜준다.

 

② Class Loader

: class 파일은 Class Loader를 통해 메모리(Runtime Data Area)에 로드된다.

 

③ Runtime Data Area

: JVM의 메모리 영역으로 자바 프로그램을 실행할 때 사용되는 데이터들을 적재하는 영역.
각각의 영역은 아래와 같이 정의한다.

 

☞ Method Area(메소드 영역)

- Class Area로 불리기도 한다.

- 클래스 파일을 읽어서 클래스에 대한 정보를 이곳에 저장한다.

- 인스턴스 변수, 클래스 변수, 메소드 코드 등이 저장된다.

 

☞ Heap Area(힙 영역)

- 인스턴스가 생성되는 공간으로서 new 연산자로 생성된 객체와 배열을 저장하는 공간.

- Garbagae Collector가 참조되지 않는 메모리를 확인하고 제거하는 영역이다.

- 힙 영역의 참조 값을 스택 영역의 객체가 갖고 있다.(아래 힙과 스택의 관계에서 자세히 알아보자)

 

☞ Stack Area(스택 영역)

- 메소드가 호출될 때 스택구조로 메모리가 할당되는 공간.

- 기본 자료형(int, float, double, long, short, char, byte, boolean)에 해당되는 지역변수 및 매개변수의 데이터값이 저장된다.(그 외에는 참조 변수이다)

- LIFO(Last In First Out)의 구조로 새로운 변수가 할당되면 이전 데이터는 지워진다.

 

☞ PC Register

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

- 현재 수행중인 JVM 명령 주소를 갖는다.

 

☞ Native Method Stack

- 자바 이외의 다른 언어에서 제공되는 메소드의 정보가 저장되는 공간.

 

 Execution Engine

Class Loader를 통해 Runtime Data Area에 배치 된 클래스의 바이트 코드를 실행하는 런타임 모듈.

JVM은 메소드 영역의 바이트 코드를 Execution Engine에 제공하여 클래스에 정의된 내용대로 실행하게 된다.

 

Execution Engine이 바이트 코드를 실행하는 방식은 2가지로 나눌 수 있다.

⑴ 바이트 코드를 한 라인씩 읽고 해석하는 인터럽트 방식

⑵ 바이트 코드를 어셈블러 같은 Native 코드르 변경되어 수행하는 JIT Compiler 방식

 

⑤ Garbage Collector(GC)

 : JVM은 OS로부터 메모리를 요청하는데 JVM이 할당받은 메모리를 사용하다가 메모리 용량이 부족하게 되면 OS에게 메모리를 더 요청한다. 그럼 OS는 JVM에게 부족하지 않게 메모리를 더 부여한다. Garbage Collector는 JVM이 OS에게 메모리를 더 요청할 때 실행된다.

 인스턴스가 생성되면서 Heap 영역에 메모리를 차지하는데 JVM이 더이상 사용되지 않는 인스턴스를 판단하여 자동으로 할당된 메모리를 삭제하는데 Garbage Collector가 이 역할을 하는 것이다.

(GC에 대해서는 좀 더 깊게 공부해서 정리해봐야겠다...)

 


 

Heap과 Stack의 관계

 

String mydrink = new String("Americano"); 라고 작성할 때 mydrink는 스택 영역에 저장되고 실행시 주소를 알려준다.

new 연산자로 생성한 인스턴스는 힙 영역에 저장되고 참조 변수 mydrink를 리턴받는다. 즉, 실제 값은 힙 영역에 있는 것이고 스택 영역에는 실제 값을 참조하는 주소(참조 변수)가 있는 것이다.

그래서 스택 영역의 참조 값으로 힙 영역의 인스턴스를 핸들할 수 있는 것이다.

 

코드를 보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package biz.test;
 
public class Cafe{
 
    public static void main(String args[]) {                        
        String mydrink = new String("Americano");
        String yourdrink = new String("Americano");        
        
        System.out.println(mydrink);   
        System.out.println(yourdrink); 
        
        if(mydrink == yourdrink){
            System.out.println("true");
        } else {
            System.out.println("false");        
        }
        
        if(mydrink.equals(yourdrink)){
            System.out.println("true");
        } else {
            System.out.println("false");        
        }
    }
}
cs


 


 

12번 라인에서 mydrink와 yourdrink의 비교값이 false로 나온 이유는 힙 영역에 생성된 String mydrink와 String yourdrink의 주소값이 다르기 때문이다.(참고로 '==' 연산자는 대상의 주소값을 비교한다)

 

때문에 true의 값을 얻기 위해서는 18번 라인과 같이 equals() 메소드를 이용해야 한다.

equals 메소드는 대상의 내용을 비교하는 것이기 때문이다. 


+ 피드백은 언제나 환영입니다 :)


 

반응형

'Programming language > Java' 카테고리의 다른 글

[Java]try catch finally  (0) 2018.08.17
[Java]Split 함수  (0) 2018.08.13
[Java]인스턴스(Instance)  (0) 2018.08.09
[Error]java.lang.ArrayIndexOutOfBoundsException  (0) 2018.08.09
[Java]생성자(Constructor)  (0) 2018.08.08
Contents

포스팅 주소를 복사했습니다.

이 글이 도움이 되었다면 공감 부탁드립니다.