Java는 개발자가 직접 메모리를 관리하지 않고, JVM(Java Virtual Machine)이 메모리를 자동으로 관리합니다. 이를 통해 메모리 누수(Memory Leak)와 같은 문제를 줄이고 안정적인 프로그램을 개발할 수 있습니다. Java의 메모리 관리와 가비지 컬렉션에 대한 구체적인 개념과 동작 원리를 이해하면, 효율적인 코드 작성과 최적화를 도울 수 있습니다.
Java 메모리 구조
Java의 메모리는 크게 다음과 같은 영역으로 나뉩니다:
- Heap
- 객체와 인스턴스 변수들이 저장됩니다.
- GC(Garbage Collector)에 의해 관리됩니다.
- Young Generation, Old Generation, 그리고 Permanent Generation/Metaspace로 나뉩니다.
- Stack
- 각 스레드에서 실행 중인 메서드 호출과 관련된 로컬 변수와 메서드 호출 스택이 저장됩니다.
- 메모리가 메서드 호출이 끝나면 자동으로 해제됩니다.
- Method Area
- 클래스 메타데이터, 정적 변수, 그리고 메서드 정보가 저장됩니다.
- Java 8 이후에는 Metaspace라는 이름으로 Heap 바깥에 위치합니다.
- PC Register 및 Native Method Stack
- 각각 스레드의 현재 실행 중인 명령과 네이티브 메서드 호출 정보를 저장합니다.
가비지 컬렉션(Garbage Collection)이란?
Java의 **가비지 컬렉션(GC)**은 더 이상 참조되지 않는 객체를 찾아 Heap 메모리에서 제거하는 프로세스입니다. 개발자가 직접 메모리를 해제하지 않아도, GC가 자동으로 이를 처리하여 메모리 누수를 방지합니다.
가비지 컬렉션의 동작 원리
- Mark-and-Sweep 알고리즘
GC는 "더 이상 참조되지 않는 객체"를 탐색하는 Mark 단계와, 탐색된 객체를 제거하는 Sweep 단계로 나뉩니다. - Generational Garbage Collection
- Young Generation: 새롭게 생성된 객체가 저장되는 영역.
- Eden과 Survivor 영역으로 나뉩니다.
- Old Generation: 오래 살아남은 객체가 저장됩니다.
- Permanent Generation/Metaspace: 클래스 정보와 상수 풀(Constant Pool)이 저장됩니다.
- Young Generation: 새롭게 생성된 객체가 저장되는 영역.
- Stop-the-World 이벤트
GC가 실행되면 모든 애플리케이션 스레드가 잠시 멈추는 이벤트가 발생합니다. 이는 성능 문제를 야기할 수 있으므로 GC 튜닝이 중요합니다.
예제: 가비지 컬렉션 시뮬레이션
다음은 Java에서 가비지 컬렉션이 작동하는 방식을 시뮬레이션한 간단한 예제입니다.
public class GarbageCollectionExample {
static class MyObject {
private String name;
public MyObject(String name) {
this.name = name;
}
@Override
protected void finalize() throws Throwable {
System.out.println("Garbage collected for object: " + name);
}
}
public static void main(String[] args) {
// 객체 생성
MyObject obj1 = new MyObject("Object 1");
MyObject obj2 = new MyObject("Object 2");
// obj1을 null로 만들어 참조 제거
obj1 = null;
// obj2를 다른 객체로 덮어씌우기
obj2 = new MyObject("Object 3");
// 명시적으로 GC 호출
System.gc();
// 일부 대기
try {
Thread.sleep(1000); // GC가 실행될 시간을 확보
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("End of program");
}
}
실행 결과 (예시):
Garbage collected for object: Object 1
Garbage collected for object: Object 2
End of program
설명:
- obj1 = null;로 참조를 제거하면 Object 1은 GC 대상이 됩니다.
- obj2는 Object 3으로 대체되어 기존의 Object 2도 GC 대상이 됩니다.
- System.gc()를 호출하여 GC를 명시적으로 요청합니다. (반드시 실행된다는 보장은 없지만, 요청됩니다.)
- finalize() 메서드는 객체가 가비지 컬렉션되기 전에 호출되며, 이를 통해 GC가 작동했음을 확인할 수 있습니다.
가비지 컬렉션 최적화를 위한 팁
1. 참조 제거
불필요한 객체에 대한 참조를 명시적으로 제거하여 GC 대상이 될 수 있도록 합니다.
list = null;
2. WeakReference 사용
GC 대상이 되어야 할 객체에 약한 참조를 사용하는 것이 유용할 수 있습니다.
WeakReference<MyObject> weakRef = new WeakReference<>(new MyObject("Weak Object"));
3. GC 로깅 활성화
GC 동작을 로깅하여 성능 문제를 파악할 수 있습니다.
-XX:+PrintGCDetails -XX:+PrintGCDateStamps
4. 적절한 JVM 옵션 사용
메모리 할당과 GC 설정을 조정하여 애플리케이션 성능을 최적화합니다.
-Xms512m -Xmx1024m -XX:NewRatio=2
결론
Java의 메모리 관리와 가비지 컬렉션은 메모리 누수와 같은 문제를 줄이고 안정성을 높이는 중요한 역할을 합니다. 그러나 GC는 성능에 영향을 미칠 수 있으므로, 메모리 관리 최적화와 GC 튜닝을 통해 애플리케이션의 성능을 극대화할 수 있습니다.
가비지 컬렉션을 이해하고 적절히 활용하면 Java 애플리케이션 개발에서 한층 더 높은 수준의 안정성과 효율성을 달성할 수 있습니다.
'Develop > JAVA' 카테고리의 다른 글
[Java] 오늘날짜 구하기 날짜 더하기 빼기 (3) | 2024.11.14 |
---|---|
[Java] 크로스 사이트 스크립트 (XSS) 취약점 조치방법 (7) | 2024.10.30 |
[Spring Framework] application.yml 파일에서 값 암호화 (7) | 2024.10.28 |
[Java] Spring Security 에서 SameSite 설정방법 (PG사 결제 시 리턴 후 세션 끊김현상 해결) (6) | 2024.10.24 |
[Java] BigDecimal 나누기 소수점 올림, 버림, 반올림 사용방법 (5) | 2024.10.21 |