보리차
chapter 19 자바의 메모리 모델과 Object 클래스 본문
자바 가상머신의 메모리 관리 방식을 가리켜 '자바 메모리 모델'이라 하는데, 이는 자바의 이해에 있어서 매우 중요한 내용이다.
자바 가상머신의 메모리 모델
자바 가상머신은 운영체제가 할당해 주는 메모리 공간을 기반으로 스스로를 실행하면서 더불어 자바 응용 프로그램의 실행도 돕는다.
자바 가상머신의 메모리 관리
가상머신은 메모리 공간을 크게 세 개의 영역으로 나눈다.
- 메소드 영역 (Method Area) 메소드의 바이트코드, static 변수
- 스택 영역 (Stack Area) 지역변수, 매개변수
- 힙 영역 (Heap Area) 인스턴스
메소드 영역 (Method Area)
바이트코드(Bytecode): 소스파일을 컴파일할 때 생성되는, 자바 가상머신에 의해 실행이 가능한 코드.
인스턴스의 생성 및 클래스 변수의 접근을 위해서는 먼저 해당 클래스의 바이트코드가 메모리 공간에 로딩되어야 하는데(메모리 공간에 올려져야 하는데), 이 때 로딩되는 메모리 공간이 '메소드 영역'이다. 즉, 메소드 영역은 특정 클래스의 정보가 메모리 공간에 올려질 때 채워지는 영역이다.
스택 영역 (Stack Area)
스택은 지역변수와 매개변수가 저장되는 공간이다. 지역변수와 매개변수는 선언되는 순간에 스택에 할당되었다가 자신이 할당된 영역을 벗어나면 소멸이 된다.
힙 영역 (Heap Area)
인스턴스는 힙 영역에 할당된다. 인스턴스를 스택이 아닌 힙이라는 별도의 영역에 할당하는 이유는 인스턴스의 소멸 시점과 소멸 방법이 지역변수와 다르기 때문이다. 인스턴스의 소멸 시기는 가상머신이 결정한다.
가비지 컬렉션(Garbage Collection): 자바의 인스턴스 소멸 방식. 어떤 참조변수도 참조하지 않는 인스턴스는 '소멸의 대상'이 되어 가상머신에 의해 소멸이 이뤄진다.
Object 클래스
finalize 메소드
아무도 참조하지 않는 인스턴스가 가비지 컬렉션에 의해 소멸되기 전에 자동으로 호출되는 메소드
protected void finalize() throws Throwable
따라서 인스턴스 소멸 시 반드시 실행해야 할 코드가 있다면 이 메소드의 오버라이딩을 고려할 수 있다.
equals 메소드
두 인스턴스의 내용 비교를 원한다면 Object 클래스의 equals 메소드를 오버라이딩 해야한다. (단순히 참조변수의 참조 값을 비교할 때는 == 연산자를 쓴다.)
// equals 메소드 예시
@Override
public boolean equals(Object obj) {
if(this.num == ((INum)obj).num) // 비교 결과의 조건은 직접 설정
return true;
else
return false;
}
clone 메소드
호출된 메소드가 속한 인스턴스의 복사본이 생성되고 이렇게 만들어진 복사본의 참조 값이 반환된다.
protected Object clone() throws CloneNotSupportedException
단, 다음 Cloneable 인터페이스를 구현한 클래스의 인스턴스만 clone 메소드를 호출할 수 있다. Cloneable 인터페이스는 '마커 인터페이스'로 clone 메소드 호출이 허용된다는 표식의 역할을 한다.
interface Cloneable
인스턴스의 복사는 클래스에 따라 허용해서는 안되는 작업이 될 수 있으므로 인스턴스 복사의 허용 여부는 클래스를 정의하는 과정에서 고민하고 결정해야 한다.
class Point implements Cloneable {
private int xPos;
private int yPos;
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
위 예제에서는 clone 메소드를 오버라이딩하면서 protected로 선언되어 있던 clone 메소드를 public으로 바꿔주었다. 이렇게 메소드 오버라이딩을 통해 접근 범위를 넓히는 것이 가능하다. (반대는 불가능)
또 clone의 호출로 인한 복사를 '얕은 복사'라고 한다. 복사 과정에서 참조변수가 지니는 참조 값이 그대로 새 인스턴스에 복사가 되는 것이다. 깊은 복사를 하려면 clone 메소드를 다음과 같이 오버라이딩 해야 한다.
@Override
public Object clone() throws CloneNotSupportedException {
//Object 클래스의 cone 메소드 호출을 통한 복사본 생성
Rectangle copy = (Rectangle)super.clone();
// 깊은 복사의 형태로 복사본을 완성
copy.upperLeft = (Point)upperLeft.clone();
copy.lowerLeft = (Point)lowerLeft.clone();
// 완성된 복사본의 참조 값 반환
return copy;
}
'Java' 카테고리의 다른 글
chapter 21 제네릭(Generics) 1 (0) | 2022.02.15 |
---|---|
chapter 20 자바의 기본 클래스 (0) | 2022.02.10 |
chapter 18 예외처리(Exception Handling) (0) | 2022.02.06 |
chapter 17 인터페이스와 추상 클래스 (0) | 2022.02.06 |
chapter 16 클래스의 상속 3: 상속의 목적 (0) | 2022.02.06 |