JVMS21 공식문서 정리 - chapter4 - (2)

응큼한포도·2024년 4월 20일
0

JVMS21 공식문서 정리

목록 보기
11/11

이제 공식문서 절반이네 지금은 그냥 번역하는 수준이라 퀄리티 낮다. ㅈㅅ

The Constant Pool

JVM 명령어는 클래스, 인터페이스, 클래스 인스턴스 또는 배열의 실행 시 레이아웃에 의존하지 않는다. 대신, 명령어는 constant_pool 테이블에 있는 심볼 정보를 참조한다.

모든 constant_pool 테이블은 다음과 같다:

cp_info {
	u1 tag;
	u1 info[];
}

constant_pool 테이블의 각 항목은 해당 항목이 표시하는 상수의 종류를 나타내는 1byte 태그로 시작한다. 이 테이블에는 17가지 종류의 상수가 있으며, 각각의 태그와 해당하는 상수가 나열되어 있다. 이 태그는 해당 장의 섹션 번호에 따라 순서가 정해진다. 각 태그 바이트 다음에는 해당 상수에 대한 정보를 제공하는 두 개 이상의 byte가 있어야 한다. 추가 정보의 형식은 태그 byte에 따라 달라진다. 즉, info 배열의 내용은 태그 값에 따라 다양하다.

클래스 파일의 버전 번호가 v인 경우, constant_pool 테이블의 각 항목은 클래스 파일 형식(§4.1)의 버전 v 또는 그 이전에 처음으로 정의된 태그를 가져야 한다. 즉, 각 항목은 클래스 파일에서 사용이 승인된 상수의 종류를 나타내어야 한다. Table 4.4-B에는 각 태그가 처음으로 정의된 클래스 파일 형식의 버전이 나열되어 있다. 또한 해당 클래스 파일 형식을 도입한 Java SE 플랫폼의 버전도 표시되었다.

constant_pool 테이블의 일부 항목은 추가 계산을 가능케 하기 위해 실행 시 스택에 푸시될 수 있는 엔티티를 나타내기 때문에 로드 가능(loadable)하다. 클래스 파일의 버전 번호가 v인 경우, constant_pool 테이블의 항목이 로드 가능하려면 해당 항목이 클래스 파일 형식의 버전 v 또는 그 이전에서 처음으로 로드 가능하다고 판명된 태그를 가져야 한다. Table 4.4-C에는 각 태그가 처음으로 로드 가능하다고 판명된 클래스 파일 형식의 버전이 나열되어 있다. 또한 해당 클래스 파일 형식을 소개한 Java SE 플랫폼의 버전도 표시되었다.

The CONSTANT_Class_info Structure

CONSTANT_Class_info 구조는 클래스 또는 인터페이스를 표현하는 데 사용된다.

CONSTANT_Class_info {
u1 tag;
u2 name_index;
}

CONSTANT_Class_info structure의 아이템들의 구조는 다음과 같다:

tag
	The tag item has the value CONSTANT_Class 

name_index

name_index 항목의 값은 constant_pool 테이블 내의 유효한 인덱스여야 한다.
해당 인덱스의 constant_pool 항목은 내부 형식으로 인코딩된 유효한 이진 클래스 또는 인터페이스 이름을 나타내는 CONSTANT_Utf8_info 구조(§4.4.7)여야 한다.

배열은 객체이기 때문에, new 명령어가 아닌 anewarray와 multianewarray 명령어가 CONSTANT_Class_info 구조체를 사용하여 constant_pool 테이블에서 배열 "클래스"를 참조할 수 있다. 이러한 배열 클래스의 경우, 클래스의 이름은 배열 타입의 descriptor이다.(§4.3.2).

예를 들어보자.


public class ArrayExample {
    public static void main(String[] args) {
        // 배열의 길이는 3으로 지정합니다.
        int arrayLength = 3;

        // CONSTANT_Class_info를 사용하여 String 배열을 생성합니다.
        String[] stringArray = (String[]) java.lang.reflect.Array.newInstance(String.class, arrayLength);

        // 배열의 각 요소에 값을 할당합니다.
        stringArray[0] = "Hello";
        stringArray[1] = "World";
        stringArray[2] = "!";

        // 배열의 내용을 출력합니다.
        for (String str : stringArray) {
            System.out.println(str);
        }
    }
}

와 같이 java.lang.reflect.Array.newInstance()을 이용해서 배열을 생성하고 할당할 수 있다. 여기서 만든 배열은 CONSTANT_Class_info 구조체를 참조한다.

The CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and CONSTANT_InterfaceMethodref_info Structures

필드, 메서드 및 인터페이스 메서드는 유사한 구조로 표현된다.


CONSTANT_Fieldref_info {
  u1 tag;
  u2 class_index;
  u2 name_and_type_index;
}
CONSTANT_Methodref_info {
  u1 tag;
  u2 class_index;
  u2 name_and_type_index;
}
CONSTANT_InterfaceMethodref_info {
  u1 tag;
  u2 class_index;
  u2 name_and_type_index;
}

이 구조의 아이템은 다음과 같다:

tag

CONSTANT_Fieldref_info 구조의 tag 항목은 값으로 CONSTANT_Fieldref (9)를 가진다.
CONSTANT_Methodref_info 구조의 tag 항목은 값으로 CONSTANT_Methodref (10)를 가진다.
CONSTANT_InterfaceMethodref_info 구조의 tag 항목은 값으로 CONSTANT_InterfaceMethodref (11)를 가진다.

class_index

class_index 항목의 값은 constant_pool 테이블 내의 유효한 인덱스여야 한다. 해당 인덱스의 constant_pool 항목은 해당 필드 또는 메서드를 멤버로 가지고 있는 클래스 또는 인터페이스 type을 나타내는 CONSTANT_Class_info 구조체(§4.4.1)여야 한다.

CONSTANT_Fieldref_info 구조에서 class_index 항목은 클래스 유형 또는 인터페이스 type이 될 수 있습니다.

name_and_type_index

name_and_type_index 항목의 값은 constant_pool 테이블 내의 유효한 인덱스여야 한다. 해당 인덱스의 constant_pool 항목은 필드 또는 메서드의 이름과 descriptor를 나타내는 CONSTANT_NameAndType_info 구조체(§4.4.6)여야 한다.

CONSTANT_Fieldref_info 구조에서 지정된 descriptor는 필드 descriptor(§4.3.2)이어야 한다. 그렇지 않은 경우, 지정된 설명자는 메서드 descriptor(§4.3.3)여야 한다.

CONSTANT_Methodref_info 구조의 메서드 이름이 '<' ('\u003c')로 시작하는 경우, 해당 이름은 특별한 이름 이어야 한다. 이는 인스턴스 초기화 메서드를 나타낸다(§2.9.1). 이러한 메서드의 반환 유형은 반드시 void여야 한다.

The CONSTANT_String_info Structure

CONSTANT_String_info 구조는 String 타입의 상수 객체를 나타내는 데 사용된다.

CONSTANT_String_info {
  u1 tag;
  u2 string_index;
}

CONSTANT_String_info 구조의 항목은 다음과 같다:

tag

tag 아이템의 값은 CONSTANT_String이다.

string_index

string_index 항목의 값은 constant_pool 테이블 내의 유효한 인덱스여야 한다. 해당 인덱스의 constant_pool 항목은 String 객체를 초기화하기 위해 사용될 유니코드 코드 포인트의 시퀀스를 나타내는 CONSTANT_Utf8_info 구조체(§4.4.7)여야 한다.

The CONSTANT_Integer_info and CONSTANT_Float_info Structures

CONSTANT_Integer_info와 CONSTANT_Float_info 구조체는 4byte 숫자형(int와 float) 상수를 나타낸다.

CONSTANT_Integer_info {
	u1 tag;
	u4 bytes;
}
CONSTANT_Float_info {
	u1 tag;
	u4 bytes;
}

tag

CONSTANT_Integer_info 구조의 tag 항목은 CONSTANT_Integer(3) 값을 가진다.
CONSTANT_Float_info 구조의 tag 항목은 CONSTANT_Float(4) 값을 가진다.

bytes

CONSTANT_Integer_info 구조의 bytes 항목은 int 상수의 값을 나타낸다. 값의 byte는 big-endian(높은 byte 우선) 순서로 저장됩니다.

CONSTANT_Float_info 구조의 bytes 항목은 IEEE 754 binary32 부동 소수점 형식(§2.3.2)에 따른 float 상수의 값을 나타낸다. 항목의 byte는 big-endian(높은 byte 우선) 순서로 저장된다.

CONSTANT_Float_info 구조로 표현된 값은 다음과 같이 결정된다. 값의 byte는 먼저 int 상수 비트로 변환된다. 그리고:

• bits가 0x7f800000인 경우, float 값은 양의 무한대가 된다.
• bits가 0xff800000인 경우, float 값은 음의 무한대가 된다.
• bits가 0x7f800001부터 0x7fffffff 또는 0xff800001부터 0xffffffff 범위에 있는 경우, float 값은 NaN(숫자가 아님)이 된다.
• 그 외의 모든 경우에는 bits에서 계산된 세 개의 값 s, e, m이 존재한다:

int s = ((bits >> 31) == 0) ? 1 : -1;
int e = ((bits >> 23) & 0xff);
int m = (e == 0) ?
(bits & 0x7fffff) << 1 :
(bits & 0x7fffff) | 0x800000;

그리고 float 값은 수학적 표현식 s · m · 2e-150의 결과와 같다.

The CONSTANT_Long_info and CONSTANT_Double_info Structures

CONSTANT_Long_info와 CONSTANT_Double_info는 8byte 숫자형(long과 double) 상수를 나타낸다.

CONSTANT_Long_info {
  u1 tag;
  u4 high_bytes;
  u4 low_bytes;
}
CONSTANT_Double_info {
  u1 tag;
  u4 high_bytes;
  u4 low_bytes;
}

모든 8바이트 상수는 클래스 파일의 constant_pool 테이블에서 두 개의 항목을 차지한다. 만약 CONSTANT_Long_info 또는 CONSTANT_Double_info 구조체가 constant_pool 테이블의 인덱스 n에 있는 항목이라면, 테이블에서 다음 사용 가능한 항목은 인덱스 n+2에 위치한다. constant_pool 인덱스 n+1은 유효해야 하지만 사용할 수 없는 것으로 간주된다.

구조의 아이템들은 다음과 같다:

tag

CONSTANT_Long_info 구조의 tag 항목은 CONSTANT_Long(5) 값을 가진다.
CONSTANT_Double_info 구조의 tag 항목은 CONSTANT_Double(6) 값을 가진다.

high_bytes, low_bytes

CONSTANT_Long_info 구조의 unsigned high_bytes와 low_bytes 항목은 long 상수의 값을 나타낸다. 이때 각각의 high_bytes와 low_bytes의 바이트는 big-endian(높은 바이트 우선) 순서로 저장되며, long 상수의 값은 다음과 같이 계산된다: ((long) high_bytes << 32) + low_bytes

ONSTANT_Double_info 구조의 high_bytes와 low_bytes 항목은 IEEE 754 binary64 부동 소수점 형식(§2.3.2)에 따른 double 값을 나타낸다. 각 항목의 바이트는 big-endian(높은 바이트 우선) 순서로 저장된다.

그리고

• bits가 0x7ff0000000000000L인 경우, double 값은 양의 무한대가 된다.
• bits가 0xfff0000000000000L인 경우, double 값은 음의 무한대가 된다.
• bits가 0x7ff0000000000001L부터 0x7fffffffffffffffL 또는 0xfff0000000000001L부터 0xffffffffffffffffL 범위에 있는 경우, double 값은 NaN(숫자가 아님)이 된다.
• 그 외의 모든 경우에는 bits에서 계산된 세 개의 값 s, e, m이 존재한다:

int s = ((bits >> 63) == 0) ? 1 : -1;
int e = (int)((bits >> 52) & 0x7ffL);
long m = (e == 0) ?
(bits & 0xfffffffffffffL) << 1 :
(bits & 0xfffffffffffffL) | 0x10000000000000L;

그리고 부동 소수점 값은 수학적 표현식 s · m · 2e-1075의 double 값과 같다.

0개의 댓글