-
[JAVA] JVM 메모리 구조LANGUAGE/JAVA 2014. 4. 24. 15:00
- JVM에서 실행되는 모든 프로그램들(스레드)들은 메소드 영역과 힙 영역을 공유하게 된다.
- 메소드 영역은 클래스 내의 메소드에 해당하는 바이트코드와 클래스 변수 등이 저장되는 영역이며,
- 힙영역은 프로그램의 실행 중에 생성된 객체를 저장하게 된다.
- 스택영역은 각각의 스레드가 수행되면서 실행하고 있는 메소드의 호출 상태를 저장하며, 여러개의 스레드가 수행되는 경우 다수개의 스택 프레임으로 구성될 수 있다.
- 메소드 영역
- 자바 프로그램을 구성하고 있는 메소드와 클래스 변수(static으로 선언된 변수)를 저장하기 위한 공간이다.
- JVM은 복수개의 스레드가 메소드를 정상적으로 사용하기 위한 동기화 기법을 제공한다
- 힙 영역
- 프로그램 상에서 데이터를 저장하기 위해 동적으로(실행시간에) 할당하여 쓸 수 있는 메모리 영역
- new 연산자를 통하여 객체를 동적으로 생성시
- 메소드 영역과 같이 모든 프로그램에 의해 공유되는 공간 ->동기화 기법 이용
- 스택 영역(Stack area)
- LIFO(Last-In-First-Out)
- 메소드가 호출되어 실행될 때 메소드의 매개변수, 메소드 내에 선언된 메소드 지역변수, 반호나 값, 임시 변수 등을 저장하기 위한 공간
- 메소드 호출시 필요로 되는 변수들을 스택에 저장하고, 메소드 실행이 끝나면 스택을 반환하게 된다.
-
PC 레지스터
- JVM이 현재 수행할 명령어의 주소를 저장하는 레지스터
Native 메소드 스택
- 프로그램이 native 메소드를 호출시 native 메소드의 매개변수, 지역변수 등을 저장하기 위해 사용하는 공간 native 메소드는 자바 언어가 아닌 기존의 다른 언어에서 제공되는 메소드를 의미
---------------------------------------------------------------------------------------------------
※ PC 레지스터부분은 제외 함!그림을 보면 JVM의 메모리 모델이 크게1. Method Area, 2. Heap, 3. Stack, 4.Native Metod Stack으로 이뤄진 것을 알 수 있다.모든 부분에 간략히 설명을 하겠지만, 자바를 쓸 때 주로 다루는 두 가지 영역에 대해 알아보자!!객체를 생성할 때 실제로 어떠한 일이 일어나는지 이해하려면 일단 자바에서 모든 것이 어디에서 사는지, 그리고 얼마나 오랫동안 사는지를 알아야 한다.즉, 스택과 힙을 더 배워야 한다.일단 스택은 메소드 호출과 지역변수가 사는 곳으로,힙은 모든 객체가 사는 곳으로 알아두자!메소드를 호출하면 그 메소드는 stack의 맨 위에 올라간다. 실제로 스택에 들어가는 것은 스택 프레임인데, 여기에는 실행하는 코드와 모든 지역변수의 값을 포함한 메소드의 상태가 들어간다.헌데, 지역변수로 들어있는 객체는 어떻게 되나?즉, 아래에서 지역 변수 h 는 어떻게 되나?public void Write() {Human h = new Human();}원시 변수가 아닌 변수에는 객체 자체가 아닌 객체에 대한 레퍼런스가 들어가있게 된다.역시 이미 말한데로 객체는 실제로 힙안에 있게 되고 지역변수 h만 스택에 들어간다.지역변수가 스택에서 산다면 인스턴스 변수는 어디에서 사나?참고) 인스턴스 변수란? 클래스의 안, 메소드 밖에서 선언 된 변수new Human() 같은 명령을 내리면 JVM은 힙에 Human()을 위한 공간을 만들어야 한다.헌데, 얼마만큼의 공간을 만들어야하나? 그 객체를 저장하기에 충분한 공간을 만들어야 할텐데!그렇기때문에 그 객체의 모든 인스턴스 변수를 저장하는데 충분한 공간을 확보하게 된다!따라서 인스턴스 변수는 힙에, 그 변수가 속하는 객체안에서 살게 된다!하지만, 인스턴스변수가 객체라면?즉 Human 객체에 Body 객체가 들어가 있다면?(= Human에 Body 유형의 레퍼런스 변수가 있다면?)새로운 객체에 원시 변수가 아닌 객체 레퍼런스인 인스턴스 변수가 들어있다면레퍼런스가 참조하는 객체를 저장할 공간도 마련해줘야 할까?정답은 "그렇지 않다"이다. Body 레퍼런스 변수가 들어갈 공간만 확보하면 된다.private Body body;레퍼런스 변수에 새로운 Body 객체를 대입하기 전까지는 힙에 실제 Body 객체가 만들어지지 않는다.private Body body = new Body();참고) 레퍼런스 변수의 크기는 얼마일까?
레퍼런스 변수의 크기는 알수없다. 또한 메모리 관련 문제에서 중요한 것은 레퍼런스 변수의 크기와 개수가 아닌 객체의 개수, 그리고 그 객체의 실제 크기이다.
또한, 모든 객체 레퍼런스의 크기는 똑같다!!(JVM 종류별로 다를수는 있다.)한 눈에 보는 메모리 구조1. Method Area
- JVM의모든 Thread들이공유하는 데이터 영역
- Class정보
- Method정보(Method의바이트코드)
- 멤버변수 정보,
- static변수(Class 변수)
2. Heap
- 프로그램 상에서 데이터를저장하기 위해 동적(실행시간)으로할당하여 사용하는 영역
- “new”연산자로생성된 객체와 배열을저장
- 주로 실행시간에 생성되는객체를 저장
- GC(GarbageCollection)으로 관리 되는영역
n Permanent Space: Class에 대한Meta 정보를저장하는 공간 => 정보는 컴파일러에 의해 최적화에 사용된다.(JITs)
u Method of a class(including the bytecodes)
u Names of the classes
u Constant pool information
u JVM으로부터 만들어진 내부 객체 ex: java/lang/Object
n New Generation
u Eden: 새로(new) 생긴 모든객체
u Survivor1(From)
l Minor GC에의해서 Eden, Survivor 2영역의객체 중 활성화된객체만 이동하여 위치
l Old Space로이동되기 전의 객체만위치
u Survivor 2(To)
l Minor GC에의해서 Eden, Survivor 1영역의객체 중 활성화된객체만 이동하여 위치
l Old Space로이동되기 전의 객체만위치
n Old Generation
u Survivor 1, Survivor 2 영역에서이동해온 객체만 위치
u Full GC의대상이 되는 객체가위치
참고) Class는 Permanent Space에, 객체는 Heap으로 왜 따로 저장되는 것일까?
객체(인스턴스)는 클래스를 인스턴스화 한것이다.
따라서 JVM 내부적으로도 이 둘의 구현방식(객체를 힙에다가, 클래스를 Permanet 에다가)은 매우 비슷하다.
근데 왜 Permanent와 Heap으로 각각 따로 저장하는 걸까?
여기에는 2가지 이유가 있다고 한다.
첫 번째는 철학적(philosophical)인 이유이다.
class는 Java 구현의 일부이다. 따라서, 힙에 Java 자체의 데이터 구조를 채울수는 없다.
→ 아마도 JVM 역시 수많은 .class 파일로 구현되기 때문인듯하다.
두번째는 기술적인 이유이다.
원래 Permanent Space는 없었고, 객체와 클래스는 함께 저장되었다. 예전의 클래스들은 대부분 정적(Static)이었다.
Custom Class Loader는 거의 사용되지 않았고, Unloading 되는 클래스도 적었다.
(허나, 지금은 아니기에) 성능 최적화를 위해 Permanent Space가 생기게 되었고 클래스를 여기에 넣게 되었다.
원본글: http://blogs.sun.com/jonthecollector/entry/presenting_the_permanent_generation3. Java Stack
- Method가 호출될 때마다 스택 프레임이 생성. 이것이 쌓여 스택을 구성.
- 수행되는 Method 정보, 지역변수, 매개변수, 연산 중 발생하는 임시데이터 저장.
- JVM은 스택 영역을 실행중인 Thread에 따라 각각 구성
4. Native Method Stacks
- Native Method 호출 시 native Method의 매개변수, 지역변수 등 을 바이트코드로 저장
'LANGUAGE > JAVA' 카테고리의 다른 글
java primitive data type + 연산자 (0) 2014.06.19 session 삭제 시점시 처리. (0) 2014.05.27 [JAVA] 오버로딩, 오버라이딩 (0) 2014.04.14 [JAVA] 상속 (0) 2014.04.14 [JAVA] 객체, 클래스, 인스턴스(작성중) (0) 2014.04.10