오늘은 java의 메모리 영역에 대해서 공부해 보았다. 평소에도 java의 메모리 영역에서 간단하게는 알고 있었는데 좀 더 자세히 공부할 필요가 있다고 생각하여 글을 작성하게 되었다.
📚 JVM
java의 메모리 영역에 대해서 알기 전 JVM이라는 것에 대해서 알 필요가 있다.
JVM(Java Virtual Machine)이란 자바 가상 머신이며 Java의 바이트 코드를 해석하고 실행하는 역할을 한다. JVM은 OS로부터 메모리를 할당받고, 그 메모리를 용도에 따라서 여러 영역으로 나누어 관리를 한다.
이러한 JVM 덕분에 다양한 운영체제에서 java 파일을 실행할 수 있다.
JVM 실행 순서
- .java 파일을 컴파일러(Compiler)를 통해 .class 파일로 변환한다.
- .class 파일을 JVM의 ClassLoader(클래스로더)에게 보낸다.
- ClassLoader에서 JVM 런타임 영역으로 로딩(할당)하여 메모리에 올린다.
JVM의 RunTime Data Area(런타임 데이터 영역)
- Java 메모리 영역에는 총 5가지 영역이 있다.
- Static Area
- Heap Area
- Stack Area
- PC Register
- Native Method Stack
이 중에서 일반적인 자바 개발자가 가장 자주 접하게 되는 메모리 영역은 Static, Heap, Static 영역 등이 있다. 그래서 이 글에서는 3가지 영역에 대해서 작성해볼까 한다.
🎫 자바 변수의 종류
3가지의 메모리 영역을 소개하기 전에 자바 변수의 종류에 대해서 알고 가는 것이 좋을듯 하여 잠깐 알아보자.
public class Person {
private String name;
private static int age = 0;
public void setName(String name) {
this.name = name;
}
public int getNextYearAge() {
int next = 0;
return next + 1;
}
}
변수의 종류와 메모리 영역
| 변수명 | 선언위치 | 설명 |
|---|
클래스 변수 (class variable, static 변수) | 메소드 영역 | 클래스 영역에서 타입 앞에 static이 붙는 변수 객체를 공유하는 변수로, 여러 객체에서 공통으로 사용하고 싶을 때 정의 |
인스턴스 변수 (instance variable) | 힙 영역 | 클래스 영역에서 static이 아닌 변수 개별적인 저장 공간으로 객체/인스턴스마다 다른 값 저장 가능 ※ 객체/인스턴스 생성만 하고 참조 변수가 없는 경우 가비지 컬렉터에 의해 자동 제거됨 |
지역 변수 (local variable) | 스택 영역 | 메서드 내에서 선언되고 메서드 수행이 끝나면 소멸되는 변수 초깃값을 지정한 후 사용할 수 있음 |
매개 변수 (parameter) | 스택 영역 | 메서드 호출 시 '전달하는 값'을 가지고 있는 인수 (지역 변수처럼 선언된 곳부터 수행이 끝날 때까지 유효함) |
각 변수의 생성시기는 아래와 같다.
- 클래스변수 : 클래스가 메모리에 올라갈 때
- 인스턴스변수 : 인스턴스가 생성되었을 때
- 지역변수 / 매개변수 : 위치하고 있는 메서드가 수행되었을 때
🧱 Static(Method) 영역
- JVM이 실행된 후 클래스가 로딩될 때 생성된다.
- JVM이 읽어들인 클래스와 인터페이스에 대한 런타임 상수 풀, 클래스 변수(static 변수), 상수(final), 메소드(method) 등을 저장하는 공간.
- Static(Method) 영역에 있는 것은 어느 곳에서나 접근 가능
- Static(Method) 영역에 있는 데이터들은 프로그램이 종료할 때까지 메모리에 남아있다. 그래서 static 메모리에 있는 데이터들은 프로그래밍 종료될 때까지 어디서든 사용이 가능하다. 그러나 static 데이터를 무분별하게 많이 사용하게 되면 메모리 부족 현상이 발생하게 된다.
🧺 Heap 영역
- 참조형 데이터 객체(타입 -> String, 배열, Enum, Object)의 실제 데이터가 저장되는 공간이다. Stack 영역에서 실제 데이터가 존재하는 Heap 영역의 참조 값을 가지고 있다.
- new로 인스턴스를 생성할 때, Heap 영역에는 생성된 객체가 저장되며 Stack 영역에서 생성된 객체에 대한 주소 값(Reference)이 저장된다.
- 만일 참조하는 변수나 필드가 없다면 의미 없는 개체가 되기 때문에 JVM은 이것을 가비지 콜렉터(GC)를 실행시켜 자동으로 제거한다.
- 쓰레드가 몇 개가 존재하든, 단 하나의 영역만 존재한다. 그래서 동기화 이슈가 발생할 가능성도 있다.
🧾 Stack 영역
- primitive 타입의 데이터(int, double, byte, long, boolean 등)에 해당되는 지역변수, 매개 변수 데이터 값이 저장되는 영역이다.
- 변수는 메서드 호출 시 스택 프레임 내에 생성되며, 초기화되지 않으면 사용 불가하다.
- Heap 영역에 생성된 데이터의 참조값이 할당됨.
- 메소드가 호출될 때 메모리에 할당, 메서드 종료시 메모리에서 삭제됨.
- 자료구조 Stack의 구조이다, LIFO(Last In First Out).
- 각 스레드마다 자신만의 Stack을 가진다. (1:1) - (Thread:Stack). 각 Thread는 독립적인 Stack을 가지며, Heap과 Static 영역은 모든 Thread가 공유한다. 그러므로 Thread는 다른 Thread에 접근할 수 없지만, Static, Heap 영역을 공유하여 사용 가능.
참조
훌룽한 청년