Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- Proxy Patter
- FCM
- @Valid
- restTemplate
- Effective Java
- JPA
- 플라이웨이트
- NotBlank
- multi module
- springboot
- db
- Firebase
- deleteById
- Connection Pool
- Web
- 디자인 패턴
- Service Locator
- @ControllerAdvice
- java
- 이펙티브 자바
- SQL 삽입 공격
- Service Locator 패턴
- Effetive Java
- @SpyBean
- Item04
- 데이터베이스
- Spring Boot
- NotEmpty
- 트랜잭션
- @MockBean
Archives
- Today
- Total
NoTimeForDawdling
Wrapper class Cache 파헤치기 본문
Java에 애플리케이션의 성능 향상을 위한 Cache로직이 종종 사용됩니다.
실제로 Integer 클래스는 내부에서 Integer 사용을 위해 IntegerCache를 관리합니다.
IntegerCache 정적 클래스
public final class Integer extends Number implements Comparable<Integer> {
...
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
...
}
- 위 코드는 Integer클래스 안에 있는 IngerCache 정적 클래스입니다.
- 코드로 보았을 때 low = -128, high = 127로 Integer Cache의 기본 범위는 -128 ~ 127이라는 것을 알 수 있습니다.
- 이 범위의 Integer 객체를 캐싱하는 이유는 개발할 때 빈번하게 사용되기 때문이라고 합니다.
- 자주 사용되는 값들만 따로 캐싱해 주는 것 같습니다.
Integer 클래스 내부의 valueOf 메서드
@HotSpotIntrinsicCandidate
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
- 위 코드는 Integer 클래스 내부에 있는 valueOf 메서드입니다.
- 코드를 보니 입력된 매개변수 값이 IntegerCache 범위를 벗어나지 않으면 캐싱해둔 Integer 값을 사용하고, 아니면 새로운 Integer 클래스를 만들어서 반환하는 것을 알 수 있습니다.
Integer값 비교
다음 코드의 결괏값이 어떻게 될지 생각해 봅시다.
public class Main {
public static void main(String[] args) {
Integer firstNumber = -128;
Integer secondNumber = -128;
System.out.println(firstNumber == secondNumber); //동일성
System.out.println(firstNumber.equals(secondNumber)); //동등성
}
}
결론부터 말하지면 동일성 & 동등성 결과 모두 true를 반환합니다.
why?
- Java는 모든 primitie type에 대해서 wrapper class를 제공하며, auto-boxing, auto-unboxing을 지원합니다.
- Integer는 int형의 wrapper 클래스로 auto-boxing이 적용됩니다.
- -128은 IntegerCache의 범위에 들어감으로 캐싱해둔 값을 반환하기 때문에 둘이 같은 Object를 가리키게 됩니다.
- 그러므로 동일성 비교(==)를 해도 true를 반환한 것입니다.
동일성과 동등성
- 동일성(==): 두 개의 오브젝트가 완전히 같을 경우 (주소 값 까지 같은 경우)
- 동등성(equals): 두 오브젝트가 같은 정보를 같고 있는 경우
그렇다면 다음 코드의 결과값은 어떻게 될지 생각해 봅시다.
public class Main {
public static void main(String[] args) {
Integer firstNumber = 128;
Integer secondNumber = 128;
System.out.println(firstNumber == secondNumber); //동일성
System.out.println(firstNumber.equals(secondNumber)); //동등성
}
}
- 128은 IntegerCache의 범위에 들어가지 않습니다. 그러므로 new Integer()를 통해 새로운 Object를 생성하게 됩니다.
- 즉, 같은 Object를 가리키지 않게 됩니다.(주소 값이 달라지게 됩니다.)
- 그러므로 동일성 비교(==)는 false, 동등성(equals) 비교는 true를 반환하게 됩니다.
정리
- 자주 사용하는 객체를 캐싱하여 이미 있는 객체가 다시 생성되지 않도록 할 수 있습니다.
- 자주 사용되는 객체를 캐싱하게 되면 메모리 요구량과 GC 비용을 줄일 수 있습니다.
- 하지만 동일성(==) 비교시 의도치 않은 결과를 발생시킬 수 있습니다.
'Java' 카테고리의 다른 글
Enum 클래스 파헤치기 (0) | 2021.02.23 |
---|---|
[Java] 불변 리스트(Immutable ArrayList) (0) | 2021.02.15 |
Arrays.asList() (0) | 2021.02.15 |
Java Virtual Machine(JVM) (0) | 2021.02.13 |
가비지 컬렉션(Garbage Collection) (0) | 2021.02.13 |