2022-04-18-TIL
Today I Learned
Memory Leak
Java는 GC(가비지 컬렉터)가 메모리를 회수하므로 C처럼 free를 잊어서 생기는 누수는 없다. 그런데도 메모리 누수는 생긴다. Oracle의 트러블슈팅 가이드는 애플리케이션이 의도치 않게 객체 참조를 계속 쥐고 있어서 GC가 그 객체를 회수하지 못하는 상황을 Java의 메모리 누수로 정의한다. GC는 참조가 남아 있는 객체를 “아직 쓰는 것”으로 보기 때문이다.
흔한 원인은 다음과 같다.
static컬렉션이나 직접 만든 캐시에 객체를 넣기만 하고 빼지 않는다.- 리스너, 콜백을 등록하고 해제하지 않는다.
ThreadLocal값을 스레드 풀 환경에서 지우지 않는다. 스레드가 재사용되므로 값도 계속 남는다.
가이드는 java.lang.OutOfMemoryError: Java heap space가 났다고 해서 반드시 누수는 아니라고도 말한다. 단순히 힙 크기가 애플리케이션에 비해 작을 수도 있다. 누수인지 보려면 full GC 직후의 사용량(live set)을 지켜봐야 한다. 안정된 부하에서 live set이 시간이 지날수록 계속 늘어난다면 누수를 강하게 의심할 수 있다. 원인을 찾는 데 가장 중요한 자료는 힙 덤프이고, jcmd, jmap, JConsole이나 -XX:+HeapDumpOnOutOfMemoryError 옵션으로 얻는다.
1
2
jcmd <pid> GC.heap_dump /tmp/heap.hprof
java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp -jar app.jar
- https://blog.wonizz.tk/2022/04/12/garbage-collector-2/
Architecture
GeekNews 주간 뉴스레터에서 InfoQ의 Software Architecture and Design Trends Report (2022년 4월)를 소개했다. InfoQ는 매년 아키텍처 관련 아이디어를 기술 수용 단계(Innovators, Early Adopters 등)별로 정리한다.
2022년 리포트에서 눈에 띈 것은 두 가지다. 하나는 아키텍처 결정 기록(ADR, Architecture Decision Records)이 Early Adopters 단계에 새로 들어간 것이다. 리포트는 원격, 하이브리드 근무로 비동기 소통이 늘어난 것이 ADR로 나타난다고 설명한다. ADR은 어떤 결정을 왜 내렸는지를 짧은 문서로 남기는 방식이라, 다이어그램만으로는 전달되지 않는 결정의 맥락을 남길 수 있다. 다른 하나는 데이터를 저장이나 전송 계층의 문제로만 보지 않고 시스템을 규정하는 요소로 보는 흐름(“Data + Architecture”)이다. 그 밖에 Dapr와 WebAssembly가 Innovators에서 Early Adopters로 이동했다.
- https://news.hada.io/weekly/202216?utm_source=slack&utm_medium=bot&utm_campaign=T74H5245A
Reflection API
리플렉션은 실행 중에 클래스의 구조(필드, 메서드, 생성자)를 들여다보고, 이름만으로 객체를 만들거나 메서드를 호출하는 기능이다. Java 튜토리얼은 JVM에서 실행 중인 애플리케이션의 동작을 검사하거나 수정해야 하는 프로그램에서 쓰인다고 설명한다. 확장 기능을 이름으로 불러오는 경우, 클래스 브라우저와 IDE, private 멤버를 들여다보는 디버거와 테스트 도구가 예다.
1
2
3
4
Class<?> clazz = Class.forName("com.example.Member");
Object member = clazz.getDeclaredConstructor().newInstance();
Method method = clazz.getMethod("getName");
Object name = method.invoke(member);
Spring의 의존성 주입, JPA의 엔티티 생성, Jackson의 JSON 변환처럼 애플리케이션 코드가 모르는 클래스를 다뤄야 하는 프레임워크가 리플렉션을 많이 쓴다.
같은 튜토리얼은 리플렉션을 무분별하게 쓰지 말라고 경고한다.
- 타입이 동적으로 결정되므로 일부 JVM 최적화가 적용되지 않아 느리다.
- 보안 관리자 아래에서는 런타임 권한이 필요할 수 있다.
- private 필드와 메서드에 접근하는 등 일반 코드에서 불가능한 일을 할 수 있어서 추상화를 깨고, 라이브러리가 업그레이드되면 동작이 바뀔 수 있다.
그래서 애플리케이션 코드에서는 리플렉션 없이 할 수 있는 일이면 리플렉션을 피하고, 프레임워크가 쓰는 원리를 이해하는 용도로 알아 두는 편이 맞다.
- https://tecoble.techcourse.co.kr/post/2020-07-16-reflection-api/
- https://highright96.tistory.com/81
댓글
아직 댓글이 없습니다