>  기사  >  Java  >  Java 가상 머신: 런타임 상수 풀

Java 가상 머신: 런타임 상수 풀

巴扎黑
巴扎黑원래의
2017-06-26 09:56:061450검색

1. 런타임 상수 풀 소개

런타임 상수 풀(런타임 상수 풀)은 메소드 영역의 일부입니다. 클래스클래스 버전, 필드, 메소드, 인터페이스 및 기타 설명과 같은 정보 외에도 컴파일 중에 생성된 다양한 리터럴과 기호를 저장하는 데 사용되는 상수 풀에 대한 정보(상수 풀 테이블)도 있습니다. 참고로, 콘텐츠의 이 부분은 클래스가 로드된 후 상수 풀에 저장됩니다.

런타임 상수는 상수에 상대적입니다. 여기에는 역학이라는 중요한 기능이 있습니다. 물론, 동일한 값을 갖는 동적 상수는 우리가 일반적으로 이야기하는 상수와는 다른 소스에서만 제공되지만 모두 풀의 동일한 메모리 영역에 저장됩니다. Java 언어에서는 컴파일 중에만 상수를 생성할 필요가 없습니다. 런타임 중에도 새 상수가 생성될 수 있으며 이러한 상수는 런타임 상수 풀에 배치됩니다. 여기에 언급된 상수에는 기본 유형 Packaging 클래스(패키징 클래스는 부동 소수점 유형을 관리하지 않고 정수만 -128에서 127까지 관리함) 및 문자열(String.intern()을 통해 문자열을 강제로 배치할 수도 있음)이 포함됩니다.

2. 클래스 파일의 정보 상수 풀

클래스 파일 구조에서 처음 4바이트는 파일이 허용되는지 여부를 결정하는 Megic Number를 저장하는 데 사용됩니다. JVM 다음 4바이트는 버전 번호를 저장하는 데 사용되며 처음 2바이트는 부 버전 번호를 저장하고 마지막 2바이트는 주 버전 번호를 저장하며 상수 풀은 상수 수를 저장하는 데 사용됩니다. 고정되지 않은 경우 상수 풀 항목은 상수 풀 용량 카운트 값을 저장하기 위해 U2 유형 데이터(constant_pool_count)를 배치합니다.

상수 풀은 주로 리터럴과 기호 참조라는 두 가지 주요 상수 유형을 저장하는 데 사용됩니다. 리터럴은 텍스트 문자열, 최종으로 선언된 상수 값 등과 같은 Java 언어 수준의 상수 개념과 동일합니다. , 기호 참조는 다음 세 가지 유형의 상수를 포함하는 컴파일 원칙의 개념입니다.

  • 클래스 및 인터페이스의 정규화된 이름

  • 필드 이름 및 설명자

  • 메서드 이름 및 설명자

3 . 상수 풀의 장점

상수 풀은 시스템 성능에 영향을 미치는 객체의 빈번한 생성과 소멸을 방지하고 객체 공유를 실현합니다. 예를 들어 문자열 상수 풀은 컴파일 단계에서 모든 문자열 리터럴을 상수 풀에 넣습니다.

  • 메모리 공간 절약: 상수 풀에 있는 동일한 문자열 상수가 모두 병합되어 한 공간만 차지합니다.

  • 실행 시간 절약: 문자열을 비교할 때 ==가 equals()보다 빠릅니다. 두 개의 참조 변수의 경우 ==를 사용하여 참조가 동일한지 여부를 확인하고 실제 값이 동일한지 확인할 수도 있습니다.

이중 등호의 의미==

  • 기본 데이터 유형 간에는 이중 등호를 적용하여 그 수치를 비교합니다.

  • 복합 데이터 유형(클래스) 사이에는 이중 등호가 적용되어 메모리의 저장 주소를 비교합니다.

4. 기본 타입 패키징 클래스와 상수 풀

Java의 대부분의 기본 타입 패키징 클래스는 상수 풀 기술, 즉 Byte, Short, Integer, Long, Character, Boolean을 구현합니다. 이러한 5가지 패키징 클래스는 기본적으로 [-128, 127] 값을 사용하여 해당 유형의 캐시 데이터를 생성하지만 이 범위를 벗어나는 경우에도 새 객체가 생성됩니다. 두 개의 부동 소수점 유형 래퍼 클래스인 Float 및 Double은 상수 풀 기술을 구현하지 않습니다.

1) 정수 및 상수 풀

Java 가상 머신: 런타임 상수 풀
Integer i1 = 40;
Integer i2 = 40;
Integer i3 = 0;
Integer i4 = new Integer(40);
Integer i5 = new Integer(40);
Integer i6 = new Integer(0);

System.out.println("i1=i2   " + (i1 == i2));
System.out.println("i1=i2+i3   " + (i1 == i2 + i3));
System.out.println("i1=i4   " + (i1 == i4));
System.out.println("i4=i5   " + (i4 == i5));
System.out.println("i4=i5+i6   " + (i4 == i5 + i6));  
System.out.println("40=i5+i6   " + (40 == i5 + i6));


i1=i2   true
i1=i2+i3   true
i1=i4   false
i4=i5   false
i4=i5+i6   true
40=i5+i6   true
Java 가상 머신: 런타임 상수 풀
설명:
  • Integer i1=40; Java는 코드를 Integer i1=In으로 직접 캡슐화합니다. t eger를 컴파일할 때. (40); 상수 풀의 개체를 사용합니다.

  • Integer i1 = new Integer(40); 이 경우 새로운 객체가 생성됩니다.

  • i4 == i5 + i6, + 연산자는 Integer 객체에 적용되지 않기 때문입니다. 먼저 i5와 i6은 자동 unboxing 작업을 수행하고 값 ​​, 즉 i4 == 40을 추가합니다. 그러면 Integer 객체는 수치값과 직접 비교할 수 없으므로 i4는 자동으로 이를 Unboxing하여 int값 40으로 변환한다. 마지막으로 이 명령문을 수치비교를 위해 40 == 40으로 변환한다.

2) 문자열 및 상수 풀 - 일반적인 메서드 할당

Java 가상 머신: 런타임 상수 풀
String str1 = "abcd";
String str2 = new String("abcd");
System.out.println(str1==str2);//false

String str1 = "str";
String str2 = "ing";
String str3 = "str" + "ing";
String str4 = str1 + str2;
System.out.println("string" == "str" + "ing");// true
System.out.println(str3 == str4);//false

String str5 = "string";
System.out.println(str3 == str5);//true
Java 가상 머신: 런타임 상수 풀
解释:
  • "abcd"是在常量池中拿对象,new String("abcd")是直接在堆内存空间创建一个新的对象。只要使用new方法,便需要创建新的对象

  • 连接表达式 +,只有使用引号包含文本的方式创建的String对象之间使用“+”连接产生的新对象才会被加入常量池中

  • 对于字符串变量的“+”连接表达式,它所产生的新对象都不会被加入字符串池中,其属于在运行时创建的字符串,具有独立的内存地址,所以不引用自同一String对象。

3)String与常量池-静态方法赋值

Java 가상 머신: 런타임 상수 풀
public static final String A; // 常量A
public static final String B;    // 常量B
static {  
   A = "ab";  
   B = "cd";  
}  
public static void main(String[] args) {  
// 将两个常量用+连接对s进行初始化  
String s = A + B;  
String t = "abcd";  
if (s == t) {  
    System.out.println("s等于t,它们是同一个对象");  
  } else {  
    System.out.println("s不等于t,它们不是同一个对象");  
  }  
}
Java 가상 머신: 런타임 상수 풀
解释:

s不等于t,它们不是同一个对象。A和B虽然被定义为常量,但是它们都没有马上被赋值。在运算出s的值之前,他们何时被赋值,以及被赋予什么样的值,都是个变数。因此A和B在被赋值之前,性质类似于一个变量。那么s就不能在编译期被确定,而只能在运行时被创建了。

4)String与常量池-intern方法

Java 가상 머신: 런타임 상수 풀
public static void main(String[] args) {
  String s1 = new String("计算机");
  String s2 = s1.intern();
  String s3 = "计算机";
  System.out.println("s1 == s2? " + (s1 == s2));
  System.out.println("s3 == s2? " + (s3 == s2));
}
s1 == s2? false
s3 == s2? true
Java 가상 머신: 런타임 상수 풀
解释:

String的intern()方法会查找在常量池中是否存在一份equal相等的字符串,如果有则返回该字符串的引用,如果没有则添加自己的字符串进入常量池

5)String与常量池-延伸

String s1 = new String("xyz"); //创建了几个对象?
解释:

考虑类加载阶段和实际执行时。

  • 类加载对一个类只会进行一次。”xyz”在类加载时就已经创建并驻留了(如果该类被加载之前已经有”xyz”字符串被驻留过则不需要重复创建用于驻留的”xyz”实例)。驻留的字符串是放在全局共享的字符串常量池中的。

  • 在这段代码后续被运行的时候,”xyz”字面量对应的String实例已经固定了,不会再被重复创建。所以这段代码将常量池中的对象复制一份放到heap中,并且把heap中的这个对象的引用交给s1 持有

这条语句创建了2个对象。

위 내용은 Java 가상 머신: 런타임 상수 풀의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.