JVM이 super keyword에 대한 처리를 어떻게 할까요?

2013-07-10 13:45

자바 기반으로 프로그래밍할 때 많이 사용하는 키워드 중에 this와 super가 있습니다.

this는 인스턴스 자기 자신을 가리키고, super는 현재 인스턴스의 부모 인스턴스를 가리키는 keyword입니다. this는 JVM이 메소드를 호출할 때 각 메소드의 stack frame에 복사해서 지역변수로 가지고 다니면서 참조하는 방식을 취하잖아요? 그런데 super는 JVM이 어떤 방식으로 처리하나요? JVM이 super keyword를 처리하는 방식에 대해 검색해도 괜찮은 내용을 못찾겠네요.

대략적으로 예측해보면 인스턴스가 만들어지는 시점에 부모 인스턴스를 먼저 만들고, 자신의 인스턴스를 만든 후에 부모 인스턴스를 참조하도록 어딘가에 정보를 가지고 있을 것이라는 생각이 드는데요. super의 처리 과정에 대해 구체적으로 설명해 주시거나 문서 있으면 공유 부탁드립니다.

0개의 의견 from FB

BEST 의견 원본위치로↓
2013-07-10 14:18

이럴 때 제일 좋은 방법은 바이트코드를 보는 것입니다.

먼저 super 키워드에 대해서 검색해봤습니다. http://docs.oracle.com/javase/tutorial/java/IandI/super.html 가 나오네요. 여기에 부모 클래스 멤버에 접근하는 예가 있습니다. 이 예의 바이트코드를 javap로 얻습니다.

$ javac Superclass.java $ javac Subclass.java $ javap -c Subclass Compiled from "Subclass.java" public class Subclass extends Superclass{ public Subclass(); Code: 0: aload_0 1: invokespecial #1; //Method Superclass."":()V 4: return

public void printMethod(); Code: 0: aload_0 1: invokespecial #2; //Method Superclass.printMethod:()V 4: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream; 7: ldc #4; //String Printed in Subclass 9: invokevirtual #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 12: return

public static void main(java.lang.String[]); Code: 0: new #6; //class Subclass 3: dup 4: invokespecial #7; //Method "":()V 7: astore_1 8: aload_1 9: invokevirtual #8; //Method printMethod:()V 12: return

}

생성자나 super를 쓸 때는 invokespecial 명령을 씁니다. 보통은 invokevirtual을 쓰는데 특이하네요. 뭔가 이유가 있을 것 같습니다. 다시 검색을 합니다. 키워드는 "invokevirtual vs invokespecial"를 썼습니다. 구글 개인 최적화가 잘된 탓인지 저는 바로 http://stackoverflow.com/questions/13764238/why-invokespecial-is-needed-when-invokevirtual-exists 가 나옵니다. 들어가보니 설명이 딱 있네요.

"invokespecial is used to call methods without concern for dynamic binding, in order to invoke the particular class’ version of a method."

질문에서 약간 오해하고 있는 부분이 있으신 것 같습니다. 자기 인스턴스, 부모 인스턴스 이렇게 따로 있는 것이 아니라 자기 인스턴스만 있습니다. 이 인스턴스에다 어떤 메소드를 호출하느냐의 차이만 있습니다.

4개의 의견 from SLiPP

2013-07-10 14:18

이럴 때 제일 좋은 방법은 바이트코드를 보는 것입니다.

먼저 super 키워드에 대해서 검색해봤습니다. http://docs.oracle.com/javase/tutorial/java/IandI/super.html 가 나오네요. 여기에 부모 클래스 멤버에 접근하는 예가 있습니다. 이 예의 바이트코드를 javap로 얻습니다.

$ javac Superclass.java $ javac Subclass.java $ javap -c Subclass Compiled from "Subclass.java" public class Subclass extends Superclass{ public Subclass(); Code: 0: aload_0 1: invokespecial #1; //Method Superclass."":()V 4: return

public void printMethod(); Code: 0: aload_0 1: invokespecial #2; //Method Superclass.printMethod:()V 4: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream; 7: ldc #4; //String Printed in Subclass 9: invokevirtual #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 12: return

public static void main(java.lang.String[]); Code: 0: new #6; //class Subclass 3: dup 4: invokespecial #7; //Method "":()V 7: astore_1 8: aload_1 9: invokevirtual #8; //Method printMethod:()V 12: return

}

생성자나 super를 쓸 때는 invokespecial 명령을 씁니다. 보통은 invokevirtual을 쓰는데 특이하네요. 뭔가 이유가 있을 것 같습니다. 다시 검색을 합니다. 키워드는 "invokevirtual vs invokespecial"를 썼습니다. 구글 개인 최적화가 잘된 탓인지 저는 바로 http://stackoverflow.com/questions/13764238/why-invokespecial-is-needed-when-invokevirtual-exists 가 나옵니다. 들어가보니 설명이 딱 있네요.

"invokespecial is used to call methods without concern for dynamic binding, in order to invoke the particular class’ version of a method."

질문에서 약간 오해하고 있는 부분이 있으신 것 같습니다. 자기 인스턴스, 부모 인스턴스 이렇게 따로 있는 것이 아니라 자기 인스턴스만 있습니다. 이 인스턴스에다 어떤 메소드를 호출하느냐의 차이만 있습니다.

2013-07-10 15:08

@eungju.park.1 답변 고맙다.

나도 바이트 코드는 열심히 분석했는데 그 맥락을 이해하지 못했는데 그 이유가 계속해서 두 개의 인스턴스가 생성될 것이라 생각했기 때문이네. 그렇다보니 this처럼 어딘가에 부모 인스턴스에 대한 reference를 super라는 이름으로 가지고 있을거라 생각했는데 인스턴스가 하나만 만들어지기 때문에 super는 별도의 인스턴스를 가질 수 없는 것이 당연하다고 봐야겠네.

super를 사용할 경우에는 바이트 코드에서 현재 인스턴스의 부모 클래스 정보를 읽어서 해당 method를 호출하는 것으로 이해하는 것이 맞겠네. 여기까지 이해한 것이 맞는 건가?

페북에서 답변 준 http://blog.naver.com/PostView.nhn?blogId=2000yujin&logNo=130156863890 글의 설명을 보면 약간 헷갈리게 설명되어 있네. 자바 깊이 들어가면 들어갈 수록 쉽지 않네.

2013-07-10 16:28

@자바지기

넵 바이트코드에서 aload_0 가 실행되면 스택에 this 를 올리게 됩니다. JVM은 super를 모릅니다. super 키워드는 컴파일러가 해석해서 super.printMethod()를 Superclass.printMethod:()V로 만듭니다. 런타임에는 this만 있는거죠.

의견 추가하기

연관태그

← 목록으로