0.들어가기 전
쓰레드 세이프란?
멀티 쓰레드에 의한 동시 호출에서 안정성이 보장되는 코드를 말한다. 즉, 멀티 쓰레드 환경에서 코드가 개발자가 의도한대로 동작하는 것을 말한다. 이 쓰레드 세이프에 대해 공부하다가 JVM의 메모리 구조를 공부하게 되었다.
메모리란?
- 프로그램을 구동하기 위해서 운영체제(OS)가 데이터를 저장할 공간을 할당함.
- 메모리 공간은 크게 Static, Stack, Heap 영역으로 구분 됨.
1.JVM과 메모리 할당
출처) https://velog.io/@agugu95/자바와-JVM-그리고-메모리-구조
1-1. JVM 메모리 공간
- Runtime Data Areas라고도 불린다.
- 위 그림과 같이 JVM의 메모리 공간은 Method Area, Heap, Stack, PC Registers, Native Method Area로 나뉜다. Heap영역은 더 세부적으로 나뉘는데 이 부분에 대한 설명은 여기서는 생략한다.
- JVM의 메모리 공간은 클래스 로더에 의해 데이터가 적재되는 공간이다. (클래스 로더에 대한 설명은 아래에서)
1-2.Runtime data area의 세 영역
- Runtime Data Areas은 정확히는 5가지 영역인데 크게는 세가지 영역으로 구분 된다. Class area, Stack area, Heap area인데 각 영역마다 저장 되는 데이터가 다르다.
Class area =(Method Area = Static area)- 전역변수와 정적 멤버변수(static이 붙은 자료형)는 static 영역에 데이터를 저장한다.
- 프로그램의 시작부터 종료가 될 때까지 메모리에 남아 있게 된다.⇒ 그렇기에 전역 변수는 프로그램이 종료 될 때 까지 어디서든 사용 가능하다.
- 클래스 파일의 바이트 코드가 로드 되는 곳.
- 클래스 정보가 차지하는 영역.
- 메소드 내에서 정의하는 기본 자료형(int, double, byte 등) 에 해당되는 지역변수의 데이터 값이 저장 되는 공간.
- 스택 영역에는 지역변수와 매개변수가 저장 된다.
- 지역 변수 = 로컬변수 (local variable) , 매개변수 = 파라미터 (parameter)
- 해당 메소드가 호출 될 때 메모리에 할당 되고 종료되면 메모리가 해제 된다.
- 참조형(Reference Type)의 데이터 타입을 갖는 객체(인스턴스), 배열 등은 Heap 영역에 데이터가 저장된다.
- 코드에서 'new' 명령을 통해 생성된 인스턴스 변수가 놓인다. - 그냥 new 명령으로 만드는 메모리는 모조리 힙 영역에 보관된다고 보면 된다.
- 실제 데이터를 갖고 있는 Heap 영역의 참조 값을 Stack 영역의 객체가 갖고 있다. 이렇게 리턴 받은 참조 값을 갖고 있는 객체를 통해서만 해당 인스턴스를 핸들 할 수 있다.
- 힙 영역에 보관되는 메모리는 메소드 호출이 끝나도 사라지지 않고 유지 된다. → 주소를 잃어버려 가비지 컬렉터에 의해 지워질 때 까지 or JVM 종료 될 때 까지
2.그림으로 보는 메모리 공간에서 쓰레드
출처 ) https://wayhome25.github.io/cs/2017/04/14/cs-15-2/
그림과 같이 하나의 힙 영역을 모든 스레드가 공유. 하지만 각 스레드는 자신들만의 고유 Stack 영역을 가지고 있음.
3.객체의 참조
- 힙에 있는 객체들에 대한 참조는 다음 4가지 종류 중 하나이다.
- 힙 내의 다른 객체에 의한 참조
- Java 스택, 즉 메서드 실행시에 사용하는 local variable(지역변수)와 parameter(매개변수)들에 의한 참조
- JNI(Java Native Interface)에 의해 생성된 객체에 대한 참조
- 메서드 영역의 static 변수에 의한 참조
4.클래스 로딩
클래스 로딩이란?
- Method area에 바이트 코드가 올라가는 것을 클래스 로딩이라고 한다.⇒ 어떤 메소드가 호출 되려면, 먼저 그 메소드를 갖고 있는 클래스 파일이 메모리에 로딩되어 있어야 한다. 그래서 클래스를 실행할 때 *.class 파일을 찾아서 메모리에 로딩하는 것이다.
Runtime에서의 JVM
출처) https://velog.io/@agugu95/자바와-JVM-그리고-메모리-구조
- 프로그램 실행 시 JVM은 OS로부터 메모리를 할당
- 자바 컴파일러(javac)가 자바 소스코드(.java)를 자바 바이트코드(.class)로 컴파일
- Class Loader를 통해 JVM Runtime Data Area로 로딩
- 로더에 의하여 로딩 된 .class들은 Execution Engine을 통해 Interpret(해석)
- 해석된 바이트 코드는 Runtime Data Area의 각 영역에 배치되어 수행. 이 과정에서 Execution Engine에 의해 GC의 작동과 쓰레드 동기화가 이루어짐
클래스 로딩을 위한 JVM의 로딩 절차
- 어떤 메소드를 호출하는 문장을 만났는데, 그 메소드를 가진 클래스 바이트 코드가 아직 로딩 된적 없다면, 곧바로 JVM은 JRE 라이브러리 폴더에서 클래스를 찾음.
- 없으면, CLASSPATH 환경변수에 지정된 폴더에서 클래스를 찾음.
- 찾았으면 그 클래스 파일이 올바른지 바이트 코드 검증.
- 올바른 바이트 코드라면 Method area에 파일을 로딩
- 클래스 변수를 만들라는 명령어가 있으면 Method area에 그 변수를 준비한다.
- 클래스 블록이 있으면 순서대로 그 블록을 실행한다.
- 이렇게 한 번 클래스의 바이트 코드가 로딩 되면 JVM이 종료 될 때 까지 유지
Uploaded by Notion2Tistory v1.1.0