Monday
Java 생성자 분석 (바이트 코드) 본문
1. 자바 생성자 내부 동작 원리
다음과 같이 Animal 클래스가 있을 때 main 함수에서 new를 호출하면 어떻게 동작하는지 살펴보겠습니다.
// Animal.java
public class Animal {
String name;
public Animal() {
this.name = "동물";
}
public Animal(String name) {
this.name = name;
}
}
Main 함수
// Main.java
public class Main {
public static void main(String[] args) {
Animal tiger = new Animal("Strong Tiger");
System.out.println(tiger.name);
}
}
Main.class 바이트 코드
// class version 52.0 (52)
// access flags 0x21
public class Main {
// compiled from: Main.java
// access flags 0x1
public <init>()V
L0
LINENUMBER 1 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
RETURN
L1
LOCALVARIABLE this LMain; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
---------------------------- 여기서부터 5줄 정도만 보시면 됩니다 -------------------------------
// access flags 0x9
public static main([Ljava/lang/String;)V
L0
LINENUMBER 4 L0 //이 부분부터 살펴보시면
NEW Animal // new Animal을 호출하면 객체를 위한 Heap 공간을 할당한 후에 해당 변수를 Stack에 쌓아둡니다.
DUP // 그 후 해당 변수를 Stack에서 Duplicate, 복사 한 후
LDC "Strong Tiger" // 매개변수 "Strong Tiger"를 Stack 푸시하고
INVOKESPECIAL Animal.<init> (Ljava/lang/String;)V // Animal("Strong Tiger")를 호출합니다.
ASTORE 1
L1
LINENUMBER 5 L1
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ALOAD 1
GETFIELD Animal.name : Ljava/lang/String;
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
L2
LINENUMBER 6 L2
RETURN
L3
LOCALVARIABLE args [Ljava/lang/String; L0 L3 0
LOCALVARIABLE tiger LAnimal; L1 L3 1
MAXSTACK = 3
MAXLOCALS = 2
}
위 코드는 Main.class 파일의 바이트 코드를 살펴본 결과입니다. Main 함수에서 new 호출 시 Heap 영역에 Animal 객체를 위한 공간을 할당하고 그 주소를 가르키는 변수(P)를 Stack에 저장합니다. 그 후, dup명령어(스택 맨 위 변수 복제)를 사용하여 주소를 가르키는 변수(Tiger)를 복사하여 동일한 주소를 가르키는 새로운 변수(P2)를 스택에 생성합니다. 마지막으로, 매개변수 "String Tiger"를 Contant Pool에 저장 후 해당 위치를 가르키는 변수(S)를 스택에 푸시합니다. 마지막으로, P2, S를 스택에서 제거하면서 생성자를 호출합니다.
2. 생성자에 숨어있는 super()
다음과 같이 Animal 을 상속받는 Cat Class가 추가되었다고 가정하겠습니다.
public class Cat extends Animal {
int age;
public Cat(){
// super() 생략
age = 0;
}
public Cat(int age){
// super() 생략
this.age = age;
}
}
Cat 클래스 생성자 내부에는 사실 super()가 생략되어있습니다.
Cat.class 바이트 코드
// class version 52.0 (52)
// access flags 0x21
public class Cat extends Animal {
// compiled from: Cat.java
// access flags 0x0
I age
---------------- 여기서부터 보시면 됩니다(주석 확인) ------------
// access flags 0x1
public <init>()V // public Cat()
L0
LINENUMBER 4 L0
ALOAD 0
INVOKESPECIAL Animal.<init> ()V //super(). 즉, Animal()이 생략되어있습니다.
L1
LINENUMBER 5 L1
ALOAD 0
ICONST_3
PUTFIELD Cat.age : I
L2
LINENUMBER 6 L2
RETURN
L3
LOCALVARIABLE this LCat; L0 L3 0
MAXSTACK = 2
MAXLOCALS = 1
// access flags 0x1
public <init>(I)V //public Cat(int age)
L0
LINENUMBER 8 L0
ALOAD 0
INVOKESPECIAL Animal.<init> ()V //super(). 즉, Animal()이 생략되어있습니다.
L1
LINENUMBER 9 L1
ALOAD 0
ILOAD 1
PUTFIELD Cat.age : I
L2
LINENUMBER 10 L2
RETURN
L3
LOCALVARIABLE this LCat; L0 L3 0
LOCALVARIABLE age I L0 L3 1
MAXSTACK = 2
MAXLOCALS = 2
}
'언어 > Java 기타' 카테고리의 다른 글
자바 Exception 종류 (0) | 2021.06.12 |
---|---|
자바 JDBC 드라이버 연결 원리(Class.forName()) (0) | 2021.04.06 |
자바 Queue 함수 비교 (Null vs Exception) (0) | 2021.03.16 |
Java 중간값 구하기 (오버플로우 실수없이) (0) | 2021.03.15 |
1주차 : JVM과 자바 코드 실행 원리 (0) | 2021.02.09 |
Comments