JAVA/JAVA Basic

[ JAVA ] 상속의 원리 : 메소드 동적 바인딩

IT록흐 2021. 6. 18. 21:53
반응형

 

 

메소드 오버라이딩을

공부하면서 궁금했다.

 

 

상속받은 메소드와

오버라이딩 된 메소드는

어떻게 구분이 되는 것일까?

출처 입력

 

메소드 호출 코드이다.

 

Car car = new Car();

car.run();

참조 변수 + .(도트연산자) + 메소드 이름

 

 

이 코드 안에

모든 답이 들어있다.

 

 

참조변수는 객체의 주소를 담고 있다. 이 말은 메소드 정보를 얻으려면 객체에 접근하라는 것이다. 하지만 메소드는 Heap영역이 아닌 메소드영역에 존재한다. 그렇다면 왜 참조변수를 통해, Heap영역에 접근하는 것일까?

 

 

 

 

 

 

 

그 이유는 객체 안에 가상 메소드 테이블(vtable)의 주소가 저장되어 있기 때문이다. 가상 메소드 테이블(vtable)은 클래스가 메모리를 할당 받을 때, 클래스 자신의 메소드를 비롯해 상속받은 모든 메소드의 주소를 모아 정리한 가상의 테이블이다. 객체가 생성되면, 객체는 4byte 안에 vtable 주소를 저장한다. vtable은 상속받은 클래스의 vtable을 토대로, 해당 클래스의 메소드 주소를 추가하여 생성되어진다.

 

상속의 원리는 간단하다. 자식 vtable에 부모의 메소드 주소가 저장되어 있으면 상속된거다. 만약 오버라이딩이 되었다면, 부모메소드가 아닌 메소드영역에 새로 생성된 오버라이딩된 메소드의 주소가 저장된다. 자식객체가 부모타입으로 선언되어도 오버라이딩된 메소드를 출력하는 이유도 이것 때문이다. 자식객체의 vtable은 오버리이딩된 메소드만을 가리키기 때문이다. (자동타입변환)

 

 

 

 

 

JVM이 자식클래스 로딩하면, 메소드(b(), c())들을 메소드영역에 할당한다. 그리고 vtable을 생성하는데, 부모 클래스 vtable 안에는 최고 조상인 Object 클래스의 메소드 주소부터 부모 메소드 주소까지 모두 저장되어 있다. 그러므로 부모의 vtable의 메모리 주소를 모조리 읽어와 자식 vtable을 생성한다. 이 후, 자식클래스 타입으로 생성된 객체는 vtable에 접근하여, 원하는 메소드명을 찾아 접근하여 호출한다.

 

 

동적바인딩

 

 

위 과정을 '바인딩(binding)'이라 한다. '바인딩'이란 코드와 메모리를 연결시키는 작업을 말한다.

 

C언어의 경우를 먼저 살펴보자.

 

int sum(int x, int y){

return x + y;

}

 

프로그램 실행되기 전, sum() 코드와 메모리를 미리 '바인딩'해놓는다. 프로그램이 실행되어 함수를 호출하면 바인딩된 주소를 따라 메모리에 바로 접근할 수 있다. 이런 방식을 두고 우리는 정적바인딩이라 부른다.

 

하지만 Java는 위에서 살펴본 바처럼, 프로그램이 실행된 후 메모리와 바인딩을 시작한다.

 

 

Car car = new Car();

car.run();

 

 

프로그램이 실행 된 후, 객체가 선언되면, 그제서야 객체의 메소드가 메모리로 로딩이 된다. 그 후, car.run() 코드와 로딩된 run 메소드의 메모리를 '바인딩'해야 한다. 이 과정은 위에서 살펴보았다.

 

car 참조 변수로 Heap 영역에 생성된 객체로 접근한 후, 객체에 저장된 vtable 주소를 따라 vtable에 접근한다. vtable에서 run()과 일치하는 메소드를 탐색한다. run()을 찾으면 run() 의 메모리 주소를 따라 메모리에 접근한다. 이런 방식으로 car.run(); 코드와 실제 run()메모리가 연결되었다.

 

이렇게 프로그램이 실행 된 후, 코드와 메모리가 바인딩되는 것을 두고 우리는 동적바인딩이라 부른다. 자바는 거의 모든 메소드가 동적바인딩을 한다.

 

 


정리

 

1. 상속이 이루어지면, vtable에 조상클래스들의 메소드 주소가 저장된다.

2. 프로그램이 실행 된 후 이루어지는 바인딩을 동적바인딩이라 부른다.

 

 

 

 

 

 

 

 

 

반응형