-128에서 127 사이의 값을 정수 클래스 캐싱하는 이유는 무엇입니까?


81

이전 질문과 관련 하여 Integer.valueOf (String)와의 == 비교가 127과 128에 대해 다른 결과를 제공하는 이유는 무엇입니까? , 우리 Integer class-128과 사이의 값을 저장하는 캐시 가 있다는 것을 알고 127있습니다.

-128과 127 사이 입니까?

Integer.valueOf () 문서 가 명시된 " 자주 값을 요청 캐시에 저장하는 것이다 " . 사이 그러나 값을 수행 -128하고 127자주 진짜 요청? 자주 요청되는 값 은 매우 주관적 이라고 생각했습니다 .
이것 뒤에 가능한 이유가 있습니까?

문서에서 " .. 그리고이 범위 밖의 다른 값을 캐시
할 수 있습니다 . " 어떻게이 작업을 수행 할 수 있습니까?


7
Re the documentation : Oracle은 나중에 동작을 변경하기로 결정한 경우를 대비하여 엉덩이를 덮고 있습니다. 예를 들어 Java 9가 -1024에서 1023까지 캐시하도록 결정할 수 있습니다. 메시지는 특정 정수를 포함하거나 포함하지 않는 캐시에 의존하지 않습니다.
Dawood ibn Kareem 2014 년

7
나는 당신이 13476에서 Y 로보 다 0에서 X까지 더 자주 반복한다고 가정합니다. 그들은 음수 값도 포함되어야하고 부호있는 바이트에 대해 -128-> 127이 합리적이라고 결정했을 것입니다.
Jeroen Vannevel 2014 년

2
루핑은 거의 항상 기본 정수로 수행되지 않습니까? 박스형 정수가 아닙니까? 캐싱이 적용되지 않습니다.
bradvido 2014 년

2
캐시는 순전히 성능 문제입니다. 성능 문제가 발생하지 않는 한 어떤 범위가 캐시되는지 신경 쓰지 않아야합니다. (그것은 당신의 코드 정수 캐싱에 대한 종속성에 빌드 어리 석음의 높이가 될 것입니다.)
핫 핥는

3
@JohnR Java 언어 사양에 있으며 아래 assylias 답변을 참조하십시오.
Zac Thompson

답변:


105

왜 -128에서 127 사이입니까?

더 큰 범위의 정수 캐시 수 있지만 적어도 -128에서 127 사이 의 정수 Java 언어 사양 (강조 내)에 의해 요구되기 때문에 캐시 되어야합니다 .

boxing되는 값 p가 true, false, 바이트 또는 \ u0000에서 \ u007f 범위의 char이거나 -128에서 127 (포함) 사이의 int 또는 짧은 숫자 인 경우 r1 및 r2를 p의 두 권투 변환. 항상 r1 == r2 인 경우입니다.

이 요구 사항의 근거는 같은 단락에 설명되어 있습니다.

이상적으로, 주어진 기본 값 p를 박싱하면 항상 동일한 참조가 생성 됩니다. 실제로 이것은 기존 구현 기술을 사용하여 실현 가능하지 않을 수 있습니다. 위의 규칙은 실용적인 타협입니다. 위의 마지막 절에서는 특정 공통 값을 항상 구별 할 수없는 개체로 묶어야합니다. [...]

이렇게하면 특히 소형 장치에서 과도한 성능 저하없이 대부분의 일반적인 경우 동작이 원하는 동작이됩니다 . 예를 들어 메모리 제한이 적은 구현에서는 모든 char 및 short 값은 물론 -32K에서 + 32K 범위의 int 및 long 값을 캐시 할 수 있습니다.


이 범위를 벗어난 다른 값을 캐시하려면 어떻게해야합니까?

사용 가능한 핫스팟 JVM 옵션-XX:AutoBoxCacheMax 목록에 실제로 문서화되지 않은 JVM 옵션사용할 수 있습니다 . 그러나 590 행 주위 Integer클래스 내부 주석에 언급되어 있습니다 .

캐시의 크기는 -XX:AutoBoxCacheMax=<size>옵션 으로 제어 할 수 있습니다 .

이것은 구현에 따라 다르며 다른 JVM에서 사용 가능할 수도 있고 사용 가능하지 않을 수도 있습니다.


2
이것은 완전하고 최선의 대답입니다. 질문은 -128에서 127 사이의 범위를 "자주 요청되는 값"과 혼동합니다. 사실 서로 다른 이유 때문입니다. 권투를 위해 -128에서 127까지 캐시됩니다. 성능을 위해 "자주 요청되는 값"이 캐시됩니다.
Zac Thompson

@ZacThompson, 이것을 지적 해 주셔서 감사합니다. 내 이전 댓글이 올바르지 않습니다. 사양의 핵심 문구는 "an int ... -128과 127 (포함) 사이의 것입니다. 그러면 r1과 r2를 p의 두 권투 변환 결과로 둡니다. 항상 r1 == r2 인 경우입니다." 그래서 내가 올바르게 이해한다면 사양은 Integer.valueOf (X) == Integer.valueOf (X) 여기서 -128 <= X <= 127을 요구합니다.
John R

이것은 "기본값"이 아닌 다른 것을 제공하는 질문의 "왜"부분에 대한 유일한 대답입니다. 그러나이 답변은 질문의 "어떻게"부분을 다루지 않기 때문에 완전하지 않습니다. XX : AutoBoxCacheMax에서 다른 사람의 응답을 참조하고 JVM의 다른 구현에서 캐싱 동작을 제어하는 ​​방법에 대한 정보를 추가하거나 (또는이 동작을 제어 할 수있는 옵션이있는 JVM 구현을 나타내는) 이것이 완전한 대답이 될 것입니다.
John R

"실제로 이것은 기존 구현 기술을 사용하여 실현 가능하지 않을 수 있습니다." 이 라인을 얻을 수 없습니다. 설명해 주시겠습니까?
niiraj874u

2
@ niiraj874u 현재 구현은 메모리에 상주하는 캐시를 사용합니다. 각 "정규"정수는 해당 캐시에 보관됩니다. 따라서 모든 정수를 캐싱하면 메모리에 최대 2 ^ 32 정수 (= 15 + GB)를 저장해야 할 수 있습니다. 이는 최신 데스크톱 컴퓨터에서도 비합리적입니다.
assylias

22

-128에서 127이 기본 크기입니다. 그러나 javadoc은 또한 Integer 캐시의 크기가 옵션에 의해 제어 될 수 있다고 말합니다 -XX:AutoBoxCacheMax=<size>. 높은 값만 설정하고 낮은 값은 항상 -128입니다. 이 기능은 1.6에서 도입되었습니다.

왜 -128에서 127까지-이것은 바이트 값 범위이며 매우 작은 캐시에 사용하는 것이 당연합니다.


어떻게 구현할 수 -XX:AutoBoxCacheMax=<size>있습니까?
DnR

java -XX : AutoBoxCacheMax = 256 ... 실행하면 Integer.valueOf (256) == Integer.valueOf (256)
Evgeniy Dorofeev 2014 년

java -XX:AutoBoxCacheMax=256콘솔에서 실행 하여Error:could not create the Java Virtual Machine
DnR

이 1.6 이상, 제 1.7 일 확인해야 -version 자바 시도
에브 게니 Dorofeev

2
자바 독을 제어 할 ..may 말한다 왜 그래, 이것은 ... 내 자바는 64 비트
에브 게니 Dorofeev

5

작은 정수를 캐싱하는 이유는 많은 알고리즘이 계산에 작은 정수를 사용하기 때문에 이러한 값에 대한 객체 생성 오버 헤드를 피하는 것이 가치가있는 경향이 있기 때문입니다.

그러면 캐시 할 정수가 문제가됩니다. 다시 말하면, 일반적으로 상수 값이 사용되는 빈도는 상수의 절대 값이 증가함에 따라 감소하는 경향이 있습니다. 모든 사람이 1 또는 2 또는 10 값을 사용하여 많은 시간을 보내고 상대적으로 소수는 109 값을 사용합니다. 집중적으로; 적은 수의 성능은 722에 대한 Integer를 얼마나 빨리 얻을 수 있는지에 달려 있습니다. Java는 부호있는 바이트 값 범위에 걸쳐 256 개의 슬롯을 할당하도록 선택했습니다. 이 결정은 당시 존재하는 프로그램을 분석하여 정보를 얻었을 수 있지만 순전히 임의적 인 결정일 가능성이 큽니다. 투자하기에 합당한 양의 공간이며 빠르게 액세스 할 수 있으며 (값이 캐시 범위에 있는지 확인하기위한 마스크, 캐시에 액세스하기위한 빠른 테이블 조회) 가장 일반적인 경우를 확실히 다룰 것입니다.

다시 말해, 귀하의 질문에 대한 대답은 "생각한 것만 큼 주관적이지는 않지만 정확한 범위는 대체로 어림짐작의 결정이며 ... 그리고 충분히 좋았다는 실험적 증거가 있습니다. "


3

캐시 할 수있는 최대 정수 값은 시스템 속성 즉 java.lang.Integer.IntegerCache.high( -XX:AutoBoxCacheMax)를 통해 구성 할 수 있습니다 . 캐시는 배열을 사용하여 구현됩니다.

    private static class IntegerCache {
    static final int high;
    static final Integer cache[];

    static {
        final int low = -128;

        // high value may be configured by property
        int h = 127;
        if (integerCacheHighPropValue != null) {
            // Use Long.decode here to avoid invoking methods that
            // require Integer's autoboxing cache to be initialized
            int i = Long.decode(integerCacheHighPropValue).intValue();
            i = Math.max(i, 127);
            // Maximum array size is Integer.MAX_VALUE
            h = Math.min(i, Integer.MAX_VALUE - -low);
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);
    }

    private IntegerCache() {}
}

0

Integer 클래스를 만나고 항상 -128에서 127 범위 내에서 boxing 될 때 아래와 같이 Integer 객체를 int 값으로 변환하는 것이 항상 좋습니다.

<Your Integer Object>.intValue()
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.