Notice
Recent Posts
Recent Comments
Link
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Archives
Today
Total
관리 메뉴

csct3434

[자바 성능 튜닝 이야기] 06~07. static, reflection 본문

개발 서적/자바 성능 튜닝 이야기

[자바 성능 튜닝 이야기] 06~07. static, reflection

csct3434 2024. 5. 5. 20:20

06. Static

static 잘 활용하기

  • 자주 사용하고 절대 변하지 않는 변수는 final static으로 선언하자
  • 설정 파일 정보는 static으로 관리하자
  • 코드성 데이터는 DB에서 한 번만 읽자

static 잘못 쓰면 이렇게 된다

  • static 변수를 여러 곳에서 수정하는 경우 동시성 문제가 발생한다
  • static으로 선언된 Collection 객체는 GC의 대상이 아니기 때문에, 계속해서 데이터가 쌓일 경우 OutOfMemoryError가 발생할 수 있다

정리

  • static은 원리를 알고 잘 사용하면 시스템의 성능을 향상시킬 수 있다
  • 하지만 잘못사용하면 돌이킬 수 없는 일, 시스템이 다운되거나 예기치 못한 결과가 발생할 수 있다
  • static은 반드시 메모리에 올라가며 GC의 대상이 되지 않는다
  • 만약 static을 사용하는 것이 걱정된다면, 아예 안쓰는 것이 안전하다.

07. reflection

reflection 이란?

  • 자바 API의 reflection 패키지에 있는 클래스(Class, Method, Field 등)를 통해 JVM에 로딩된 클래스의 여러가지 세부 정보를 조회할 수 있다.
  • 클래스의 메타 데이터 정보는 JVM의 Perm 영역에 저장되기 때문에, Class 클래스를 사용하여 엄청나게 많은 클래스를 동적으로 생성한다면 Perm 영역이 고갈되어 OutOfMemoryError가 발생할 수 있으니 조심해야 한다.
this.getClass().getName()

일반적으로 로그를 프린트할 때 클래스 이름을 알아내기 위해서는 위와 같이 Class 클래스를 많이 사용한다.

성능에 많은 영향을 미치지 않는다만, Class 객체를 만들고 그 객체의 이름을 가져오는 getName() 메서드를 실행하는 데 시간과 메모리가 사용된다는 점을 알아두자.

reflection 클래스를 잘못 사용한 사례

public String checkClass(Object src) {
	if(src.getClass().getName().equals("java.main.BigDecimal")) {
    	// 데이터 처리
    }
    // 이하 생략
}

간혹 어떤 개발자들은 reflection 관련 클래스를 너무 좋아한 나머지 이를 잘못 사용하는 경우가 있다. 이 경우 응답 속도에 그리 많은 영향을 주지는 않지만, 많이 사용하면 필요 없는 시간을 낭비하게 된다.

 

객체의 타입을 비교하는 조건문을 다음과 같이 수정할 수 있다.

public String checkClass(Object src) {
	if(src instanceof java.math.BigDecimal) {
    	// 데이터 처리
    }
    // 이하 생략
}

instanceof를 사용하니 코드가 훨씬 간단해졌다. 그렇다면 두 코드 사이에 얼마나 성능 차이가 있는지 비교해보자.

import java.math.BigDecimal;

class Reflection {
    
    int LOOP_COUNT=100;
    String result;
    
    public void withEquals() {
        Object src = new BigDecimal("6");
        for (int loop = 0; loop < LOOP_COUNT; loop++) {
            if(src.getClass().getName().equals("java.math.BigDecimal")) {
                result = "BigDecimal";
            }
        }
    }
    
    public void withInstanceOf() {
        Object src = new BigDecimal("6");
        for (int loop = 0; loop < LOOP_COUNT; loop++) {
            if(src instanceof java.math.BigDecimal) {
                result = "BigDecimal";
            }
        }
    }
}
대상 응답 시간(마이크로초)
withEquals() 1.022
withInstanceOf() 0.167

instanceof를 사용했을 때와 리플렉션을 사용했을 때를 비교하면 약 6배의 성능 차이가 발생한다. 시간으로 보았을 때 큰 차이는 발생하지 않았지만, 이런 부분이 모여 큰 차이를 만들기 때문에 작은 것부터 생각하면서 코딩하는 습관을 가지는 것이 좋다.