자바의 데이터 타입은 크게 기본 타입과 참조 타입으로 분류된다.
기본 타입으로 선언한 변수는 실제 값을 변수 안에 저장한다.
int a = 20;
boolean flag = false;
참조 타입으로 선언된 변수는 메모리의 주소를 값으로 갖는다.
주소를 통해 객체를 참조하므로 참조 타입으로 불리는 것이다.
// str의 값은 객체의 주소 이다.
String str = "This is Reference Type";
자바에서 참조타입은 배열, 열거, 문자열, 클래스, 인터페이스 등이 있다.
아래의 코드에서 s1과 s2는 name이 "Jane"이고 age가 16인 Student 객체이고 서로 값이 같아서 s1과 s2는 같은 값으로 보이지만, 서로 참조하고 있는 객체(힙 영역에 생성된 객체)가 다르므로 주소가 다르다. s1 == s2를 했을때 false가 나온다.
Student s1 = new Student("Jane",16);
Student s2 = new Student("Jane",16);
System.out.println(s1 == s2); // false
String은 문자열 리터럴이 동일하면 String 객체를 공유하도록 되어있어서 아래와 같은 경우는 s1 == s2는 true이다.
String s1 = "Hello, World!";
String s2 = "Hello, World!";
System.out.println(s1 == s2); // true
객체 생성 연산자new
를 사용하여 힙 영역에 String 객체를 생성했을 경우에는 s1과 s2는 서로 다른 String 객체를 참조한다.
String s1 = new String("Hello, World!");
String s2 = new String("Hello, World!");
System.out.println(s1 == s2); // false
따라서 문자열만을 비교할 때에는 equals()메소드를 사용한다.
String s1 = "Hello, World!";
String s2 = "Hello, World!";
String s3 = new String("Hello, World!");
System.out.println(s2 == s3); // false
System.out.println(s2.equals(s3)); // true
// 비교하면 같음
int number1 = 10;
int number2 = 10;
// 비교하면 같지 않음. 이유는 참조 타입이기 때문에 (참조 타입은 만들어 질 때 힙 영역에 값이 만들어지고 그 값을 참조하게 되기 때문)
int[] arr1 = {1,2,3};
int[] arr2 = {1,2,3};
// 비교하면 같음. String 은 참조 타입인데도 같음. 이유는 문자가 같으면 서로 공유하게 되어있기 때문
String text1 = "abc";
String text2 = "abc";
// 하지만 new 키워드를 통해 만든다면 같지 않음.
String text3 = new String("abc");
String text4 = new String("abc");
// 이렇게 서로 섞어서 비교해도 같지 않음
String text5 = new String("abc");
String text6 = "abc";
// 하지만 비교를 올바르게 할 수 있는 방법이 있음 (String만) -> equals 라는 메소드를 사용해야 함.
System.out.println(text5.equals(text6));
java.exe
로 JVM이 시작되면 JVM은 운영체제에서 할당받은 메모리 영역(Runtime Data Area) 을 아래와 같이 세부 영역으로 구분해서 사용한다.
메소드 영역에서는 코드에서 사용되는 클래스들을 클래스 로더로 읽어 클래스별로 런타임 상수풀(runtime constant pool), 필드(field) 데이터, 메소드(method) 데이터(메소드 이름,리턴 타입, 파라미터, 접근 제어자), 메소드 코드, 생성자(constructor), static 변수, final class 변수 등이 생성되는 영역이고 모든 스레드가 공유하는 영역이다.
힙 영역은 객체와 배열이 생성되는 영역이다. 힙 영역에 생성된 객체와 배열은 JVM 스택 영역의 변수나 다른 객체의 필드에서 참조한다. 만약 참조하는 변수나 필드가 없다면 JVM은 쓰레기 수집기(Garbage Collector)를 실행시켜 힙 영역에서 자동으로 제거한다.
지역 변수, 파라미터, 리턴 값, 연산에 사용되는 임시 값등이 생성되는 영역이다. 메소드를 호출할때마다 스택 영역이 생성된다. 기본 타입 변수와 참조 타입 변수가 push 되거나 pop 된다. 변수는 선언된 블록 안에서만 스택에 존재하고 블록을 벗어나면 스택에서 사라진다.
아래와 같은 코드에서 if문을 빠져나가면 c는 사라지고, 객체 Person은 힙 영역에 생성되며, 스택 영역에서 p1은 힙 영역에서 생성된 객체의 주소 값을 가진다.
int a = 1;
boolean b = true;
if(b) {
char c = 'B';
}
Person p1 = new Person();
스레드가 생성될때마다 생성되는 영역으로 현재 스레드가 실행되고 있는 부분의 주소와 명령을 저장하고 있는 영역이다.
자바 외 언어로 작성된 네이티브 코드를 위한 메모리 영역이다.
게시글 참고하며 혼자 보려고 정리한 글 입니다.