Java의 저장 메모리 - Static, Heap, Stack

Java의 저장 메모리 - Static, Heap, Stack
muaga's avatar
Apr 30, 2024
Java의 저장 메모리 - Static, Heap, Stack
Java의 메모리는 RAM에 저장이 된다는 가정 하에 저장 메모리가 3개로 분류가 된다. 이것을 변수를 나누는 것 이라고 하는데, 메모리를 효율적으로 사용하기 위해 분류하는 것이다.
 

1. Static(정적 변수)


main 메소드가 시작되기 전, 이미 존재해야 하는 필수 메모리며 main이 종료되기 전까지 관리할 수 없는 메모리므로 신중히 저장한다. 주로 main 실행 처음부터 끝까지 존재해야하는 데이터를 저장한다.
  • class당 static 공간은 1개만 존재한다.
  • new( )를 사용하지 않아도, 클래스 자체와 연결되어 있기 때문에 바로 static 클래스의 메소드는 사용이 가능하다.
  • 정적 변수이므로 처음부터 존재하고 있을 수도 있으며, 처음에 존재하지 않더라도 main이 시작되기 직전에 존재해도 괜찮다.
  • static 안에 heap 변수를 넣을 수 없다.
 
✔️ 예시
커피 빨리 마시는 대회에서 대회가 시작되기 전 준비되어 있는 커피 머신과 기록을 적어 놓을 전광판
 
public class MyStar01 { public static void main // static이 붙어야 static에 저장되고 실행된다. // static + main 명칭이 있어야 해당 프로젝트의 실행 - 종료가 된다. - JVM이 프로그래밍을 시작할 때 MyStar01 - static - 'main'을 찾아 실행한다. - class가 없는 언어는 static이 없다.
 

2. Heap(동적 변수)


프로그램이 실행되기 위한 메모리로, 관리가 가능하고 상대적으로 큰 메모리 공간을 할당받는다.
  • 애플리케이션에서 생성된 객체와 배열을 저장하는 메모리 영역이며, 객체는 클래스의 인스턴스로서 new( )를 통해 heap 영역에 저장된다. 또한 클래스의 static 변수도 heap에 저장된다.
  • 여러 개의 객체가 동일한 클래스를 기반으로 생성되더라도, heap 영역에는 개별 객체들의 데이터와 상태가 저장된다.
  • 객체는 각자의 메모리 공간을 가지고 있으며, 인스턴스 변수의 값이 객체마다 별도로 유지된다.
  • 각 클래스 내부에 속해 있으며, JVM 프로세스당 하나의 heap을 가지고 있다.
  • 여러 스레드 간에 공유되는 데이터가 저장되는 영역이다.
 
✔️ 예시
대회가 시작되면서 참여하는 사람들, 기록을 위해 필요한 커피
 
class Cal02 { void add(int n1, int n2) { System.out.println("더하기 : " + (n1 + n2);} // static이 없는 메소드가 class 안에서 실행될 때 heap에 저장된다.
 

3. Stack(동적 변수 - 지역 변수 - 로컬 변수)


메소드 호출과 관련된 메모리로, 메소드의 코드 블록이 실행되면 스스로 사라지는 유지시간이 짧은 메모리다. 메소드가 시작하면서 기록이 되고, 종료 시 사라지는 데이터를 저장한다.
  • 메소드 내부에 속해 있다.
  • 각 스레드마다 별도의 stack이 생성된다.
  • 메소드의 코드 블록을 실행하기 위해 존재한다.
  • heap 보다 존재하는 시간이 상대적으로 짧다.
  • stack은 실행되면 스스로 사라지기 때문에 관리를 할 필요가 없다.
 
✔️ 예시
참가자 1이 커피를 마시기 시작한 시간 + 다 마신 시간 + 걸린 시간(연산 : CPU가 진행) + (커피)결과 이 모든 것이 stack에 저장되며 대회에 중요한 '결과'만 static에 있는 전광판에 이동하고 그 외 모든 것이 사라진다.
 
class sum { int n1 = 7; int n2 = 3; System.out.println("더하기 : " + (n1+n2)) } // stack에 저장된 값은 int n1, n2 // sum 클래스 실행 시 stack에 7, 3의 8byte만 저장되고, sum 실행이 종료되면 // 7, 3의 8byte는 사라지고 sum에 빈 공간이 생긴다.
 

❔실행된 데이터를 Stack이 아닌 Heap에 저장하고 싶다면

  1. 'return'을 이용
  1. 'this'를 이용
  • 메소드 내부 stack - 같은 class의 heap에 접근 가능 ➡️ 'this' 사용
  • 매소드 내부 stack - 다른 class와 다른 heap에 접근 불가능 ➡️ 만약 접근하고 싶다면 '인수(매개변수)'로 전달해야 한다.
  • 매소드 내부 stack - 다른 stack 접근 불가능
 

4. 예시로 보는 Static, Heap, Stack


4.1. 예시를 결과로 남은 메모리

  • static - 커피머신, (커피)기록, 전광판
  • heap - 참가자 1, 2, 3 ......, 커피 1, 2, 3....
  • stack - 실행을 위한 행위는 모두 삭제
그런데 실행 속도를 빠르게 하기 위해서 RAM의 불필요한 메모리는 삭제를 해줘야 한다. 최종적으로 대회가 끝마치려면 참가자와 커피는 현재 메모리로 필요 없기 때문에 삭제해줘도 된다.
 
⚠️ 주의할 점
대회가 끝나도 상을 줘야 하므로, 전광판에 (커피) 결과 뿐만 아니라 참가자의 인적 사항 등도 전광판에 정리해서 메모리를 저장해두면 heap 영역의 참가자들이랑 커피는 삭제해줘도 된다.
 

4.2. 진행 코드

class Hello { static int price = 20000; String dringName = "커피"; public void order() { int n1 = 2; System.out.println(n1 + "잔을 주문한다."); } } class Mem01 { int time = 10; static String orderName = "홍길동"; } public class Memory { static int price = 10000; public static void main(String[] args) { System.out.println(price); // static은 main이 시작되기 전에 이미 static에 저장되어 있는 값이다. System.out.println(Mem01.orderName); System.out.println(Hello.price); // orderName와 price는 static 변수라서 new할 필요가 없다. System.out.println(Mem01.time); // time은 static 변수가 아니라서, Mem01 클래스를 new한 후 메소드 사용이 가능하다. Mem01 mem01 = new Mem01(); // 위의 Mem01.int를 사용하고 싶으면 먼저 인스턴스 선언하여 객체를 생성해야 Mem01의 메소드 사용이 가능하다 Hello hello = new Hello(); hello.order(); // hello 참조변수는 n1 = 7의 값이 저장되어 있는 주소 => stack // Hello 는 n1 = 7의 값이 저장되어 있는 곳 => heap } }
Share article

muaga's Hub