세 가지 종류의 참조 유형이 있다: 클래스 타입, 배열 타입, 그리고 인터페이스 타입.
참조 유형의 값은 동적으로 생성된 클래스 인스턴스, 배열, 또는 인터페이스를 참조한다.
배열 타입은 하나의 차원으로 구성되며, 길이는 타입에 의해 지정되지 않는다.
배열 타입의 구성 요소 타입은 자체적으로 배열 타입일 수 있다.
배열 타입에서 시작하여 해당 타입의 구성 요소 타입을 고려하고, 그 타입이 또 다시 배열 타입이면, 이 과정을 반복하다가 마지막으로 배열 타입이 아닌 구성 요소 타입에 도달해야 한다. 이것을 배열 타입의 요소 타입(element type)이라고 한다.
배열 타입의 요소 타입은 반드시 기본 타입(primitive type), 클래스 타입, 또는 인터페이스 타입 중 하나여야 한다.
참조의 기본값은 null이다. null값은 어느 타입으로든 cast될 수 있다.
그리고 null에 대한 구체적인 인코딩 값을 강제하지 않는다.
JVM은 프로그램 실행 중에 사용되는 여러 런타임 데이터 영역을 정의하고 있다.
데이터 영역 중 일부는 JVM이 시작될 때 생성되며, JVM이 종료될 때까지 파괴되지 않는다.
일부 데이터 영역은 각 쓰레드별로 존재한다.
쓰레드별 데이터 영역은 쓰레드가 생성될 때 만들어지고, 쓰레드가 종료될 때 파괴된다.
JVM 시작 시 생성되는 데이터 영역과 쓰레드 시작 시 생성되는 데이터 영역은 서로 다른 생명 주기를 가진다.
전자는 JVM의 시작과 종료에 연결되어 있고, 후자는 각 쓰레드의 시작과 종료에 연결되어 있다.
JVM은 동시에 여러 실행 스레드를 지원할 수 있다.
각 JVM 스레드는 자체 프로그램 카운터(pc) 레지스터를 가지고 있다.
각 JVM 스레드는 현재 실행 중인 메서드의 코드를 가리키는 프로그램 카운터(pc) 레지스터를 가지고 있다.
각 스레드는 현재 스레드에 대한 현재 메서드를 가리키는 프로그램 카운터를 유지한다.
현재 실행 중인 메서드가 자바 메서드(네이티브 메서드가 아닌 경우)인 경우, pc 레지스터는 현재 실행 중인 Java Virtual Machine 명령의 주소를 포함한다.
현재 실행 중인 메서드가 네이티브 메서드인 경우, Java Virtual Machine의 pc 레지스터 값은 정의되지 않는다.
참고
네이티브 메서드는 자바 언어로 작성된 코드가 아닌, 네이티브 언어(C, C++, 어셈블리 등)로 작성된 코드를 자바 어플리케이션에서 호출하거나 사용할 수 있도록 제공되는 메서드이다.
Java Virtual Machine의 pc 레지스터는 특정 플랫폼에서 returnAddress나 네이티브 포인터를 저장할 수 있을 정도로 크다.
각각의 jvm thread는 자체적인 스택을 가진다. 이 스택은 thread가 생성될 때 같이 생성된다. 스택들은 frame들을 저장한다. frame은 매서드와 호출에 대한 정보를 가지고 있다.
jvm의 스택은 c와 유사하게 로컬 변수와 partial result들을 저장하고 매서드의 호출 및 반환에 역할을 한다.
jvm 스택은 프레임을 직접 조작하지 않고 프레임을 push, pop한다. 따라서 프레임은 힙에 할당될 수 있다.
스택 크기의 유연성:
JVM 스택은 고정 크기일 수도 있고, 필요에 따라 동적으로 확장 및 축소될 수도 있다.
고정 크기의 JVM 스택인 경우, 각 JVM 스택의 크기는 해당 스택이 생성될 때 독립적으로 선택될 수 있다.
사용자 제어 가능성:
JVM 구현은 프로그래머나 사용자에게 JVM 스택의 초기 크기뿐만 아니라 동적으로 확장 또는 축소되는 JVM 스택의 최대 및 최소 크기에 대한 제어를 제공할 수 있다.
예외 조건:
JVM 스택과 관련된 예외 상황이 있다.
만약 스레드의 계산이 허용된 JVM 스택 크기보다 큰 스택을 필요로 한다면, JVM은 StackOverflowError를 발생시킨다.
만약 JVM 스택이 동적으로 확장 가능하며, 확장을 시도했지만 충분한 메모리를 사용할 수 없거나 새로운 스레드의 초기 JVM 스택을 생성하는 데 충분한 메모리를 사용할 수 없다면, JVM은 OutOfMemoryError를 발생시킨다.
공유되는 JVM 힙:
JVM은 모든 JVM 스레드 간에 공유되는 힙을 가지고 있다.
힙은 모든 클래스 인스턴스와 배열에 할당되는 메모리의 실행 시 데이터 영역이다.
힙의 생성과 관리:
힙은 JVM이 시작될 때 생성된다.
객체를 위한 힙 저장 공간은 자동 저장 관리 시스템 (garbage collector)에 의해 회수된다. 객체는 명시적으로 해제되지 않는다.
자동 저장 관리 시스템의 유형:
JVM은 특정 유형의 자동 저장 관리 시스템을 가정하지 않으며, 구현자의 시스템 요구에 따라 저장 관리 기술을 선택할 수 있다.
힙의 크기 관리:
힙은 고정 크기일 수 있고, 계산에 따라 필요에 따라 확장되거나 불필요한 큰 힙이 생길 경우 축소될 수 있다.
힙의 메모리는 연속적일 필요가 없다.
만약 요구되는 힙 메모리가 자동 저장 관리 시스템으로 사용 가능한 양보다 많다면, Java Virtual Machine은 OutOfMemoryError를 발생시킨다. 이 에러는 힙 메모리 부족으로 인해 더 이상 할당할 수 없을 때 발생하는 예외를 나타낸다.
jvm은 모든 스레드간 공유되는 method area를 가지고 있다.
메소드 영역은 실행 시 상수 풀, 필드 및 메서드 데이터, 메서드 및 생성자의 코드 등과 같은 각 클래스에 대한 구조를 저장한다.
메소드 영역은 jvm 실행시 생성되며, 논리적으로 힙의 일부이지만 간단한 구현에서는 가비지 수집이나 압축을 수행하지 않을 수 있다.
클래스 파일의 상수 풀 테이블에 대한 실행 시간 표현으로, 컴파일 시간에 알려진 숫자 리터럴부터 실행 시간에 해결해야 하는 메소드 및 필드 참조까지 여러 종류의 상수를 포함하고 있다.
각 실행 시간 상수 풀은 자바 가상 머신의 method area에서 할당된다. 클래스 또는 인터페이스가 생성될 때 자바 가상 머신에 의해 생성된다. 클래스 또는 인터페이스의 실행 시간 상수 풀 구성과 관련된 다음의 예외적인 상황이 있다:
클래스 또는 인터페이스를 생성하는 동안, 실행 시간 상수 풀의 구성에 필요한 메모리가 자바 가상 머신의 메소드 영역에서 사용 가능한 메모리보다 많으면 자바 가상 머신이 OutOfMemoryError를 throw한다.
자바 가상 머신은 네이티브 메소드 스택을 지원하기 위해 전통적인 스택 또는 "C 스택"을 사용할 수 있다. 이는 네이티브 메소드나 자바 가상 머신 명령어 집합을 해석하는 인터프리터에 활용됩니다. 네이티브 메소드 스택은 스레드당 할당되며 크기는 고정 또는 동적으로 조절될 수 있다. 프로그래머나 사용자는 초기 크기 및 최대/최소 크기를 제어할 수 있다. 다만, 크기 제한을 초과하면 StackOverflowError가 발생하며, 동적 확장 시 메모리 부족이나 초기 스택 생성 실패 시 OutOfMemoryError가 발생한다.