developer tip

Integer 래퍼 클래스를 사용하여 생성되는 개체는 몇 개입니까?

copycodes 2020. 12. 6. 21:42
반응형

Integer 래퍼 클래스를 사용하여 생성되는 개체는 몇 개입니까?


Integer i = 3; 
i = i + 1; 
Integer j = i; 
j = i + j; 

위의 샘플 코드에있는 명령문의 결과로 생성 된 개체 수와 그 이유는 무엇입니까? 생성 된 개체 수를 볼 수있는 IDE가 있습니까 (디버그 모드 일 수 있음)?


놀랍게도 대답은 0입니다.

Integer-128에서 +127까지의 모든 s는 JVM에 의해 미리 계산됩니다.

코드 는 이러한 기존 개체에 대한 참조만듭니다 .


정답은 Integer생성 되는 객체 의 수가 불확실 하다는 것입니다 . 0에서 3 사이, 256 1 또는 2 이상일 수 있습니다 .

  • 자바 플랫폼 3 ,
  • 이 코드가 처음 실행되었는지 여부 및
  • (잠재적으로) int값의 권투에 의존하는 다른 코드가 그 전에 실행 되는지 여부 4 .

Integer-128에서 127까지 값은 사전 계산 에 반드시 필요한 것은 아닙니다 . 실제로 Boxing 변환을 지정한 JLS 5.1.7 은 다음과 같이 말합니다.

boxing되는 값 p가 -128과 127 (§3.10.1) 사이의 int 유형의 정수 리터럴 인 경우 ... a와 b를 p의 두 권투 변환 결과로 둡니다. 항상 a == b 인 경우입니다.

주의해야 할 두 가지 사항 :

  • JLS 는 >> literals << 에만 이것을 필요로합니다 .
  • JLS는 값의 eager 캐싱을 요구하지 않습니다 . 지연 캐싱은 JLS의 동작 요구 사항도 충족합니다.

에 대한 javadoc조차도 결과가 열심히 캐시되도록 지정Integer.valueof(int) 하지 않습니다 .

java.lang.IntegerJava 6에서 8까지 의 Java SE 소스 코드를 살펴보면 현재 Java SE 구현 전략이 값을 미리 계산하는 것임이 분명합니다. 그러나 여러 가지 이유로 (위 참조) "얼마나 많은 객체"질문에 대한 명확한 답변을 제공하기에 충분하지 않습니다.


1-위 코드를 실행하면 클래스 Integer초기화 중에 캐시가 열심히 초기화되는 Java 버전에서 클래스 초기화가 트리거되면 256이 될 수 있습니다 .

2-캐시가 JVM 사양에 필요한 것보다 크면 더 많을 수 있습니다. 일부 Java 버전에서는 JVM 옵션을 통해 캐시 크기를 늘릴 수 있습니다.

3-복싱 구현에 대한 플랫폼의 일반적인 접근 방식 외에도 컴파일러는 계산의 일부 또는 전부를 컴파일 타임에 수행하거나 완전히 최적화 할 수 있음을 발견 할 수 있습니다.

4-이러한 코드는 정수 캐시의 지연 또는 즉시 초기화를 트리거 할 수 있습니다.


우선 : 0다른 사람들이 이미 언급했듯이 귀하가 찾고있는 답은 입니다.

하지만 좀 더 자세히 살펴 보겠습니다. Stephen이 언급했듯이 실행 시간에 따라 다릅니다. 캐시가 실제로 지연 초기화되기 때문입니다.

java.lang.Integer.IntegerCache의 문서를 보면 :

캐시는 처음 사용할 때 초기화됩니다.

즉, Integer를 처음 호출하는 경우 실제로 생성합니다.

  • 256 개의 정수 객체 (또는 그 이상 : 아래 참조)
  • 1 정수를 저장할 배열의 객체
  • 클래스 저장에 필요한 객체 (및 메서드 / 필드)는 무시하겠습니다. 어쨌든 메타 공간에 저장됩니다.

두 번째로 호출 할 때부터 0 개의 개체를 만듭니다.


숫자를 조금 더 높이면 상황이 더 재미있어집니다. 예를 들면 다음과 같습니다.

Integer i = 1500; 

유효한 옵션은 다음과 같습니다. 0, 1 또는 1629에서 2147483776 사이의 숫자 (이번에는 생성 된 정수 값만 계산합니다. 이유는 무엇입니까? 대답은 정수 캐시 정의의 다음 문장에 나와 있습니다.)

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

따라서 실제로 구현되는 캐시의 크기를 변경할 수 있습니다.

즉, 위 라인에 도달 할 수 있습니다.

  • 1 : 캐시가 1500보다 작은 경우 새 개체
  • 0 : 캐시가 이전에 초기화되었고 1500 개가 포함 된 경우 새 개체
  • 1629 : new (Integer)-캐시가 정확히 1500으로 설정되고 아직 초기화되지 않은 경우 개체입니다. 그런 다음 -128에서 1500까지의 정수 값이 생성됩니다.
  • 위의 문장에서와 같이 여기에 Integer.MAX_VALUE + 129까지 정수 객체의 양에 도달합니다. 이것은 언급 된 2147483776입니다.

주의 사항 : 이것은 Oracle / Open JDK에서만 보장됩니다 (버전 7 및 8 확인).

보시다시피 완전한 정답을 얻기가 쉽지 않습니다. 하지만 말만하면 0사람들이 행복해집니다.


추신 : 멘션 된 매개 변수를 사용하면 다음 문장을 참으로 만들 수 있습니다. Integer.valueOf(1500) == 1500


The compiler unboxes the Integer objects to ints to do arithmetic with them by calling intValue() on them, and it calls Integer.valueOf to box the int results when they are assigned to Integer variables, so your example is equivalent to:

Integer i = Integer.valueOf(3);
i = Integer.valueOf(i.intValue() + 1);
Integer j = i;
j = Integer.valueOf(i.intValue() + j.intValue());

The assignment j = i; is a completely normal object reference assignment which creates no new objects. It does no boxing or unboxing, and doesn't need to as Integer objects are immutable.

The valueOf method is allowed to cache objects and return the same instance each time for a particular number. It is required to cache ints −128 through +127. For your starting number of i = 3, all the numbers are small and guaranteed to be cached, so the number of objects that need to be created is 0. Strictly speaking, valueOf is allowed to cache instances lazily rather than having them all pre-generated, so the example might still create objects the first time, but if the code is run repeatedly during a program the number of objects created each time on average approaches 0.

What if you start with a larger number whose instances will not be cached (e.g., i = 300)? Then each valueOf call must create one new Integer object, and the total number of objects created each time is 3.

(Or, maybe it's still zero, or maybe it's millions. Remember that compilers and virtual machines are allowed to rewrite code for performance or implementation reasons, so long as its behavior is not otherwise changed. So it could delete the above code entirely if you don't use the result. Or if you try to print j, it could realize that j will always end up with the same constant value after the above snippet, and thus do all the arithmetic at compile time, and print a constant value. The actual amount of work done behind the scenes to run your code is always an implementation detail.)


You can debug the Integer.valueOf(int i) method to find out it by yourself. This method is called by the autoboxing process by the compiler.

참고URL : https://stackoverflow.com/questions/36058577/how-many-objects-are-created-by-using-the-integer-wrapper-class

반응형