Java의 데이터 타입의 분류(기본 타입, 참조 타입)와 메모리 영역

Jakezo·2021년 6월 26일
0
post-thumbnail

Java 데이터 타입의 분류

프로그램은 자료구조(데이터)와 알고리즘의 결합으로 이루어집니다. 즉 프로그램이란 자료구조를 통해 데이터를 구성하고 표현하며 알고리즘을 통해 문제를 해결합니다. 데이터 표현의 방법은 프로그램의 많은 영향을 주게 되는데 이는 문제를 해결하는 방법 알고리즘이 데이터의 표현에 따라서 달라지기 때문입니다. 따라서 데이터를 얼마나 잘 다루느냐가 좋은 프로그램을 작성할 수 있는 관건이 됩니다.

데이터를 잘 다루기 위해서는 자버에서 지원하는 데이터 타입에 대해서 제대로 이해할 필요가 있습니다. Java의 데이터 타입에는 크게 기본타입(primitive type)과 참조 타입(reference type)으로 분류됩니다. 여기서 기본 타입은 정수, 실수, 문자, 논리 리터럴을 저장하는 타입을 말합니다. 참조 타입이란 객체의 번지를 참조하는 타입으로 배열, 열거, 클래스, 인터페이스 타입을 말합니다.

기본 타입(Primitive type)

java에서 기본 데이터 타입이란 정수, 실수, 문자, 논리 리터럴을 직접 저장하는 타입을 말한다. 정수 타입에는 byte, char, short, int, long이 있고, 실수 타입에는 float, double이 있다. 그리고 논리 타입에는 boolean이 있다. 아래 표는 기본 데이터 타입의 크기와 저장되는 값의 범위를 보여준다.

메모리에는 0과 1을 저장하는 최소 기억 단위이 비트(bit)가 있습니다 그리고 8개의 비트를 묶어서 바이트(byte)라고 합니다. 기본 타입은 정해진 메모리 사용 크기(바이트 크기)로 값을 저장하는데 바이트 크기가 클 수록 표현하는 값의 범위가 큽니다. 각 타입별 저장되는 갑의 범위는 기억할 필요는 없습니다. 다만 사용되는 메모리 크기는 기억해둬야 합니다. 이 메모리 크기를 알고 있으면 사용되는 값의 범위를 대략 알 수 있기 때문입니다. 정수 타입의 경위 저장 되는 되는 값의 범위는 -2^(n-1) ~ (2^(n-1)-1) 입니다.

변수마다 사용할 수 있는 값의 범위를 왜 기억해야 하냐면 만약에 변수가 사용할 수 있는 값의 범위를 초과하게 되면 오버플로우(overflow)현상이 발생하기 때문입니다. 오버플로우 현상이란 간단히 설명하면 그릇에 담을 수 있는 한계를 초과하여 흘러 넘치는 것을 말합니다. 변수에서 오버플로우 현상이 발생하게 되면 내가 원하지 않은 엉뚱한 값이 변수에 들어가게 됩니다. 아래 그림은 오버플로우를 설명하기 그림과 설명입니다.

참조 타입(Reference type)

java에서 참조 타입(reference type)이란 객체의 번지를 참조하는 타입으로 배열, 열거, 클래스, 인터페이스 타입을 말합니다. 기본 타입과 참조 타입의 차이는 저장되는 값이 무엇인가입니다. 기본 타입으로 선언된 변수는 실제 값을 변수에 저장하지만 참조 타입은 배열, 열거, 클래스, 인터페이스를 이용해서 선언된 변수는 메모리에 번지를 값으로 갖게 됩니다. 즉 번지를 통해 객체를 참조한다는 뜻으로 참조 타입이라고 부릅니다.

또한 기본 데이터 타입과 참조 타입은 데이터가 생성되고 저장되는 위치가 다릅니다. 기본 데이터 타입은 스택 영역에 생성이 되고 참조 데이터 타입은 힙 영역에 생성이 됩니다. 이는 아래 메모리 영역을 설명할 때 자세히 알아보겠습니다.

메모리 사용 영역

java.exe로 프로그램 실행하면 JVM(Java Virtual Machine)이 실행이 됩니다. JVM은 운영체제에서 할당받은 메모리 영역(Runtime Data Area)을 메소드 영역(Method Area), 스레드 영역(Thread Area), 힙 영역(Heap Area)과 같이 세부 영역으로 구분을 해서 사용합니다. 이 때 쓰레드 영역마다 하나의 JVM 스택 영역이 존재하게 됩니다. 아래 그림은 각 영역을 그림으로 표현한 것입니다.

메소드 영역

메소드 영역에는 코드에서 사용되는 클래스들을 클래스 로도로 읽어 클래스 별로 런타임 상수 풀, 필드 / 메소드 데이터, 메소드 코드, 생성자 코드 등을 분류해서 저장합니다. 메소드 영역은 JVM이 시작할 때 생성되고 모든 스레드가 공유하는 영역입니다.

힙 영역

힙 영역은 객체와 배열이 생성되는 영역입니다. 힙 영역에 생성된 객체와 배열은 JVM 스택 영역의 변수나 다른 객체의 필드에서 참조한다. 참조하는 변수나 필드가 없다면 의미 없는 객체가 되기 때문에 이것을 쓰레기로 취급하고 JVM은 Garbage Collector를 실행시켜 스레기 객체를 힙 영역에서 자동으로 제거합니다. 그렇기 때문에 개발자는 객체를 제거하기 위해 별도의 코드를 작성할 필요가 없습니다. 사실 Java는 고드로 객체를 직접 제거시키는 방법을 제공하지 않습니다. 다만 System.gc()라는 메소드가 있지만 이는 직접적으로 쓰레기를 제거한다기 보다는 JVM에게 제거를 요청하는 형태입니다. 이러한 Garbage Collector의 존재가 C언어와의 차이점 중 하나입니다. C언어에서 참조 변수(포인터)를 사용하게되면 직접 쓰레기를 제거해줘야 하기 때문입니다.

JVM(Java Virtual Machine) Stack Area

JVM 스택 영역은 각 스레드마다 하나씩 존재하며 스레드가 시작될 때 할당됩니다. 자바 프로그램에서 추가적으로 스레드를 생성하지 않는다면 main 스레드만 존재하므로 JVM 스택도 하나입니다. 이때 스레드의 개념은 어려운 개념이여서 나중에 따로 작성하여 설명하겠습니다. JVM 스택은 메소드를 호출할 때마다 프레임을 추가하고 메소드가 종료되면 해당 프레임을 제거하는 동작을 수행합니다.

프레임 내부에는 로컬 변수 스택이 있는데 기본 타입 변수와 참조 타입 변수가 추가되거나 제거됩니다. 변수는 선언된 블록 안에서만 스택으로 존재하고 블록을 벗어나면 스텍에서 제거됩니다. 이는 메소드, if문, for문 등에서 내부에서 생성된 변수는 해당 로컬 변수 스택에만 존재하여 해당 구문을 빠져 나오게되면 제거가 되여 외부에서는 사용이 불가능 하다는 것을 말합니다. 다만 배열 같은 경우에는 배열의 변수는 스택 영역에 생성되지만 배열의 데이터 자체는 Heap 영역에 생성되어 제거되지 않습니다. 즉 Java에서 배열은 객체로 취급을 합니다.

profile
탐험가

0개의 댓글