Programming/Java

[Java] Java, JVM 개념 정리

owls 2023. 4. 27. 12:38
728x90

Java

Java란?

Sun Microsystems에서 개발하여 1996년 1월에 공식적으로 발표한 객체지향 프로그래밍 언어입니다.

자바는 운영체제에 독립적이라는 특징이 있어 운영체제의 종류에 관계없이 실행이 가능합니다. 

이는 JDK(Java Development Kit)라는 개발 도구가 있기에 가능합니다.

 

특징

1. 운영체제에 독립적

자바가 운영체제에 독립적으로 사용할 수 있는 이유는 일종의 애뮬레이터인 JVM(Java Virtual Machine)을 통해서 가능합니다. 자바 응용 프로그램은 운영체제나 하드웨어가 아닌 JVM하고만 통신하고 JVM이 자바 응용프로그램으로부터 전달받은 명령을 해당 운영체제가 이해할 수 있도록 변환하여 전달합니다.

자바로 작성된 프로그램은 운영체제에 독립적이지만 JVM은 운영체제에 종속적이어서 Sun에서는 여러 운영체제에서 설치할 수 있는 JVM을 제공합니다.

 

자바 소스는 컴파일 후 바이트코드가 생성되며 JVM은 바이트코드를 해석해 운영체제에서 실행할 수 있도록 변역해 주는 역할을 담당합니다.

2. 객체지향언어

객체지향개념의 특징인 상속, 캡슐화, 다형성이 잘 적용된 객체지향언어입니다.

숫자(int, float, long 등), 논리 값(true, false)를 제외한 모든 것이 객체로 구성되어 있습니다. 자바는 Object클래스에서 모든 클래스를 파생합니다.

(int, float, long, true, false등을 원시 자료형(Primitive type)이라고 합니다.)

 

3. 자동 메모리 관리(Garbage Collection)

자바로 작성된 프로그램이 실행되면, Garbage Collector가 자동으로 메모리를 관리해주기 때문에 프로그래머가 메모리를 따로 관리하지 않아도 됩니다.

이는 포인터 연산을 지원하지 않기 때문에 잘못된 주소를 가르킬 가능성이 없습니다. 모든 메모리 접근을 자바 시스템이 관리하고 제한하며 예외 핸들링을 하여 시스템 붕괴의 우려가 없습니다. 

 

4. 네트워크와 분산처리 지원

다양한 네트워크 프로그래밍 라이브러리(JAVA API)를 통해 비교적 짧은 시간에 네트워크 관련 프로그램을 개발할 수 있도록 지원합니다.

 

5. 멀티쓰레드 지원

자바에서 개발되는 멀티쓰레드 프로그램은 시스템과는 관계없이 구현이 가능하고, 관련된 JAVA API 라이브러리가 제공되어 구현이 쉽습니다. 여러 쓰레드에 대한 스케줄링을 자바 인터프리터가 담당하게 됩니다.

 

6. 동적 로딩(Dynamic Loading) 지원

자바로 작성된 애플리케이션은 여러 개의 클래스로 구성되어 있습니다. 자바는 동적 로딩을 지원하기 때문에 실행 시에 모든 클래스가 로딩되지 않고 필요한 시점에 클래스를 로딩하여 사용할 수 있다는 장점이 있습니다. 그 외에도 일부 클래스가 변경되어도 전체 애플리케이션을 다시 컴파일하지 않아도 되며, 애플리케이션의 변경사항이 발생해도 비교적 적은 작업만으로 처리할 수 있는 유연하게 애플리케이션을 작성할 수 있습니다.

 

 

Java의 핵심 기술 패키지

JVM

Java Virtual Machine으로, 자바 프로그램을 실행하는 자바 플랫폼 구성요소입니다.

자바로 작성된 애플리케이션은 모두 JVM에서만 실행되기 때문에, 자바 애플리케이션이 실행되기 위해서는 반드시 JVM이 필요합니다. 

 

Java 애플리케이션은 OS사이에 JVM이 있어, JVM을 한 번 더 거치게 됩니다. 하드웨어에 맞게 컴파일된 상태가 아닌 실행 시에 해석(interpret)되기 때문에 속도가 느리다는 단점을 가지고 있습니다. 하지만 바이트코드(컴파일된 자바코드)를 하드웨어의 기계어로 바로 변환해주는 JIT컴파일러와 향상된 최적화 기술이 적용되어 속도의 격차가 줄어졌습니다.

 

Java 애플리케이션은 JVM하고만 상호작용하기 때문에 OS와 하드웨어에 독립적이라는 특징이 있지만, JVM은 OS에 종속적이기 때문에 OS에 맞는 JVM을 설치해야합니다.

 

JRE

Java Runtime Environment로, 자바로 만들어진 프로그램을 실행시키는데 필요한 라이브러리들과 각종 API, JVM이 포함되어 있습니다. 

JVM을 생성하는 디스크 상의 부분입니다.

JDK는 자바 기반 소프트웨어를 개발하기 위한 도구들로 이루어진 패키지인 반면, JRE는 자바 코드를 실행하기 위한 도구들로 구성된 패키지입니다. JRE는 자바로 개발(쓰기)은 안되고 실행(읽기)만 된다고 이해하면 됩니다.

 

JDK

Java Development Kit로, 자바 애플리케이션을 구축하기 위한 핵심 플랫폼으로 자바를 개발하는데 필요한 프로그램들이 있습니다.

개발자들이 JVM과 JRE에 의해 실행되고 구동될 수 있는 자바 프로그램을 생성할 수 있게 해줍니다.

즉, 자바 기반 소프트웨어를 개발하기 위한 도구들로 이루어진 패키지입니다.

개발을 하려면 실행도 시켜줘야 하기 때문에 JRE도 함께 포함되어 있습니다.

 

 

JDK의 bin디렉토리에 있는 주요 실행파일은 다음과 같습니다.

javac.exe 자바 컴파일러, 자바소스 코드를 바이트코드로 컴파일한다.
java.exe 자바 인터프리터, 컴파일러가 생성한 바이트코드를 해석하고 실행한다.
javap.exe 역어셈플러, 컴파일된 클래스 파일을 원래의 소스로 변환한다.
( .class파일이 역컴파일되어 .java파일에 저장됩니다. 소스전체가 아닌 선언부만 저장함)
javadoc.exe 자동문서 생성기, 소스파일에 있는 주석을 이용하여 java api문서와 같은 형식의 문서를 자동으로 생성한다.
jar.exe 압축프로그램, 클래스파일과 프로그램의 실행에 관련된 파일을 하나의 jar로 압축하거나 압축해제한다.

 

JVM

JVM 동작 방식

사진 출처 :https://coding-factory.tistory.com/828

1. 자바 프로그램을 실행하면 JVM은 OS로 부터 메모리를 할당합니다.

2. 자바 컴파일러(Javac)가 자바 소스 코드(.java)를 자바 바이트 코드(.class)로 컴파일합니다.

3. Class Loader를 통해 JVM Runtime Data Area로 로딩합니다.

4. Runtime Data Area에 로딩 된 .class들은 Execution Engine을 통해 해석합니다.

5. 해석된 바이트 코드는 Runtime Data Area의 각 영역에 배치되어 수행하며 이 과정에서 Execution Engine에 의해 GC의 작동과 스레드 동기화가 이루어집니다.

 

JVM 구조

Class Loader

사진 출처 : https://coding-factory.tistory.com/828

자바는 동적으로 클래스를 읽어옵니다. 프로그램이 실행 중인 런타임에서 모든 코드가 자바 가상 머신과 연결됩니다. 이렇게 동적으로 클래스를 로딩해주는 역할이 "클래스 로더"입니다. 

자바에서 소스를 작성하면 .java파일이 생성되고, .java소스를 컴파일러가 컴파일하면 .class파일이 생성되는데 클래스 로더는 .class파일을 묶어서 JVM이 운영체제로부터 할당받은 메모리 영역이 Runtime Data Area로 적재합니다.

 

Execution Engine

클래스 로더에 의해 JVM으로 로드된 .class파일(바이트 코드)들은 Runtime Data Area의 Method Area에 배치되는데, 배치된 이후에 JVM은 Method Area의 바이트 코드를 실행 엔진에 제공하여, 정의된 내용대로 바이트 코드를 실행시킵니다.

이때, 로드된 바이트 코드를 실행하는 런타임 모듈이 실행 엔진입니다. 실행 엔진은 바이트 코드를 명령어 단위로 읽어서 실행합니다.

 

Garbage Collector

자바 가상 머신은 가비지 컬렉터를 이용하여 사용하지 않는 메모리를 자동으로 회수해줍니다. 개발자가 따로 메모리 관리를 하지 않아도록 자동으로 관리해줍니다. Heap 메모리 영역에 생성(적재)된 객체들 중 참조되지 않은 객체들을 탐색 후 제거하는 역할을 하며 해당 역할을 하는 시간은 정확이 언제인지는 알 수 없습니다. GC역할을 수행하는 스레드를 제외한 나머지 모든 스레드들은 일시정지 상태가 됩니다.

 

Runtime Data Area

사진 출처 : https://coding-factory.tistory.com/828

런타임 데이터 영역은 JVM의 메모리 영역으로 자바 애플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역입니다.

 

●모든 스레드가 공유해서 사용(GC의 대상)

- Heap Area

- Method Area

 

●Thread마다 하나씩 생성

- Stack Area

- PC Register

- Native Method Stack


- Heap Area

new 키워드로 생성된 객체와 배열이 생성되는 영역입니다. (전역 변수)

주기적으로 GC가 제거하는 영역입니다.

 

- Method Area

클래스 멤버 변수의 이름, 데이터 타입, 접근 제어자 정보와 같은 각종 필드 정보들과 메서드 정보, Constant Pool, static변수, Final class 등이 생성되는 영역입니다.

 

- Stack Area

지역변수, 파라미터, 리턴 값, 지역 변수가 생성되는 영역입니다. 

 

- PC Register

Thread가 생성될 때마다 생성되는 영역으로 프로그램 카운터입니다.

현재 스레드가 실행되는 부분의 주소와 명령을 저장하고 있는 영역입니다.

 

- Native Method Stack

자바 이외의 언어(C, C++, 어셈블리 등)로 작성된 네이티브 코드를 실행할 때 사용되는 메모리 영역으로 일반적인 C 스택을 사용합니다.

보통 C/C++등의 코드를 수행하기 위한 스택을 말하며(JNI) 자바 컴파일러에 의해 변환된 자바 바이트 코드를 읽고 해석하는 역할을 하는 것이 자바 인터프리터(Interpreter)입니다.

 

 

 

참고 자료 

https://coding-factory.tistory.com/828

https://dinfree.com/lecture/language/112_java_1.html#m2

https://wikidocs.net/199

 

728x90