Computer Science/Java & Spring

[Java] 자바 기본 개념

kyung.Kh 2025. 6. 4. 01:36

JVM, JDK, JRE

JVM(Java Virtual Machine: 자바 가상 머신)
자바 애플리케이션을 실행하기 위해 이식 가능한 런타임 환경을 제공하는 소프트웨어 입니다.
JVM의 주요 목적은 자바 프로그램이 어떤 운영체제나 기기에서도 동일하게 실행할 수 있도록 지원하는 것과 프로그램의 메모리를 관리하고 최적화하는 역할을 수행합니다. 또한, JVM은 OS와 Java 프로그램 사이에서 중재자 역할을 하며, 특정 OS에 종속되지 않고 애플리케이션이 독립적으로 동작할 수 있게 해줍니다.

 

JRE(Java Runtime Envirnment: 자바 런타임 환경)
자바 프로그램을 실행하기 위한 환경으로 JVM과 자바 프로그램을 실행하는 데 필요한 라이브러리 파일이 포함되어 있어, 개발이 아닌 실행만 할 때 사용됩니다.

 

JDK(Java Development Kit: 자바 개발 키트)
자바 프로그램을 개발하고 실행할 수 있는 모든 도구를 제공하는 개발 키트입니다. JRE의 기능은 물론, 추가로 컴파일러(javac), 디버거, 문서 생성기 같은 개발에 필요한 도구들이 포함되어 있습니다.

 

■ Java가 OS에 독립적일 수 있는 이유는 무엇인가요?

자바가 운영체제에 독립적일 수 있는 가장 큰 이유는 JVM 덕분입니다.

자바 컴파일러는 자바 소스 코드를 기계어로 직접 번역하는 것이 아니라 바이트 코드(.class 파일)로 변환합니다. 이 바이트 코드는 특정 운영체제나 하드웨어에 종속되지 않은 중간 형태의 코드입니다.

따라서 어떤 운영체제든 해당 플랫폼에 맞는 JVM만 설치되어 있다면, 같은 바이트 코드를 해석하고 실행할 수 있습니다. 이 덕분에 자바는 “Write Once, Run Anywhere”라는 특징을 가질 수 있습니다.

 

자바 컴파일 과정

  1. 소스 작성: 개발자는 .java 확장자를 가진 자바 소스 파일을 작성하며, 이 소스 파일은 사람이 읽을 수 있는 고수준 언어로 되어 있습니다.
  2. 컴파일: 작성한 소스 파일을 자바 컴파일러(javac)를 이용해 컴파일하면 .class 확장자를 가진 바이트 코드 파일이 생성됩니다. 이 바이트 코드는 특정 운영체제에 종속되지 않은 중간 형태의 코드로, JVM만 설치되어 있다면 어떤 플랫폼에서도 실행될 수 있도록 설계되어 있습니다.
  3. 클래스 로딩: 프로그램이 실행될 때, JVM 내부의 클래스 로더가 필요한 클래스 파일들을 메모리로 불러옵니다. 이 과정은 로드(Load), 검증(Verify), 준비(Prepare), 분석(Resolve), 초기화(Initialize)라는 다섯 가지 세부 단계로 이루어져, 프로그램의 안전성과 일관성을 보장합니다.
  4. 실행 엔진(Execution Engine) 실행: 메모리에 올라온 바이트 코드를 JVM의 실행 엔진이 가져와 해석하고 실행합니다. 실행 엔진은 인터프리터 방식과 JIT 컴파일러 방식으로 바이트 코드를 처리합니다.
    • 인터프리터 방식: 방식은 명령어를 한 줄씩 읽고 즉시 실행하는 방식으로 초기 실행 속도는 빠르지만 전체 실행은 느릴 수 있습니다.
    • JIT(Just-In Time) 컴파일러 방식: 자주 사용되는 코드 블록을 바이너리 코드로 변환해두고, 이후부터는 빠르게 실행하는 것으로, 장기 실행 프로그램에서는 성능이 점점 향상됩니다.

Java Runtime Data Area

  • PC Register: 각 스레드마다 존재하며, 현재 어떤 명령어를 실행해야 하는지를 기록하는 역할을 합니다. → JVM 명령의 주소를 저장하는 공간
  • JVM Stack: 메서드 호출 시마다 생성되는 프레임을 저장하는 영역입니다. 지역 변수, 매개 변수, 메서드 정보, 임시 데이터 등이 저장되며, 스레드마다 별도로 생성되어 관리됩니다.
  • Native Method Stack: 자바가 아닌 다른 언어(기계어)로 작성된 네이티브 코드를 실행할 때 사용하는 메모리 영역입니다.
  • Heap: 런타임 시, 동적으로 생성되는 객체와 배열이 저장되는 공간입니다. 모든 스레드가 공유하는 영역이며, 할당된 객체는 Garbage Collector에 의해 관리됩니다. JVM의 성능과 직접적으로 연결되기 때문에 Heap 메모리는 성능 이슈에서 가장 많이 언급됩니다.
  • Method Area: 클래스와 인터페이스에 대한 런타임 상수 풀, 정적 변수, 메서드 바이트 코드 등을 저장하는 공간입니다. 이 또한 모든 스레드가 공유하는 영역이며, JVM 시작 시 생성됩니다. 

Garbage Collection (GC: 가비지 컬렉션)

자바에서는 프로그래머가 직접 메모리를 관리할 필요 없이, JVM이 메모리를 자동으로 관리해 주는데, 이를 가능하게 해주는 기능을 가비지 컬렉션 이라고 합니다.

가비지 컬렉션은 프로그램 실행 중 더 이상 참조되지 않는 객체를 찾아내고, 이를 메모리에서 제거하여 사용 가능한 힙 메모리를 확보하는 역할을 합니다.

실행 순서는 세 단계로 이뤄지며, 먼저, 참조되지 않은 객체들을 탐색하고, 이어서 탐색된 객체를 삭제한 뒤, 삭제된 객체가 차지하던 메모리를 반환하여 다시 사용할 수 있도록 합니다.

이러한 과정을 통해 메모리 누수를 방지하고, 자바 프로그램이 안정적으로 동작할 수 있게 하며, 개발자는 비즈니스 로직에 집중할 수 있고, JVM은 백그라운드에서 메모리 관리를 책임지는 구조를 제공합니다.

Primitive Type & Reference Type

  • Primitive Type (기본형 타입)
    • boolean, byte, short, int, long, float, double, char 총 8가지의 기본형 타입을 제공
    • 가장 단순하고 핵심적인 데이터 타입으로, 값 전체를 직접 저장하는 비객체 타입
    • null을 가질 수 없고, 사용 전에 반드시 명시적으로 선언해야 하며, Stack 메모리에 저장되어 빠른 접근이 가능
  • Reference Type (참조 타입)
    • Class, Interface, Array, Enum 등이 포함되며, Primitive Type을 제외한 나머지 모든 타입을 Java에서 Reference Type으로 분류
    • 값 자체가 아니라 객체의 메모리 주소를 참조하는 구조로, 실제 객체는 Heap 메모리에 저장됨

Call by value & Call by reference

  • Call by value (값에 의한 호출)
    • 함수 호출 시, 변수의 값을 복사해서 함수에 전달하는 방식
    • 함수 안에는 복사된 값의 지역적으로 사용되기 때문에, 함수 내부에서 인자 값을 변경해도 원본 변수에는 영향을 주지 않음
  • Call by referenct (참조에 의한 호출)
    • 변수 자체가 아닌 변수의 주소(reference)를 전달하는 방식
    • 함수 내부에서 이 주소를 참조해 직접 원본 데이터를 수정할 수 있음

Casting(UpCasting & DownCasting)

캐스팅(Casting): 변수가 다른 타입으로 변환되거나, 원하는 정보를 다룰 수 있도록 타입을 변환하는 과정

 

자바에서는 변수나 객체가 다른 타입으로 변환될 때, 내부적으로 데이터의 호환 가능 여부를 따지게 됩니다.

캐스팅이 필요한 이유는 크게 두 가지로 다형성을 통해 오버라이딩된 함수를 구분해서 활용할 수 있도록 하고, 상속을 통해 보다 범용적인 프로그래밍을 가능하게 해줍니다.

형변환은 크게 묵시적 형변환과 명시적 형변환으로 구분됩니다.

  • 묵시적 형변환(UpCasting, 자동 형변환: promotion): 상위 타입이 하위 타입의 모든 속성을 포함하기 때문에, 별도의 명시 없이 자동으로 형변환이 일어납니다.
  • 명시적 형변환(DownCasting, 강제 형변환: casting): 상위 타입을 하위 타입으로 변환할 때는, 반드시 캐스팅할 내용을 명시해야 합니다. 단, 다운캐스팅은 업캐스팅이 선행된 경우에만 안전하게 사용할 수 있습니다.

이처럼 캐스팅은 타입 간 변환을 통해 프로그램의 유연성과 확장성을 높여주는 중요한 역할을 합니다.

728x90