최종에서 고배를 마셨던 11번가의 기술 면접에서 받았던 질문 중 가장 기억에 남는 질문이었던 Integer
의 caching 기능에 대해서 알아보고자 한다.
Integer a = 127;
Integer b = 127;
System.out.println(a==b); // ???
다음과 같이 127 값을 갖고 있는 두 개의 Integer
객체를 비교했을 때, 결과는 어떻게 될까?
처음 이 질문을 접했을 때, Integer
가 new
생성자로 생성하는 객체들은 당연히 Heap memory에 서로 다른 주소 값을 가진 객체로 존재할 것이라고 생각했고, 결과는 false
가 나올 것이라고 생각했지만 실제로는 true
가 출력된다.
Integer
클래스는 내부에서 Integer
의 사용을 위해서 IntegerCache
를 관리한다. 이 캐시의 기본 범위는 -128 ~ 127
이며, Integer.valueOf()
메소드는 캐시 범위에 해당하는 objects
를 리턴하게 된다.
위 코드를 다시 보자.
Integer a = 127;
Integer b = 127;`
JAVA는 Referene Type들에 대해서 auto-boxing, auto-unboxing
을 제공한다. 따라서 위 코드는 다음과 같이 작동한다.
Integer a = Integer.valueOf(127);
Integer b = Integer.valueOf(127);
위에서 언급했듯이 Integer
의 IntegerCache
는 valueOf
로 넘어온 값들에 대해서 127
이라는 값을 가지고 있는 같은 object
를 넘겨 준다.
따라서 a==b
는 a와 b의 메모리 주소를 비교하게 되고, true
를 출력하게 되는 것이다.
IntegerCache.low
와IntegerCache.high
의 기본 값은 각각 -128
, 127
이다.
즉, Integer.valueOf()
메소드는 -128 ~ 127
사이의 int literal을 넘겨줄 떄, 새로운 Integer
를 생성하는 대신 내부의 IntegerCache
객체에서 Integer
객체를 반환하는 것이다.
이러한 캐싱은 Integer
뿐만 아니라, Integer.IntegerCache
처럼 ByteCache
, ShortCache
, LongCache
, CharacterCache
도 각각 존재한다.
Byte, Short, Long 타입은 -127~127의 고정된 캐시값을 가진다. 하지만, Character는 0부터 127까지의 고정된 캐시값을 가진다.
범위를 수정하는 것은 Integer만 수정할 수 있고 다른 타입은 수정이 불가능하다.
-XX:AutoBoxCacheMax
캐시는 IntegerCache
클래스가 메모리에 로드되는 처음에 초기화되는데, 캐시의 최대값은 JVM 옵션을 통해 위와 같이 조정할 수 있다.