sun.reflect.GeneratedMethodAccessor 클래스에 대해서
톰캣 운영 중에 로딩된 클래스 목록을 확인해보았더니 다음과 같은 클래스들이 굉장히 많이 로드되어있었다.
sun.reflect.GeneratedConstructorAccessor54
sun.reflect.GeneratedConstructorAccessor57
sun.reflect.GeneratedConstructorAccessorXX
...
뒤에 숫자는 순차적으로 붙는 것 같은데 이게 확인해보니
톰캣 운영 중에 동적으로 생성되어 로드된 클래스였다.
이 클래스들이 Metaspace의 상당히 많은 부분을 차지하고 있었고 무엇인지에 대해 찾아보니 다음과 같았다.
JAVA reflection으로 메소드를 호출할 때 기본 최초 15번까지는 JNI를 통해 호출하는데 (inflation이라고 부름)
그 다음부터는 pure java로 처리하는데 이 때 생성되는 클래스가 GeneratedMethodAccessorXXX이다.
pure java가 JNI를 통한 것보다 속도가 빠르지만, 단점은 GeneratedMethodAccessor 클래스들이 많이 생겨서 Metaspace를 많이 쓴다는 것이다.
호출 빈도가 잦지 않은 경우는 성능은 떨어지더라도 JNI를 통해 처리하지만,
호출 빈도가 잦다고 판단되면(15회 이상) 아예 별도 클래스로 만들어서 처리하여 성능을 높이겠다는 전략이라고 볼 수 있을 것 같다.
(대신 Metaspace 영역은 조금 더 사용하겠지만)
다음 JVM 옵션으로 inflation을 몇 번까지 사용할지 변경도 가능하다. (메소드 단위로 카운팅됨)
sun.reflect.inflationThreshold=20
다음과 같이 설정하여 JNI 사용하지 않고 바로 클래스 생성하는 것도 가능하다.
sun.reflect.noInflation=true
위 동작 관련 코드는 sun.reflect.ReflectionFactory 클래스를 열어보면 확인할 수 있고
웹 서비스에서 이 값을 튜닝해서 쓸 정도의 시스템은 별로 없을 것 같긴 하다.
그리고 리플렉션 메소드 호출을 직접적으로 코드 상에서 많이 사용하지 않아도 스프링 같은 프레임워크를 쓴다면 내부적으로 많이 사용될 수 있다.
찾아본 정도는 이 정도인데 이 부분만 해도 꽤 될 것 같다.
- Spring Controller 메소드 호출 시 (DispatcherServlet과 Controller의 연결)
- myBatis select 쿼리 결과 Result class로 바인딩할 때
- Spring RestController 리턴 객체 json으로 변환 시
참고 내용
'개발 > 자바' 카테고리의 다른 글
JVM 트러블 슈팅 및 분석을 위한 명령어들 (0) | 2021.03.08 |
---|---|
Java Metaspace에 대해서 (0) | 2020.10.22 |
자바 성능을 결정짓는 코딩 습관과 튜닝 이야기 (0) | 2020.06.09 |
Effective Java 3/E - 8장 메서드 요약정리 (0) | 2019.05.26 |
Effective Java 3/E - 7장 람다와 스트림 요약정리 (0) | 2019.05.19 |