최근 안드로이드 개발을 담당하면서, 스프링에 의존하여 웹개발을 하던 시기보다, JAVA의 근본적인 원리에 대해 더 깊은 이해가 필요하게 되었다. 새삼 스프링 프레임워크의 강력함에 대해 느끼게 됨과 동시에.. 기초가 많이 부족하다는 것 또한 깨닫게 되었다.
이전에 간략하게 메모리 영역에 대해 포스팅 하였으나, 이 기회에 조금 더 상세하게 이해하고 작성해보고자 한다.
1. 메모리
- 프로그램을 실행하기 위한 데이터 및 명령어를 저장하는 공간
- 메모리 구조에 대해 공부해야 하는 이유
- 같은 기능의 프로그램이더라도 메모리 관리에 따라 성능이 좌우된다.
- 메모리 관리가 되지 않는 경우 속도저하나 튕김이 발생할 수 있다.
- 한정된 메모리를 효율적으로 사용함으로서 높은 성능을 내고자 함.
2. JVM
- JVM은 Java Virtual Machine의 약자로, 자바 가상 머신이라고 한다. 주요한 기능으로는..
- 자바 코드를 컴파일해서 얻은 바이트 코드를 해당 운영체제가 이해할 수 있는 기계어로 바꾸어 실행해주는 역할
- 메모리 관리 기능(Garbage Collection)
- JVM은 크게 4가지 영역으로 나뉜다.
- Class Loader
- 개발자가 소스코드를 작성하는 파일은 .java 이다.
- .java를 자바 컴파일러가 컴파일 하면 .class(바이트코드) 파일이 생성된다.
- 이렇게 생성된 클래스 파일들을 JVM이 운영체제로부터 할당받은 메모리 영역인 Runtime Data Area로 적재하는 역할을 한다.
- Execution Engine
- Class Loader에 의해 메모리에 적재된 클래스(바이트 코드)들을 기계어로 변경해 명령어 단위로 실행하는 역할을 한다.
- 명령어를 순차적으로 읽어 실행하는 Interpreter방식과 JIT(Just-In-Time)방식이 있다.
- JIT 는 적절한 시간에 전체 바이트 코드를 네이티브 코드로 변경해서 Engine이 실행하는 것으로 성능을 높이는 방식이다.
- Garbage Collector(GC)
- GC는 Heap 메모리 영역에 적재된 객체들 중에 참조되지 않는 객체들을 탐색하여 제거한다.
- GC가 수행되는 시간은 정확히 알 수 없다.(참조가 없어지자마자 해제됨을 보장하지 않는다.)
- GC가 실행되는 동안 다른 쓰레드가 일시정지 되기 때문에, Full GC가 일어나 수 초 동안 모든 쓰레드가 정지한다면 장애가 발생할 수 있다.
- Runtime Data Area
- JVM의 메모리 영역으로 애플리케이션 실행에 사용되는 데이터들을 적재하는 영역
- 크게 Method Area, Heap Area, Stack Area, PC Register, Native Method Stack 으로 나눌 수 있다.
- Method 영역 : 클래스 맴버 변수의 이름, 데이터 타입, 접근 제어가 정보같은 필드 정보와 메소드의 이름, 리턴 타입, 파라미터, 접근 제어자 정보같은 메소드 정보, Type정보, Constant Pool, static변수, final class 변수 등이 생성되는 영역
- Heap 영역 : new 키워드로 생성된 객체와 배열이 생성되는 영역이다. 메소드 영역에 로드된 클래스만 생성이 가능하고 GC가 참조되지 않는 메모리를 확인하고 제거하는 영역이다.
- Stack 영역(LIFO) : 지역변수, 파라미터, 리턴 값, 연산에 사용되는 임시 값등이 생성되는 영역이다. 메소드를 호출할 때마다 개별적으로 스택이 생성된다. 메소드 수행이 끝나면 삭제
- PC Register : 쓰레드가 생성될 때마다 생성되는 영역으로, 현재 쓰레드가 실행되는 부분의 주소와 명령을 저장하고 있는 영역이다. 이것을 이용하여 쓰레드를 돌아가면서 수행할 수 있게 한다.
- Native method stack : 자바 외의 언어로 작성된 네이티브 코드를 위한 메모리 영역이다. 주로 c/c++등의 코드를 수행한다.
- Class Loader
이 중 Heap 영역에 대해서 조금 더 알아보자면..(Heap 영역은 자바의 버전에 따라 그 동작방식이 다르다..)
- Permanent Generation : 생성된 객체들의 정보의 주소값이 저장된 공간이다. Class, Method 등에 대한 Meta 정보가 저장되는 영역이고, JVM에 의해 사용된다. Reflection을 사용하여 동적으로 클래스가 로딩되는 경우에도 사용된다.
- New / Young 영역
- Eden : 객체들이 최초로 생성되는 공간
- Survivor 0/1 : Eden에서 참조되는 객체들이 저장되는 공간
- Old 영역 : Old 영역에 대해서는 GC에 대한 이해가 함께 필요할 것 같다..
- Minor GC
- Eden 영역에 객체가 가득차게 되면 첫번째 GC가 일어난다.
- survivor1 영역에 Eden영역의 메모리가 그대로 복사된다. 그리고 survivor1 영역을 제외한 다른 영역의 객체를 제거한다.
- Eden과 survivor1 영역이 가득차게 되면, 두 영역에서 참조되고 있는 객체가 있는지 검사한다.
- 이 중 참고죄고 있는 객체만 survivor2 영역에 복사한다.
- survivor2 영역을 제외한 다른 영역의 객체들을 제거한다.
- 위 과정 중 일정 횟수 이상 참고죄고 있는 객체들을 survivor2에서 Old 영역으로 이동시킨다.
- Magor GC
- Old 영역에 있는 모든 객체들을 검사하며 참조되고 있는지 확인
- 참조되지 않는 객체들을 모아 한번에 제거한다.
- 이 과정은 Minor GC보다 시간이 훨씬 많이 걸리고, 실행중에는 GC를 제외한 모든 쓰레드가 중지한다.
- 이 과정에서 Heap 메모리 영역에 빈 공간이 생기게되고, 메모리 재구성을 하게 되는데, 이 때 다른 쓰레드가 메모리를 사용하면 안되기 때문에 모든 쓰레드가 정지하게 된다.
- Minor GC
참고
https://steady-coding.tistory.com/305
https://asfirstalways.tistory.com/158
https://limkydev.tistory.com/51
https://jeong-pro.tistory.com/148
https://cafe.naver.com/jjdev/227
'개발 > Java' 카테고리의 다른 글
[Java] JVM - ClassLoader(아주 얕은 수준) (0) | 2022.09.03 |
---|---|
[Java]Try-with-resource (0) | 2022.08.16 |
[Java]Serialization(직렬화) (0) | 2022.05.25 |
[Java] 자바의 메모리 영역(1) (0) | 2022.04.26 |
[Algorithm]구간합 구하기 (0) | 2022.04.24 |