[JVM]변수 선언과 할당시 관점으로 JVM 동작 이해하기
글의 목표
Person kyu = new Person("steadykyu", "950204-xxxxxx","Seoul");
위 코드대로 객체 생성 시, 각각의 데이터들이 Java 메모리의 어느 부분에 저장되는지 이해한다.
Person 클래스 설명
class Person {
String name; // 유저 닉네임이라고 해보자.
PersonInfo personalInfo;
public Person(String name, String socialNumber, String address) {
this.name = name;
personalInfo = new PersonInfo(socialNumber, address);
}
// 회원 가입 메서드
void save(){
// name과 personalInfo 를 이용하여 회원가입 로직 실행했다고 가정
System.out.println("회원가입 완료");
System.out.println("이름 : "+ name);
System.out.println("주민번호 : "+ personalInfo.SocialNumber);
System.out.println("주소 : "+ personalInfo.ADDRESS);
}
public class PersonInfo{
private String name;
// 주민번호
private final String SocialNumber;
private final String ADDRESS;
private PersonInfo(String socialNumber, String address) {
this.SocialNumber = socialNumber;
this.ADDRESS = address;
}
public String getSocialNumber() {
return SocialNumber;
}
public String getAddress() {
return ADDRESS;
}
}
}
public class SignUp {
public static void main(String[] args) {
Person kyu = new Person("steadykyu", "950204-xxxxxx", "Seoul");
kyu.save();
}
}
- Person 클래스는 필드(name - 닉네임), 메서드(save), 내부 클래스(PersonInfo - 개인정보)를 가지고 있다.
- 매개변수 값을 입력받아, “kyu”라는 객체(인간)를 생성하고 있다.
- PersonInfo는 외부에서 접근할수 없도록 코드를 작성해본것인데 글의 주제와는 상관 없으므로 넘어가도 된다.
Java 전체 메모리 영역
- 우리가 작성한 Person 소스 코드는 Person.java로 저장됩니다.
- Java 컴파일러(javac.exe)에 의해 Person.class로 변환됩니다.
- Class Loader를 통해 JVM Runtime Data Area로 로딩합니다.
- Runtime Data Area에 로딩 된 .class들은 Execution Engine을 통해 해석합니다.
- 해석된 바이트 코드는 Runtime Data Area의 각 영역에 배치됩니다.
전체적인 흐름만 이해하고, Runtime Data Area 에서 우리가 필요한 세 영역(Method Area, Heap Area, Stack Area) 만 쪼개서 봐봅시다.
메서드 영역, 스택영역, 힙 영역
이제 부터 아래 소스 코드를 하나하나 쪼개서 메모리에 어떻게 저장되는지 봅시다.
Person kyu = new Person("steadykyu", "950204-xxxxxx","Seoul")
클래스 - (Person)
클래스 ,구체적으로 클래스 코드는 Method 영역(=Class Area, static Area)에 저장됩니다.
그러므로 메서드 코드와 생성자 코드도 Method 영역에 저장됩니다.
- 이 두 코드는 Method 영역에서 저장되고 공유됩니다.
- 그러므로 우리는 객체를 생성할 때 마다 메서드와 생성자를 선언하지 않고, 공유된 코드를 호출해 올 수 있습니다.
또한 정적(static) 필드와 상수도 이 클래스 영역에 저장되어, 클래스를 통해 만들어지는 모든 인스턴스들에게 공유 될 수 있습니다.
참조변수 - (kyu)
kyu는 참조 변수로 생성된 객체의 주소 값을 저장하고 있습니다. 일반적으로 참조형 변수들은 주소값은 stack에 실제 값은 Heap 영역에 저장합니다. 그림에서 확인해보면, 객체와 배열이 Heap 영역에 저장된 모습을 볼 수 있습니다.
참고 : 메서드 호출시 생성되는 지역변수도 이 stack 영역에 저장됩니다.
객체 생성 - new Person(…)
new 명령어는 객체를 생성하고 해당 객체(아래 참고)를 Heap 영역에 넣어줍니다.
- 타입과 상관없이 static이 붙지않은 인스턴스 변수들(필드)
- inner class
Person(…) 는 생성자로, 매개변수의 값을 이용하여 객체를 초기화 해줍니다.
그러므로 생성자로 초기화한 객체를 new 명령어로 Heap 영역에 넣어준 후, kyu 참조변수에 주소값을 부여하고 이 주소값은 stack 영역에 저장 시킵니다.
이제 kyu 참조변수의 주소값(100)을 이용하여 Heap영역의 값을 꺼내 올 수 있게 됩니다.
- ex) kyu.name