JVM 메모리 구조
Java 응용프로그램이 실행되면, JVM은 시스템으로부터 프로그램을 수행하는데 필요한 메모리를 할당받고, 이 메모리를 용도에 따라 여러 영역으로 나누어 관리한다.
Method 영역
: Runtime 중 특정 Class가 사용되면, JVM은 해당 Class의 .class파일을 읽고 분석한 결과(클래스에 대한 정보)를 이 곳에 저장한다.
참고) Class variable도 같이 저장된다.
Heap 영역
: instance가 생성되는 공간이다. Runtime 중 instance는 모두 이곳에 생성된다.
참고) 즉, instance variable이 생성되는 공간이다.
콜 스택(Call Stack)
: 메서드 작업에 필요한 메모리 공간을 제공한다.
- 메서드 호출 → 콜 스택(stack)에 메서드를 위한 메모리가 할당된다.
- 메서드가 작업을 마치면 할당되었던 메모리 공간은 반환되어 비워진다.
- 참고) 콜 스택의 최상단 메서드가 현재 실행 중인 메서드다. 나머지는 대기상태에 있게 된다.
콜 스택에서 발생하는 에러
JVM 내 콜 스택이 계속 쌓임으로써 특정 구간의 메모리 한계를 넘게 된다면 StackOverflowError가 발생한다.
이를 통해, StackOverflowError가 발생한다면 이제 나는 내 로직에서 메서드를 끝없이 호출하는(ex) 반복문 or 재귀)있는 부분이 있을 수 있겠다고 판단할 수 있다!
primitive type과 reference type
콜 스택에 메서드 실행에 필요한 메모리가 할당된다고 위에서 소개했다. 그럼 메서드의 실행에 있어서 매개변수를 받게되는 경우가 있는데, 이 때 그 type에 따라 해당 매개변수의 값을 변경유무를 나눌 수 있다.
Java의 메서드 매개변수
Java에서는 메서드를 호출할 때 매개변수를 넘기는 경우가 있다.
이 때 매개변수로 지정한 값은 해당 메서드의 매개변수에 복사해서 넘겨주게 된다.
이 방식에서 차이점을 보이게 되는데 아래와 같다.
- primitive type은 값이 매개변수로 복사가 된다. - read
- reference type은 instance의 주소가 매개변수로 복사가 된다. - read & write
instance의 주소가 복사된다는 의미
: 해당 메서드 내에서도 같은 주소값(참조변수의 주소)을 가지는 참조변수의 메모리 할당이 콜 스택에 이루어진다. 메서드 내 새로운 참조변수를 통해서 instace에 접근을 함으로써 instace 내의 instance variable에 접근이 가능하기 때문에 해당 매개변수의 값을 변경 가능하다는 의미다.
instance method와 class method
그럼 이렇게 메서드의 작업을 수행할 때, instance variable을 사용하는 메서드가 있다.
그럼 이에 이름을 붙여하는데 이를 선구 개발자들이 ‘instance method’라고 부른 것 뿐이다.
반면에, instance와 관계가 전혀 없는(instance variable이나 instance method도 사용안하는) 메서드는 ‘class method’라고 이름을 붙였다.
정리
JVM
: 응용프로그램 실행 시, 시스템으로부터 프로그램을 수행하는 데 필요한 메모리를 할당받는다.
: 할당받은 메모리를 용도에 따라 Method Area, Call Stack, Heap 영역으로 나눈다. - 주요 영역
- Method Area: Class data 저장
- Call Stack: 메서드 실행을 위한 메모리 제공
- Heap: instance가 생성되는 공간
primitive type과 reference type
메서드를 호출함으로써 콜 스택에 해당 메서드에 필요한 메모리가 저장이 된다.
메서드의 매개변수의 type에 따라 해당 매개변수의 값이 넘어오느냐 instance주소가 넘어오느냐가 나눠진다.
그로 인해 매개변수의 원본을 변경할 수 있느냐 없느냐를 구분할 수 있는 것이다.
왜냐하면, 참조변수의 주소를 통해 instance에 접근하여 내부 instace 변수에 접근할 수 있기 때문에
static variable
: 모든 (클래스의) 인스턴스에서 사용가능한
: 프로그램이 시작됨으로써 JVM이 Class를 로드할 때, Method Area에 Class 저장공간이 할당이 되는데, 이 때 static 변수(class 변수)도 동시에 저장이 된다.
=> 프로그램이 실행되는 동안 static 변수의 참조되는 위치가 변경되지 않으므로, CPU가 한 번 Class의 위치 내 static variable의 위치를 찾으면 이를 빠르게 액세스 가능 (by cache)
instance vairable
: Class의 instance 내 변수 -> 인스턴스가 생성이 되어야 instance variable이 생성이 된다.
특정 인스턴스(=객체)를 생성할 때마다, 힙(메모리 내 가변적인 부분)에 새로운 주소의 공간에 저장이 된다.
즉, CPU는 객체마다 서로 다른 위치에 액세스 해야 한다. => static variable에 비해 액세스 하는데에 더 많은 시간이 소요된다.
instance 메서드 / static 메서드
: 메서드의 실행에 있어서 instance variable을 사용하는 메서드 / 메서드의 실행에 있어서 instance variable을 사용하지 않는 메서드
Static 메서드(=Class 메서드)는 instance variable을 사용하지 말자.
: Static 메서드는 static variable이 이미 메모리에 올라갈 때 자동적으로 생성되어 있기 때문에 instance 생성 없이 호출할 수 있다. 따라서, Static 메서드 instance 접근 시 instance가 있다고 반드시 보장할 수는 없다.
하지만, instance variable이 존재한다고 하면, 이미 static 변수는 메모리에 존재하는 것을 의미하기 때문에 instance 메서드에서 static variable에는 언제든 접근 가능하다.
메서드 내 instance variable를 사용하지 않는다면, 차라리 static을 붙이는 걸 고려하자.
: 메서드 내에서 instance variable을 필요하지 않는다면, static을 붙임으로써 메서드 호출시간이 짧아지므로 성능을 향상시킬 수 있다.
반면, instance 메서드는 실행 시 호출되어야할 메서드를 찾는 과정이 추가적으로 필요하기 때문에 시간이 더 걸린다.
: 또한, static을 붙임으로써 다수의 heap 메모리에 해당 값이 저장되는 것이 아닌, Method Area 내 클래스 데이터에 해당 값을 저장함으로써 단 하나의 저장 공간만을 갖도록 한다.
설계
- Class의 멤버변수 중 모든 instsance에 공통된 값을 유지해야 한다면 static으로 지정한다.
- 작성한 메서드들 중 instance variable이나 instance 메서드를 사용하지 않는 메서드를 static으로 지정한다.
참고
'Java' 카테고리의 다른 글
System.out.println을 쓰면 안되는 이유 (0) | 2023.07.06 |
---|---|
Java Exception ( feat. Checked, UnChecked ) (0) | 2023.06.26 |
Java (0) | 2023.06.23 |
Java - equals, hashCode() (0) | 2023.06.20 |