자바에서는 배열이 객체이다.
이것은 자바 언어 명세에 적혀있다. JLS 4.3.1
An object is a class instance or an array.
오브젝트는 클래스의 인스턴스이거나 배열이다.
C/C++ 의 배열
즉 C/C++의 배열과 달리 자바의 배열은 객체라는 큰 차이가 생긴다.
C언어에서는 sizeof 라는 명령으로 자료구조의 크기를 구할 수 있다.
#include <stdio.h>
int main(int argc, const char * argv[]) {
int num = 1;
int arr[2] = { 1, 2 };
printf("%lu\n", sizeof(num));
printf("%lu\n", sizeof(arr));
return 0;
}
C언어의 데이터 타입의 크기는 플랫폼(시스템)에 따라 다를 수 있는데 C표준에서 이야기 하고 있는 수준은 아래와 같다.
sizeof(int) <= sizeof(long int) <= sizeof(long long int)
내가 수행했을 때 4와 8이 콘솔에 출력이 되었다.
앞에 찍힌 4라는 값은 시스템에 따라 바뀔 수 있지만 뒤에 출력된 값이 2배가 된다라는 사실은 동일하다.
왜냐하면 배열이란 동일한 타입을 두 개를 묶은 개념은 바뀌지 않기 때문이다.
자바의 배열
위에 언급했듯이 자바에서 배열은 객체이다.
자바에서 객체를 만들 때 처럼 new 라는 연산자를 이용한다.
public class SingleArrayInt {
public static void main(String[] args) {
int[] array = new int[2];
if (array instanceof Object) {
System.out.println("Yes!");
}
}
위의 코드는 int 타입의 배열을 생성해서 Object 타입인지 확인하고 있다.
명세와 마찬가지로 array 변수의 타입은 객체이므로 Yes! 라는 출력이 된다.
바이트코드 관점
바이트 코드 관점에서는 배열 관련해서는 크게 3가지의 opcode가 있다.
자바에서는 new로 동일하게 만들지만 문맥에 따라서 아래 3가지로 바뀌게 된다.
opcode (hexa value) | operand(s) | 설명 |
NEWARRAY (0xBC) | atype | operand stack에서 길이를 꺼내서(pop) atype이 나타내는 primitive 타입의 새로운 배열을 할당한다. 새로운 배열은 objectref를 operand stack에 넣는다.(push) |
ANEWARRAY (0xBD) | indexbyte1, indexbyte2 | 위와 동일하지만 클래스의 객체에 대해 수행하는 것이 다르다. |
MULTIANEWARRAY (0xC5) | indexbyte1, indexbyte2, dimensions | 다차원배열을 만들 때 사용한다. operand stack에서는 각 차원의 길이를 획득하고 operand들에는 만들 타입과 크기를 이용한다. |
NEWARRAY
int[] array = new int[2];
위의 자바코드는 아래의 바이트코드로 바뀐다. (상수방식이나 지역변수 번호는 자바 컴파일러에 따라 문맥에 따라 바뀔 수 있다.)
0x05, 0xBC, 0x0A, 0x4C
이 바이트코드는 사람이 쉽게 이해를 하기 어려우므로 기호로 치환하면 아래와 같다.
hexa value | INSTRUCTION SET | 설명 | 참고 | |
0x05 | ICONST_2 | 상수 2를 operand stack에 push한다. | -1: iconst_m1 = 2 0: iconst_0 = 3 1 : iconst_1 = 4 2: iconst_2 = 5 3: iconst_3 = 6 4: iconst_4 = 7 5: iconst_5 = 8 6 ~ 127: bipush + byte ~ = 16 (0x10) 128 ~ 32767: sipush + byte1 + byte2 ~ = 17 (0x11) ~ 2147483647 : ldc + index = 18 (0x12) |
|
0xBC, 0x0A | NEWARRAY T_INT | 현재 operand stack에 있는 값(2)을 pop해서 int 타입의 배열을 생성하여 operand stack에 push한다. | 배열 타입 코드들 T_BOOLEAN = 4
|
|
0x4C | ASTORE 1 | 현재 operand stack에 있는 레퍼런스를 pop해서 local variable 1번에 store한다. | astore = 58 (0x3A) astore_0 = 75 (0x4B) astore_1 = 76 (0x4C) astore_2 = 77 (0x4D) astore_3 = 78 (0x4E)
|
ANEWARRAY
Object[] object = new Object[6];
위의 자바코드는 아래의 바이트코드로 바뀐다. (상수방식이나 지역변수 번호는 자바 컴파일러에 따라 문맥에 따라 바뀔 수 있다.)
0x10, 0x06, 0xBD, 0x00, 0x02, 0x4C
풀어쓰면 아래와 같다.
hexa value | INSTRUCTION SET |
0x10, 0x06 | BIPUSH 6 |
0xBD, 0x00, 0x02 | ANEWARRAY java/lang/Object |
0x4C | ASTORE 1 |
MULTIANEWARRAY
int[][] multipleArray = new int[2][3];
위의 자바코드는 아래의 바이트코드로 바뀐다. (상수방식이나 지역변수 번호는 자바 컴파일러에 따라 문맥에 따라 바뀔 수 있다.)
0x05, 0x06, 0xC5, 0x00, 0x02, 0x02, 0x4C
풀어쓰면 아래와 같다.
hexa value | INSTRUCTION SET | 참고 |
0x05 | ICONST_2 | |
0x06 | ICONST_3 | |
0xC5, 0x00, 0x02, 0x02 | MULTIANEWARRAY [[I 2 | B: byte C: char D: double F: float I: int J: long L ClassName ;: reference S: short Z: boolean [: reference eg) doube[][][] => [[[D |
0x4C | ASTORE 1 |
'Programing > JVM(Java, Kotlin)' 카테고리의 다른 글
[Java] 지역변수 이름과 죄수번호...? (1) | 2020.11.01 |
---|---|
[Java] Sonarqube: Modifiers should be declared in the correct order (0) | 2020.10.26 |
[책] 프로그래머의 장점과 단점 (0) | 2020.09.04 |
[Java] Effective Java의 Dogma (0) | 2020.08.19 |
[Java] count++, count+=1, count = count + 1 차이는 (0) | 2020.08.16 |