JAVA 메모리에 관하여
우리는 JAVA언어를 이용해 코드를 작성하고 실행하면서 어떻게 실행되는지 들여다본적이나 생각해본적이 있을까?
이런 궁금증으로 자세하게 찾아보게 되었다.
우선 JAVA 메모리 구조에 대해 알아보기 전 필요한 사전 지식에 대해 알아보자
JVM
JVM은 Java Virtual Machine의 약자이며, 자바 가상 머신이라고 부른다.
하는 일은 JAVA의 Byte코드를 해석하고 실행하는 역할이다.
특징으로는 os에 상관없이 JVM이 깔려있다면 어디서든 .java 파일을 실행할 수 있다.
JVM의 실행 순서
- 우선 .java 파일을 Compiler를 통해 .class파일로 변환한다.
- 변환된 .class파일을 JVM의 classLoader에게 전달한다.
- ClassLoader는 JVM의 런타임 데이터 영역으로 class파일을 로딩하여 메모리를 할당한다.
JVM의 런타임 데이터 영역
위의 마지막 과정에서 ClassLoader가 런타임 데이터 영역으로 class파일을 로딩한다고 하였다.
그럼 JVM안의 런타임 데이터 영역에 무엇이 있는지 알아보면
- Static(Method) 영역
- Heap 영역
- Stack 영역
- PC Register 영역
- Native Method Stack 영역
이중에서 자세하게 알아볼 것은 Static, Heap, Stack 영역이다.
위 영역을 알아보기 전에 잠깐 Java 변수에 대해 정리해보자
클래스 변수, 인스턴스 변수, 지역 변수
각 차이는 코드를 보면 감이 조금 잡히게 된다.
public class Variable {
public static int age = 20; // 클래스 변수(전역 변수)
int height = 60; // 인스턴스 변수(전역 변수)
public static void main(String[] args) { // 매개변수(파라미터)
int size = 50; // 지역변수
}
}
클래스 변수 (Static)
클래스 내부에서 Static 키워드로 선언된 변수이다.
특징으로는
1. 처음 JVM이 실행되어 클래스가 메모리에 올라갔을 때 부터 프로그램이 종료될 때 까지 살아있다.(유지)
2. 클래스가 여러번 생성되어도 static변수는 처음 딱 한 번만 생성된다.
3. 동일한 클래스의 모든 객체에서 접근이 가능하다. (공유 가능)
- 클래스 변수, 인스턴스 변수를 부르는 다른 말
전역변수(global variable), 멤버변수(member variable), 필드(filed)이며 셋다 같은 뜻이다.
인스턴스 변수(Non-static)
클래스 내부에서 Static 키워드가 작성되지 않은 변수이다.
여기서 햇갈리지 않게 instance의 뜻을 정의하고 갈 필요가 있다.
인스턴스(Instance) : 클래스를 통해 만들어진 객체
즉, 객체는 모든 인스턴스를 포함하는 포괄적인 단어이고 인스턴스는 해당 클래스에서 만들어진 "객체" 하나를 집어 말하는 것이다.
특징으로는
1. 객체 생성시마다 매번 새로운 변수가 생성된다.
2. 클래스 변수와 다르게 공유되지 않는다.
아직 개념적으로 햇갈릴 수 있기 때문에 예제 코드를 보면
실질적으로 변수의 값을 바꾸는 부분을 보면
staticTest1.classVar = 12;
staticTest1.instanceVar = 400;
인데 classVar(클래스 변수)의 특징은 class가 로딩될 때 딱 한 번 생성되어 공유가 가능하다.
하지만 static이 붙지않은 instanceVar (인스턴스변수)의 특징은 class가 로딩 될 때 계속해서 새로 생성됨으로 공유가 불가능하다.
그렇기에 실행 결과를 보면
1. 10, 28
2. 10, 28
1. 12, 400
2. 12. 28
클래스 변수는 동시에 바뀌었지만 인스턴스 변수는 하나만 바뀐 것을 볼 수 있다.
지역변수
우리가 가장 자주사용하는 변수형식이다.
클래스 내부의 메소드 블럭 안에 선언된 변수이다.
특징으로는
1. 메소드 호출부터 종료시점 동안 유지된다.
Static 영역, Heap 영역, Stack 영역
이제 각 변수가 저장되는 영역을 정리해보면
Static 영역
Static 영역 혹은 Method 영역이라고 불린다. 클래스 변수나, static 으로 선언된 것들이 해당 메모리 영역에 저장된다.
- JVM이 실행되어 Class 가 로딩될 때 생성.
- Class의 정보, Static 변수(클래스 변수), 생성자(Constructor), Static 메소드(Method)와 같은 것들을 저장한다.
- JVM이 종료 시(프로그램이 종료 시) 메모리에서 해제 된다. 즉 프로그램이 종료되기 전까진 메모리 상에 존재하게된다. 그렇기 때문에 어디서든 접근이 가능하다.
주의 사항 : 무분별 하게 사용될 경우 메모리 부족 현상이 발생할 수 있다.
Heap 영역
- JVM이 관리하는 프로그램 상에서 데이터를 저장하기 위해 런타임 시 동적으로 할당하여 사용하는 영역
- 참조형(Reference Type) 데이터 타입을 갖는 객체(인스턴스), 배열 등이 저장 되는 공간
- 단, Heap 영역에 있는 오브젝트들을 가리키는 레퍼런스 변수는 stack에 적재
- Heap 영역은 Stack 영역과 다르게 보관되는 메모리가 호출이 끝나더라도 삭제되지 않고 유지된다.
그러다 어떤 참조 변수도 Heap 영역에 있는 인스턴스를 참조하지 않게 된다면, GC(가비지 컬렉터)에 의해 메모리에서 청소된다. (마지막에 추가 설명) - heap은 몇개의 스레드가 존재하든 상관없이 단 하나의 heap 영역만 존재한다.
class Dodle{
public int a = 10;
public int b = 20;
}
public class Main{
static int all = 30;
public static void main(String[] args){
Dodle dodle = new Dodle();
}
}
위와 같은 코드가 있을 때 new로 생성된 인스턴스 Dodle 의 객체는 Heap 영역에 저장되고 참조하는 값인 dodle은 stack 영역에 저장된다. 또한 new로 생성된 인스턴스 안에 변수, 즉 인스턴스 변수도 Heap 영역에 저장된다.
Stack 영역
- 위에서 Heap 영역은 참조형 데이터의 실제 데이터를 저장하는 곳이라면 Stack은 참조 값을 저장하는 곳이다.
(위 코드에서 dodle을 Stack영역에 저장함) - 지역변수, 매개변수, 원시 자료형 (primary type)이 저장된다.
- 메소드가 실행되면 스택 영역안에 스택 프레임이라는 것을 만들고 그 안에 메소드를 호출한다.
- Stack은 Java의 자료구조 Stack의 LIFO(Last-In-First-Out)의 특성을 가진다.
- 메소드가 호출될 때 생성하고 메서드의 끝을 알리는 중괄호 } 를 만나면 삭제된다.
- 각 Thread 마다 자신만의 Stack 을 가진다. (1:1) - (Thread : Stack)
스택 프레임이란?
하나의 메서드에 필요한 메모리 덩어리를 묶어서 스택 프레임(Stack Frame)이라고 한다.하나의 메서드당 하나의 스택 프레임이 필요하며, 메서드를 호출하기 직전 스택프레임을 자바 Stack에 생성한 후 메서드를 호출하게 된다.스택 프레임에 쌓이는 데이터는 메서드의 매개변수, 지역변수, 리턴값 등이 있다.만일 메서드 호출 범위가 종료되면 스택에서 제거된다.
출처: https://inpa.tistory.com/entry/JAVA-☕-그림으로-보는-자바-코드의-메모리-영역스택-힙
[Inpa Dev 👨💻:티스토리]
모든 코드가 종료되면..
위에 Stack 영역은 메소드가 호출되고 호출이 끝나면 자동으로 삭제된다.
하지만 Heap 영역은 계속해서 남아있게 되는데 그럼 이때 GC(가비지 컬렉터) 라고 하는 친구가 와서 삭제하게 된다.
삭제하는 조건이 무엇일까??
힙 영역은 참조형 데이터의 실제 값이 존재한다. -> 즉, 나 자신을 가르키는 참조 값이 없다면 아무도 오지않는 무인도가 되어버린다.
이게 조건이다. 누구도 Heap에 있는 값을 참조하지 않는다면 GC가 삭제해버리게 된다.
추가
- 스택 메모리가 가득차면 자바에서는 java.lang.StackOverFlowError를 발생시킨다.
- 스택 메모리 사이즈는 힙 메모리와 비교했을 때 매우 적다.
하지만 스택 메모리는 간단한 메모리 할당 방법(LIFO)를 사용하므로 힙 메모리보다 빠르다.
마치며..
GC (가비지 컬렉터)에 대한 자세한 포스팅은 이곳이다.
https://dodledd.tistory.com/17
JAVA [GC, Garbage Collection] 정리본
가비지 컬렉션이란? 유효하지 않은 메모리들을 처리해주는 프로세스라고 보면 된다. 그럼 유효하지 않은 메모리는 무엇일까? 밑에 코드를 보면 public class ad { public static void main(String[] args) { num nu
dodledd.tistory.com