JAVA

JVM 메모리 구조 및 변수 적재 위치

k9e4h 2020. 12. 14. 23:31

자바 응용프로그램이 시작되면, 자바 가상 머신(Java Virtual Machine, JVM)은 프로그램 수행에 필요한 메모리를 할당 받고, 이 메모리를 관리합니다.

 

 

Java에서 변수는 크게 전역변수, 지역변수로 구분되며 전역변수는 클래스 변수, 인스턴스 변수로 세분화됩니다.

변수의 종류를 결정짓는 요소는 변수가 어느 위치에 선언됐느냐에 따라 변하게됩니다.

 

 

변수의 종류 선언 위치 생성 시기 특징
전역변수
=멤버변수
=필드
클래스 변수
(=Static변수)
클래스 영역 클래스가 메모리에 올라갈 때

- static 메모리에 생성
- 프로그램 실행시 생성, 종료시 소멸
- 변수의 초기화 지원(초기화 필요 없음)

인스턴스 변수
(=객체변수)
인스턴스가 생성되었을 때

- heap 메모리에 생성
- GC에 의해 메모리 소멸

지역변수 클래스영역 이외의 영역
(메서드, 생성자, 초기화 블럭 내부)
메소드 블럭 안에서 변수 선언문이 수행되었을때

- 메서드 수행시 메모리에 생성
-
stack 메모리에 생성
- 초기화가 안되므로 초기화 후 사용가능
- 메소드 종료시 메모리에서 소멸

class Test {  

  int AAA; // 인스턴스 변수  
  static inst BBB; // 클래스 변수(또는 static 변수, 공유 변수)  
  
  void method(){    
  	int CCC=0; // 지역변수  
  } // 메서드 영역
  
} // 메소드 포함 전체가 클래스 영역

 

1. 전역변수

1-1. 클래스 변수

static이 붙은 변수 

인스턴스마다 독립적인 저장공간을 갖는 인스턴스 변수와는 달리, 클래스변수는 모든 인스턴스가 공통된 저장공간(변수)를 공유하게된다.

한 클래스의 모든 인스턴스들이 공통적인 값을 유지해야하는 경우 클래스 변수로 선언하여 사용

1-2. 인스턴스변수

클래스 영역에 선언되며, 클래스의 인스턴스를 생성할때 만들어진다. 인스턴스는 독립적인 저장공간을 가지므로 서로 다른 값을 가질 수 있다. 인스턴스마다 고유한 상태를 유지해야하는 경우 인스턴스 변수로 선언하면 되겠다.

2. 지역변수

메소드 블럭 안에 선언된 변수로 메소드의 블럭이 끝나는 순간 생명이 다한다.

메서드 내에 선언되어 메서드 내에서만 사용 가능하다.

for문 또는 while문의 블럭 내에 선언된 지역변수는 지역변수가 선언된 {}블럭 안에서만 사용 가능하며, {}블럭을 벗어나게 되면 소멸되어 사용할 수 없게 된다.

 

 

클래스 메서드에서는 인스턴스 변수와 관계없이 매개 변수로만 작업이 가능,

클래스 메서드는 인스턴스 변수를 사용하지 못함.

클래스 메서드에서는 클래스 변수만 사용가능,인스턴스 메서드에서는 클래스 메서드 및 인스턴스 변수 사용 가능

 

인스턴스 변수를 사용하기 위해서는 인스턴스가 생성되어 있어야한다. 이것은 사용자가 생성을 했을 때 만들어지는 것이다.  static이 붙은 것은 자동으로 생성이 된다. 

자동으로 생성된 static은 있을지 없을지 모르는 인스턴스를 갑자기 부를 수는 없다.

같은 클래스 내에서 static 메서드가 인스턴스 메서드를 호출해야 하는 경우에는 클래스 객체를 생성해서 호출하면 된다.

 

 

 

 

메소드 영역 (Method area)

1. 프로그램 실행 중 어떤 클래스가 사용되면, JVM은 해당 클래스의 클래스 파일 (.class) 파일을 읽어 클래스에 대한 정보를 저장합니다. Class Variable도 함께 저장하는데 그것은 Static Variable과 같습니다. 어디서든 공유해 쓸 수 있는 변수를 의미합니다.

2. 프로그램 실행 중 사용 되는 Class 파일을 JVM이 읽어 클래스에 대한 정보를 저장.
해당 클래스의 클래스 변수도 함께 저장

 

호출 스택 (call stack)

1. 메서드의 작업에 필요한 메모리 공간을 할당합니다. 메서드가 호출되면 스택에 호출된 메서드를 위한 메모리가 할당되고, 이 메모리는 메서드의 연산의 중간 결과, 지역변수, 매개변수 등을 저장하는데 사용합니다. 그리고 메서드의 작업을 마치면 메모리 공간을 반환합니다.

2. 메소드 작업에 필요한 메모리 할당. 매개변수, 지역변수, 연산 중간결과 등을 저장.

메소드가 작업을 마치면 메모리 반환

 

힙 영역 (heap)

1. 클래스의 인스턴스와 배열이 저장되는 공간입니다. 프로그램 중 생성된 인스턴스는 모두 이곳에 저장됩니다. 인스턴스 변수도 생성됩니다.

2. 인스턴스가 생성되어 저장되는 메모리 영역. 인스턴스 변수 포함

 



static 영역

  • 패키지나 클래스 정보가 올라갑니다. 
  • 패키지나 클래스는 프로그램 시작과 동시에 모두 올라가는 것이 아니라, 실제로 호출 될 때 올라가게 됩니다. (JVM은 영리합니다.)
  • static이라는 키워드를 붙여서 선언된 필드와 메소드인 '클래스 멤버'도 static 영역에 올라갑니다. static 영역에 있는 것은 어떤 곳에서나 접근이 가능해지기 떄문에 '전역'이라는 키워드를 사용합니다.
  • 그러므로, static (전역) 변수는 읽기 전용이 아닌 경우에는 가능한 사용하지 말아야 합니다. (누구나 접근해서 값을 수정하면 혼란을 가져 올 수 있기 때문)
  • class영역 혹은 method 영역 이라고도 불립니다.
  • static 영역에 자리잡게되면 JVM이 종료 될 때까지 사라지지 않고, 고정된(static) 상태로 유지됩니다.

stack 영역

  • 여는 중괄호 '{'를 만날 때 마다 스택 프레임이 하나씩 생기고, 닫는 중괄호 '}'를 만나게 되면 스택 프레임이 사라집니다. 그러므로 메소드가 실행될 뿐 만 아니라, if문, 반복문, 예외처리를 위한 try문 등도 모두 스택프레임이 생기게 됩니다.
  • stack 내부에서 선언된 지역변수는 stack 영역에 올라갑니다.
  • 기본형 타입 변수의 값들은 stack영역에 저장되고, 참조형 타입 변수는 참조값만 저장됩니다. (이 참조값은 heap 영역에 존재하는 인스턴스(객체)를 가르키는 역할을 합니다. 엄격한 표현은 아니지만 인스턴스(객체) 주소값 정도로 이해하셔도 됩니다.)
  • 외부 스택 프레임에서는 내부 스택 프레임의 변수에 접근 하는 것은 불가능하나 그 역은 가능합니다. 쉽게 생각하면 메소드안에 for문 스택 프레임을 만든 경우, for문에서는 자신을 호출한 메소드의 변수는 사용가능하나, 메소드에서는 for문에서 선언한 변수를 사용 할 수 없습니다. 
  • + 메소드를 호출하는 것은 별개의 스택프레임 이기 때문에 스택 프레임을 넘어서 접근할 수 없습니다.
  • 쓰레드도 stack 영역에 생기게 됩니다. 하나의 쓰레드는 내부적으로 별개의 T메모리 구조 static, stack, heap영역을 갖게 됩니다. 이런 이유로 하나의 쓰레드는 다른 쓰레드로 접근 할 수 없지만, static 영역과 heap 영역은 공유해서 사용 할 수있는 특징을 가지게 됩니다. (이런 특징이 멀티 프로레스 구조보다 멀티 쓰레드 구조가 메모리를 적게 사용 할 수 있는 이유입니다.)

heap 영역

  • 생성된 객체(인스턴스)들이 올라갑니다.
  • 인스턴스 필드들은 heap 영역에 올라갑니다. (이러한 이유로 static한 메소드에서 인스턴스 멤버를 접근할 수가 없는 겁니다. 어떤 인스턴스 인지도 알 수 없고, 존재하지도 않을 수도 있는 인스턴스를 사용하라는 것이기 떄문입니다.)
  • 메소드들은 static이 아니더라도 굳이 heap에 생기지 않습니다. 어차피 같은 로직의 메소드이기 때문에, 여러개 일 필요가 없습니다. (JVM은 영리합니다.)
  • stack영역에서 참조값을 이용하여 참조형 변수가 heap 영역에 있는 인스턴스를 가르키어 제어 할 수 있게 됩니다.
  • 어떤 참조 변수도 힙영역에 있는 인스턴스를 참조하지 않게 된다면, GC(가비지 컬렉터)에 의해 메모리에서 사라지게 됩니다.
  • 상속을 이용한 인스턴스를 만들었다면 상위 클래스들의 인스턴스들도 같이 생성됩니다. (최상위인 Object까지)

 

[출처]

siyoon210.tistory.com/124

lion-king.tistory.com/58

mainpower4309.tistory.com/4

https://itmining.tistory.com/21

itmining.tistory.com/21

blog.naver.com/withyou_ai/120105445756

janggiraffe.tistory.com/entry/JAVA-%EB%B3%80%EC%88%98%EC%99%80-%EB%A9%94%EB%AA%A8%EB%A6%AC

tcpschool.com/c/c_memory_structure

sujinhope.github.io/2021/03/03/Java-%ED%81%B4%EB%9E%98%EC%8A%A4%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%B0%A8%EC%9D%B4(Static%EB%B3%80%EC%88%98%EC%99%80-Non-Static%EB%B3%80%EC%88%98).html

반응형

'JAVA' 카테고리의 다른 글

LogBack Log4J  (0) 2021.03.15
[JAVA] Builder Model  (0) 2021.01.07
Java 성능 관리  (0) 2020.12.09
[Java] boolean, Boolean  (0) 2020.07.21
모던 자바 인 액션 내용 정리  (0) 2020.07.21