Java

[Java] IntegerCache: Integer 객체에서 캐싱을 제공한다고?

Woonys 2022. 6. 16. 22:32
반응형

Introduction

회사 슬랙 채널에 재밌는 글이 올라왔다.

 

 

<이것이 자바다>에서 배우기로, 기본적으로 서로 다른 두 객체는 갖는 값에 상관없이 힙 영역 내 서로 다른 주소 번지에 위치하게 된다. 그렇다면 위의 예시에서 같은 값을 서로 다른 두 Integer 객체 a, b에 대해 비교하면 둘다 false가 나와야 정상일 것이다. 그런데 위의 코드를 실행하면 아래와 같은 결과가 나온다.

public static void main(String[] args) {
                // case 1
        Integer a = 127;
        Integer b = 127;
        System.out.println(a == b);
                // true

                // case 2
        Integer a = 128;
        Integer b = 128;
        System.out.println(a == b);
                // false
    }

애당초 둘다 false여야 하거늘, 차라리 둘다 true가 떴으면 떴지 왜 case 1은 true이고 case 2는 false란 말인가? 이미 눈치 챈 사람들을 위해 결론부터 말하자면, 바로 자바 integer 객체에서 자체적으로 지원하는 캐싱 기능 때문이다.

Java IntegerCache: Integer 객체 내부 Caching 기능

Java에서는 Integer 객체에 대해 Integer Cache 기능을 제공한다. 말 그대로 정수 리터럴을 변수에 배정할 때, 기존에 만들어 둔 Int 객체 중에 동일한 값이 있다면 새 객체를 생성하는 게 아니라 미리 만들어둔 객체를 참조하도록 한다. 즉, 위 예제 case1에서 a와 b는 같은 객체를 참조하고 있는 것이다. 정확히는 앞에서 만든 Integer a에 대한 객체를 b가 동일하게 참조하고 있는 것.

이 기능은 자바 5에서 추가된 것인데, 메모리 관리를 효율적으로 하기 위한 기능이다. 하지만 모든 정수값에 대해 캐싱 기능을 제공하는 것은 아니다. 아래 코드를 살펴보자. 자바에서 제공하는 IntegerCache 기능에 대한 코드이다. min값이 -128, max값이 127인 것을 볼 수 있다. 즉, -128부터 127 사이에 있는 값에 한해서만 캐싱 기능을 제공하는 것. case 2에서 a,b는 캐싱 기능이 제공되지 않아 서로 다른 객체를 참조한다. 그러니 false를 반환하는 것.

// A program demonstrate IntegerCache
// implementation in Java.

// This is how IntegerCache class works.
private static class IntegerCache {

     // Method and variable declaration.
    static final int low = -128;
    static final int high;
    static final Integer[] cache;
    private IntegerCache() {}

    static
    {
        // Range value from -128 to 127
        int var0 = 127;
        String var1 = VM.getSavedProperty(
            "java.lang.Integer.IntegerCache.high");
        int var2;

       // Check if var1 value is null or not.
        if (var1 != null) {

          // For exception case
           try {
                var2 = Integer.parseInt(var1);
                var2 = Math.max(var2, 127);
                var0 = Math.min(var2, 2147483518);
            }
            catch (NumberFormatException var4) {
            }
        }

        high = var0;

       // High range for IntegerCache
        cache = new Integer[high - -128 + 1];
        var2 = -128;

       // defining var3 values using loop.
        for (int var3 = 0; var3 < cache.length; ++var3) {
            cache[var3] = new Integer(var2++);
        }
        assert high >= 127;
    }
}

Reference

반응형