4장. 자바가 확장한 객체 지향
자바에서 상속을 이용한 확장 시 메모리 구조는 어떻게 사용되며, 확장 키워드들은 무엇이 있는지 알아본다.
왜 프로그램이 실행될 때 바로 클래스들의 정보를 T 메모리의 static 영역에 로딩하지 않고 해당 클래스가 처음 호출될 때 로딩할까?
클래스 정보는 해당 클래스가 코드에서 맨 처음 사용될 때 T 메모리의 스태틱 영역에 로딩되며, 이때 단 한번 해당 클래스의 static 블록이 실행된다.
클래스가 호출되는 경우
클래스의 정적 속성을 사용할 때
클래스의 정적 메서드를 사용할 때
클래스의 인스턴스를 최초로 만들 때
질문으로 다시 돌아와, 왜 클래스를 호출할 때 로딩할까? 그 이유는 JVM 메모리 구조의 static 영역도 메모리이기 때문이다.
메모리는 디스크에 비해 용량이 작기 때문에 최대한 늦게 사용을 시작하고 최대한 빨리 반환하는 것이 정석이다. 물론, 자바에서 static 영역에 올라간 데이터는 프로그램이 종료되기 전 까지 반환할 수 없지만, 그럼에도 최대한 늦게 로딩함으로써 메모리 사용을 늦추기 위해서이다.
멤버 변수만 다른 동일한 타입의 객체를 100개 이상 만들고, 같은 메서드를 실행하면 heap 영역에 100개의 객체 프레임이 생길까?
public class Example {
void test() {
System.out.println("Test");
}
}
class ExampleMain {
public static void main(String[] args) {
Example example = new Example();
example.test();
}
}만약 위와 같은 코드가 있다면 메모리구조는 아래와 같이 형성된다.

여기서 집중해서 봐야 할 관점은 Example 객체가 생성한 example 이 하나가 아닌, Example[100] 과 같이 요소가 100개인 배열이라면 힙 영역에 생기는 객체 프레임은 100개가 되고, test() 메서드도 각 객체에 따라 프레임 내부에 만들어져야한다.
객체 멤버 메서드는 각 객체별로 달라지는 것이 아니며, 새롭게 생성되는 객체 멤버 속성 값만 다를뿐이다.
이렇게 똑같은 객체 멤버 메서드인 test() 메서드를 힙 영역에 100개나 만드는 것은 심각한 메모리 낭비이다. 그래서, JVM 은 지능적으로 객체 멤버 메서드 test() 를 위 그림 처럼 스태틱 영역에 단 하나만 보유한다.
그리고 직접 코드상 눈에 보이지 않지만 test() 메서드를 호출할 때 객체 자신을 나타내는 this 객체 참조 변수를 인자로 넘긴다.

이로써 비효율적으로 메모리를 낭비하지않고 JVM 이 컴파일 당시 바이트 코드를 조작하여 최적화를 하면서 메모리 구조를 효율적으로 사용하게 된다.
Last updated