[Java] IntegerCache: Integer 객체에서 캐싱을 제공한다고?
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;
}
}