코드 레벨
- 불변 객체
참조 상태가 변경되지 않기 때문에, GC가 객체의 참조를 수시로 확인할 필요가 줄어듬 - 객체 재사용 고려
- StreamAPI 이용 (무조건 X, 성능의 이점을 가져올 수 있는 경우에 적용 가능해 보임)
Lazy Evaluation과 파이프라인 구조 덕분에 중간 연산들은 실제 데이터를 처리하지 않고, 최종 연산이 호출될 때에만 데이터를 처리 - I/O, 소켓, 쓰레드 등 사용 후 닫았는지 전반적인 확인 (GC가 회수 하지 못함)
예시) Contents 서버 > outputstream을 사용하고 닫지 않음
- static 변수 검토 (StackOverflow)
static 변수는 GC에 의해 회수 되지 않아 사이즈가 큰 객체를 참조가 진행되면서 메모리 누수 가능성 - 내부 클래스 검토
생명 주기를 가지거나 이벤트 리스너, 스레드와 같이 비동기적으로 동작하는 경우, 외부 클래스의 인스턴스가 더 이상 필요하지 않더라도 내부 클래스가 계속 존재
-> 외부 클래스의 인스턴스가 메모리에서 해제되지 않아서 메모리 누수 가능성 - 약한 참조
네이버
https://d2.naver.com/helloworld/329631
스터디
https://be-study-record.tistory.com/40
아이템 7 다 쓴 객체 참조를 해제하라
객체 참조 해제란 메서드 내에서 사용할 객체를 인스턴스화 하여 로컬 변수에 할당하여 참조하고 사용 후 더 이상 사용하지 않는다고 명시적 null처리로 참조 관계를 끊어주거나 해당 메서드가
be-study-record.tistory.com
https://be-study-record.tistory.com/52
Java의 참조 유형
Java의 참조 유형 Java에는 다양한 참조 유형이 있는데 참조 유형에 따라 가비지 컬렉터의 실행 대상 여부 및 시점이 달라진다. Strong Reference (강한 참조) 자바의 기본 참조 유형이다. Class class = new C
be-study-record.tistory.com
class Data {
private int[] array = new int[3000];
}
class ReferenceTest {
List<WeakReference<Data>> weakRefs = new LinkedList<>();
List<SoftReference<Data>> softRefs = new LinkedList<>();
List<Data> strongRefs = new LinkedList<>();
// out of memory 발생 X
void weakReferenceTest() {
try {
while (true) {
weakRefs.add(new WeakReference<>(new Data()));
}
} catch (OutOfMemoryError outOfMemoryError) {
System.out.println("out of memory!");
}
}
// out of memory 발생 X
void softReferenceTest() {
try {
while (true) {
softRefs.add(new SoftReference<>(new Data()));
}
} catch (OutOfMemoryError outOfMemoryError) {
System.out.println("out of memory!");
}
}
// Strong일 경우 out of memory 발생
void strongReferenceTest() {
try {
while (true) {
strongRefs.add(new Data());
}
} catch (OutOfMemoryError outOfMemoryError) {
System.out.println("out of memory!");
}
}
static void main(String[] args) {
System.out.println("실행");
ReferenceTest test = new ReferenceTest();
test.weakReferenceTest();
// test.softReferenceTest();
// test.strongReferenceTest();
System.out.println("종료");
}
}
- JVM
- MaxTenuringThreshold 수치 조절
minor gc가 일어날 때 age bit가 증가하고 설정 수치를 넘기 전까지 survivor영역에 남아 있는데, 수치가 높아 계속 남아 있게 되면 결국 가득 차 누수 발생
반대로 설정 수치가 낮으면 계속해서 tenured 영역으로 넘어가고 Major GC를 대기하는데 Major GC가 일어나기 전에 tenured영역이 가득 차 누수가 발생
major gc 도중에는 stw(stop the world) 발생 → 모든 애플리케이션 스레드 일시 정지 - ZGC (STW 개선… 좀 더 알아봐야겠다)
-XX:+UseZGC
ZGC의 목적 중 하나는 STW 상태를 10ms 아래로 가져가는 것이다.
https://d2.naver.com/helloworld/0128759 - 힙 메모리 사이즈 조절
최대 : 서버의 가용 메모리의 약 1/4로 설정됨
최소 : 서버의 가용 메모리의 약 1/64로 설정됨
예시) esocket 8GB
기준최대 메모리 사이즈 : 8GB / 4 ≒ 약 2GB
초기 메모리 사이즈 : 8GB / 64 ≒ 약 127MB
- Heap Dump 와 GC log 설정
- Heap Dump (IntelliJ에서도 가능하고 Eclipse MAT, VisualVM 등으로 분석)
> 어떤 객체가 메모리를 차지하고 있는지, 레퍼런스의 구조 등을 분석하는 데 사용
-XX:+HeapDumpOnOutOfMemoryError :힙 덤프 파일을 생성
-XX:HeapDumpPath : 힙 덤프가 생성되는 폴더 경로를 지정
-XX:OnOutOfMemoryError : OOM이 발생할 경우, 수행할 스크립트를 지정 - GC log
> GC 이력을 로그 파일
-Xlog:gc:file=gc-%t.log : 로깅 파일
-Xlog:gc=info : GC 상세 내역
-Xlog:gc*:time : GC 발생 시간
- Heap Dump (IntelliJ에서도 가능하고 Eclipse MAT, VisualVM 등으로 분석)
- MaxTenuringThreshold 수치 조절
'Knowledge' 카테고리의 다른 글
Trie 자료구조 - 14425 (1) | 2023.07.19 |
---|---|
LinkedList 직접 구현해 보기 (1) | 2023.07.11 |
SQL (1) | 2023.01.09 |
JDBC (1) | 2023.01.09 |
Servlet & JSP (0) | 2023.01.09 |
댓글