brunch

You can make anything
by writing

C.S.Lewis

by 서준수 Mar 21. 2019

자바의 객체 (3/3)

메모리 구조

객체 생성과 메모리 구조 (2/2)


2. 스택(Stack) 메모리와 힙(Heap) 메모리

 스택에는 함수 내에 존재하는 로컬 변수가 저장되고, 힙에는 클래스 내에 존재하는 인스턴스 변수가 저장된다. 실제 객체를 생성할 때 스택과 힙에 어떻게 할당될까? (자바의 메모리 영역이 스택과 힙만 있는 것은 아니지만 객체 생성 시 가장 관련이 있는 것이 두 메모리이다.)


 객체가 생성될 때 메모리에서 어떤 일이 일어나는지 살펴보기 위해 앞서 살펴본 코드를 조금 수정한다.

먼저 Developer 클래스는 다음과 같이 약간 수정하여 먹고, 자고, 코딩하는 함수를 제거하였다.


public class Developer {

    private String name;

    private int age;

    public Developer() {

        System.out.println("[default] Developer Object is created!");

    }

    public Developer(String name, int age) {

        System.out.println("[name : " + name + " age : " + age + "] Developer Object is created!");

        this.name = name;

        this.age = age;

    }

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public int getAge() {

        return age;

    }

    public void setAge(int age) {

        this.age = age;

    }

}



HelloWorld 클래스는 다음과 같이 수정하였다.


public class HelloWorld {

    public static void main(String[] args) {

        String name = null;

        int age = 0;


        Developer javaDeveloper = new Developer();

        javaDeveloper.setName("Tom");

        javaDeveloper.setAge(23);

        name = javaDeveloper.getName();

        age = javaDeveloper.getAge();

        System.out.println("name = " + name+ ", age = " + age);


        Developer kotlinDeveloper = new Developer("Jerry", 20);

        name = kotlinDeveloper.getName();

        age = kotlinDeveloper.getAge();

        System.out.println("name = " + name+ ", age = " + age);

    }

}


[default] Developer Object is created!

name = Tom, age = 23

[name : Jerry age : 20] Developer Object is created!

name = Jerry, age = 20



이제 위 코드가 실행되면서 객체가 생성될 때 실제 스택과 힙에 할당되는 값이 무엇인지 하나씩 살펴보겠다.


        String name = null;

        int age = 0;


 name, age는 main 함수 내에 선언된 로컬 변수이다. 로컬 변수는 스택에 저장된다고 했다. 따라서 다음과 같이 스택에 로컬 변수가 생성된다. 아직 힙에는 아무런 변화가 없다.


String name = null; int age = 0;

 

 다음은 Developer 객체를 생성하는 부분이다. 해당 부분을 조금씩 나눠 살펴보자. 먼저 Developer javaDeveloper 부분이 실행될 때 스택에 로컬 변수 javaDeveloper가 생성된다.


Developer javaDeveloper = new Developer();



Developer javaDeveloper


 다음으로 객체가 실제 생성되는 new Developer()로 인스턴스화가 되면서 실제 힙에 Developer 클래스의 요소들이 생성된다. 이때 생성된 힙 메모리 주소는 0x100번지라고 가정한다. 또한 함수명은 생략하고 함수라고만 표기하였다.


Developer javaDeveloper = new Developer();



new Developer

 객체가 기본 생성자를 통해서 만들어졌기 때문에 추가적인 작업이 없이 마무리되었다. 따라서 최종적으로 아래의 구문이 끝나게 된 것이다. 이때 스택에 있는 javaDeveloper 변수에 객체의 위치 정보인 힙의 주소가 할당된다.


Developer javaDeveloper = new Developer();



Developer javaDeveloper = new Developer();


 setter 함수를 통해서 인스턴스 변수에 값을 할당하면 힙에 해당 값이 할당된다.


javaDeveloper.setName("Tom");

javaDeveloper.setAge(23);



javaDeveloper.setName("Tom"); javaDeveloper.setAge(23);


반대로 getter 함수를 통해서 인스턴스 변수의 값을 로컬 변수에 할당할 수도 있다.


name = javaDeveloper.getName();

age = javaDeveloper.getAge();


name = javaDeveloper.getName(); age = javaDeveloper.getAge();


 코드를 보면 하나의 객체를 더 만드는데 기본 생성자가 아니라 오버로딩한 생성자를 사용했다. 이때도 로컬 변수 생성하는 단계에서는 차이점이 없다.


Developer kotlinDeveloper = new Developer("Jerry", 20);


Developer kotlinDeveloper


 다음으로 객체를 생성하는 과정도 같다.


Developer kotlinDeveloper = new Developer("Jerry", 20);


new Developer


 그리고 오버로딩된 생성자를 사용하면서 나타나는 차이점이 있다. 이 경우는 곧바로 인스턴스 변수를 생성자의 인자 값으로 초기화하기 때문에 인스턴스 변수의 값이 최종적으로 다음과 같이 된다.


Developer kotlinDeveloper = new Developer("Jerry", 20);


new Developer("Jerry", 20)


 최종적으로 해당 구문이 모두 실행되면 kotlinDeveloper에 힙 메모리 주소가 할당된다.


Developer kotlinDeveloper = new Developer("Jerry", 20);


Developer kotlinDeveloper = new Developer("Jerry", 20);


 나머지 getter, setter 함수를 사용하는 부분은 동일하다. 따라서 생략한다.

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari