본문 바로가기

Java

[Java] 자바 메모리 구조에 대한 공부 (Heap,Stack,Method)

jvm 영역에 대해서 공부를 했다. 공부를 하면서 자바 메모리 구조에 대하여 공부하겠다.

 

간단하게 Runtime Data Area를 다시 보면 위 그림과 같다.

여기서 Heap, Stack, Method의 구조와 영역에 대해서 공부할 것이다. 

 

일단 자바에 변수에 대해서 알아야 한다. 자바의 변수는 아래 코드와 같이 나누어 진다.

public class Shop{
    public static int count = 10; // 클래스 변수
    
    public int inventory = 100; //인스턴스 변수
    
}


public class Main {

    public static void main(String[] args) {//매개 변수

        //지역 변수
        int wieght = 20;

    	Shop sh = new Shop(); // 객체를 생성한다.
        
        System.out.println(Shop.count); //10 -> 클래스 변수
        System.out.println(sh.inventory); //100 -> 인스턴스 변수
    	System.out.println(weight); //20 -> 지역 변수

    }
}

여기서 변수의 선언 위치와 static의 사용 여부에 따라서 변수의 종류가 달라지게 된다.

 

클래스 변수

타입 앞에 static이 붙은 변수. 인스턴스와 무관하게 클래스에 바로 접근하고 사용하는 게 가능하다. 프로그램이 시작할 때 딱 1개만 만들어지고 여러 곳에서 공유하는 목적으로 사용된다.

인스턴스 변수

클래스 영역에서 static 아닌 변수, static이 붙지 않은 멤버 변수는 인스턴스를 생성해야 사용할 수 있고, 인스턴스에 소속되어 있다.

매개 변수

메서드 호출 시 전달하는 값을 가지고 있는 변수이다.

지역 변수

메서드 내부에서 선언된고 수행이 끝나면 소멸되는 변수. 초기 값을 지정해야 사용이 가능하다.

static

static은 정적인, 고정된이라는 뜻을 가지고 있다. 이러한 어떤 객체에 소속되는 것이 아닌, 클래스에 고정되어 있는 변수나 메서드이다. 할당된 메모리는 모든 객체가 공유하여 어디서든지 참조가 가능하다.

static 키워드는 heap영역이 아닌 static 영역에 할당되기에 Garbage Collector로 삭제되지 않고 프로그램의 종료 시까지 남아 있다. 

 

 

우리는 이제 기본적인 정보를 알고 있다. 이제 위에 코드를 기준으로 그림으로 구조에 대해서 공부할것이다. 

 

위 그림은 메모리 구조(Stack, Heap, Method영역)를 그림으로 표현한 것이다. 우리 맨 위에 코드를 기억해 보자 main클래스를 실행한다고 생각해 보자

 

맨 처음 클래스가 로딩이 되면 static 변수를 다 읽는다. 위 그림처럼 Method 영역에 static변수가 만들어진다. 여기서 Method 역영의 생성된 것들은 프로그램을 종료할 때까지 메모리가 남아있고 어디서든 사용이 가능하다. 하지만 Method  영역은 GC으로 삭제대상이 되지 않아서 남용할 경우에는 메모리 부족현상이 일어나기에 남용을 주의해야 한다.

 

여기서 main 메서드를 실행하게 된다. 위 그림처럼 main() 메서드는 args [](매개변수)와 wieght(지역변수)를 가지고 Statc Area에 스택프레임이 생성된다.

 

 

Shop sh = new Shop()을 통해서 인스턴스를 생성하는데 위 그림처럼 Shop 인스턴스가 inventory(인스턴스 변수)을 가지고 heap영역에 생성된다. 

 

System.out.println(Shop.count) 라인이 실행될 때 위 그림처럼 Method Area영역에 static int count를 사용한다. 그래서 우리는 count을 사용할 때 Shop.(클래스)을 붙여서 실행한다. 그리고 10의 값을 얻는다.

System.out.println(sh.inventory) 라인이 실행될 때는 Shop 인스턴스의 inventory(인스턴스 변수) 값을 사용했기에 inventory를 사용해 때 sh.(인스턴스)을 붙여서 실행된다. 그리고 100의 값을 얻는다.

System.out.println(weight) 라인이 실행할 때는 weight(지역변수) 값을 사용하다.

마지막 코드가 실행되고 }(닫는 중괄호)를 만나면 main() 스택 프레임을 제거한다. 하지만 위 그림처럼 Heap영역에 Shop 인스턴스는 남아있다.

위처럼 Garbage Collector가 힙영역에 있는 참조되지 않는 인스턴스를 찾아서 삭제한다. 코드 실행이 모두 끝나면서 Method 영역도 비워진다.

 

 

Stack과 Heap영역이 어떻게 구성되어 있는지에 대한 글은 다음에 적도록 하겠습니다.

 

혼자 공부하는 것이다 보니 틀린 정보가 있을 수 있습니다. 틀린 부분이 있다면 댓글 달아주세요. 글을 읽어주셔서 감사합니다.

 

 

출처

https://www.inflearn.com/course/%EA%B9%80%EC%98%81%ED%95%9C%EC%9D%98-%EC%8B%A4%EC%A0%84-%EC%9E%90%EB%B0%94-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard

https://j-growthdiary.tistory.com/entry/%EB%B3%80%EC%88%98%EC%9D%98-%EC%A2%85%EB%A5%98%ED%81%B4%EB%9E%98%EC%8A%A4-%EB%B3%80%EC%88%98Static-%EB%B3%80%EC%88%98%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-%EB%B3%80%EC%88%98%EC%A7%80%EC%97%AD-%EB%B3%80%EC%88%98

https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EA%B7%B8%EB%A6%BC%EC%9C%BC%EB%A1%9C-%EB%B3%B4%EB%8A%94-%EC%9E%90%EB%B0%94-%EC%BD%94%EB%93%9C%EC%9D%98-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EC%98%81%EC%97%AD%EC%8A%A4%ED%83%9D-%ED%9E%99