brunch
매거진 Java 익힘책

자바의 객체 (3/3)

메모리 구조

by 서준수

객체 생성과 메모리 구조 (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 함수 내에 선언된 로컬 변수이다. 로컬 변수는 스택에 저장된다고 했다. 따라서 다음과 같이 스택에 로컬 변수가 생성된다. 아직 힙에는 아무런 변화가 없다.


stack1.PNG String name = null; int age = 0;


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


Developer javaDeveloper = new Developer();



stack2.PNG Developer javaDeveloper


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


Developer javaDeveloper = new Developer();



stack3.PNG new Developer

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


Developer javaDeveloper = new Developer();



stack4.PNG Developer javaDeveloper = new Developer();


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


javaDeveloper.setName("Tom");

javaDeveloper.setAge(23);



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


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


name = javaDeveloper.getName();

age = javaDeveloper.getAge();


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


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


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


stack7.PNG Developer kotlinDeveloper


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


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


stack8.PNG new Developer


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


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


stack9.PNG new Developer("Jerry", 20)


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


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


stack10.PNG Developer kotlinDeveloper = new Developer("Jerry", 20);


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

keyword
매거진의 이전글자바의 객체 (2/3)