코딩쿠의 코드 연대기

JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가. 본문

코딩스터디/JAVA스터디

JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가.

코딩쿠 2024. 10. 10. 21:57

학습목표, 과제

  • JVM이란 무엇인가
  • 컴파일 하는 방법
  • 실행하는 방법
  • 바이트코드란 무엇인가
  • JIT 컴파일러란 무엇이며 어떻게 동작하는지
  • JVM 구성 요소
  • JDK와 JRE의 차이

JVM이란 무엇인가?

 

출처 : [Java] JVM과 자바 코드 실행 방법 이해하기 (velog.io)

 

JVM(Java Virtual Machine)은 java의 중간 코드를 실행할 수 있는 주체로, OS에 종속되지 않고 .java 코들를 실행할 수 있게 하는 '가상 컴퓨터' 이다.

Java 소스코드, 즉 원시코드(*.java)는 CPU가 인식을 하지 못하므로 기계어로 컴파일을 해줘야한다.
하지만 Java는 이 JVM 이라는 가상머신을 거쳐서 OS에 도달하기 때문에 OS가 인식할 수 있는 기계어로 바로 컴파일 되는게 아니라 JVM이 인식할 수 있는 Java bytecode(*.class)로 변환된다.

 

출처

  1. 따즈아 > 김지은 JAVA 입문
  2. 나무위키 : JVM
  3. [Java] JVM과 자바 코드 실행 방법 이해하기 (velog.io)

컴파일 하는 방법, 실행하는 방법

1. 터미널 또는 명령 프롬프트 열기

Windows에서는 명령 프롬프트, macOS 또는 Linux에서는 터미널을 엽니다.

2. Java 코드 파일이 있는 디렉토리로 이동

cd 명령어를 사용하여 Java 코드 파일이 있는 디렉토리로 이동합니다. 예를 들어, HelloWorld.java 파일이 C:\Users\YourName\Documents\Java 디렉토리에 있다면 다음 명령어를 입력합니다.

 

Bash

cd C:\Users\YourName\Documents\Java

3. javac 명령어를 사용하여 컴파일

다음 명령어를 입력하여 Java 코드를 컴파일합니다.

 

Bash

javac HelloWorld.java

HelloWorld.java는 컴파일하려는 Java 코드 파일의 이름입니다. 컴파일이 성공하면 .class 확장자를 가진 파일(예: HelloWorld.class)이 생성됩니다. 이 파일에는 Java 가상 머신(JVM)에서 실행할 수 있는 바이트 코드가 포함되어 있습니다.

추가 정보

  • 여러 파일 컴파일: 여러 개의 Java 파일을 컴파일하려면 파일 이름을 공백으로 구분하여 나열합니다. 예: javac 파일1.java 파일2.java 파일3.java
  • 특정 디렉토리에 클래스 파일 저장: -d 옵션을 사용하여 컴파일된 클래스 파일을 특정 디렉토리에 저장할 수 있습니다. 예: javac -d classes HelloWorld.java (classes 디렉토리에 HelloWorld.class 파일이 저장됨)
  • 클래스패스 지정: 외부 라이브러리를 사용하는 경우 -cp 옵션을 사용하여 클래스패스를 지정해야 합니다. 예: javac -cp ".;lib/*" HelloWorld.java (현재 디렉토리와 lib 디렉토리 아래의 모든 JAR 파일을 클래스패스에 추가)

컴파일 오류 해결

컴파일 중 오류가 발생하면 오류 메시지를 주의 깊게 읽고 코드에서 오류를 수정해야 합니다. 일반적인 컴파일 오류는 다음과 같습니다.

  • 구문 오류: 코드에 잘못된 구문이 있는 경우 발생합니다. 예를 들어, 세미콜론(;)을 잊어버리거나 중괄호({})를 닫지 않은 경우입니다.
  • 타입 오류: 변수에 잘못된 유형의 값을 할당하려는 경우 발생합니다. 예를 들어, 정수형 변수에 문자열 값을 할당하려는 경우입니다.
  • 이름 오류: 존재하지 않는 변수, 메서드 또는 클래스를 사용하려는 경우 발생합니다.

참고: Java Development Kit (JDK)가 설치되어 있어야 Java 코드를 컴파일하고 실행할 수 있습니다. JDK는 Oracle 웹 사이트에서 무료로 다운로드할 수 있습니다.

예시

HelloWorld.java 파일의 내용이 다음과 같다고 가정해 보겠습니다.

Java

public class HelloWorld {
  public static void main(String[] args) {
    System.out.println("Hello, world!");
  }
}

이 파일을 컴파일하려면 터미널에서 다음 명령어를 실행합니다.

Bash

javac HelloWorld.java

컴파일이 성공하면 HelloWorld.class 파일이 생성됩니다. 이 파일을 실행하려면 다음 명령어를 실행합니다.

Bash

java HelloWorld

그러면 터미널에 "Hello, world!"가 출력됩니다.

 

출처

  1. https://javarush.com/ko/groups/posts/ko.2318.-
  2. https://devdebin.tistory.com/173#google_vignette
  3. https://hcn1519.github.io/articles/2016-12/java_console
  4. https://javarush.com/ko/groups/posts/ko.2318.-

Java 설치법 (JDK17, Window 11)

※특정 IDE에서 실행하기 (이클립스)

이클립스에서 Java 코드를 컴파일하고 실행하는 방법은 터미널에서 직접 컴파일하는 것보다 훨씬 간편합니다. 이클립스는 자바 개발을 위한 통합 개발 환경 (IDE)으로, 코드 작성, 컴파일, 실행, 디버깅 등 모든 작업을 하나의 프로그램에서 수행할 수 있도록 도와줍니다.

 

이클립스에서 Java 코드 컴파일 및 실행 과정

  1. 이클립스 실행 및 프로젝트 생성:
    • 이클립스를 실행합니다.
    • File > New > Java Project 를 선택하여 새로운 자바 프로젝트를 생성합니다.
    • 프로젝트 이름을 입력하고 Finish 버튼을 클릭합니다.
  2. Java 소스 파일 생성:
    • 생성된 프로젝트의 src 폴더를 선택하고 마우스 오른쪽 버튼을 클릭합니다.
    • New > Class 를 선택하여 새로운 Java 클래스를 생성합니다.
    • 클래스 이름을 입력하고 (예: HelloWorld) Finish 버튼을 클릭합니다.
  3. 코드 작성:
    • 생성된 Java 클래스 파일 (예: HelloWorld.java) 에 코드를 작성합니다. 예를 들어, 다음과 같이 작성할 수 있습니다.
        public class HelloWorld {
            public static void main(String[] args) {
                System.out.println("Hello, world!");
            }
        }
    • Java
  4. 컴파일:
    • 이클립스는 코드를 저장할 때 자동으로 컴파일합니다. Ctrl + S (Windows) 또는 Command + S (macOS) 를 눌러 코드를 저장합니다.
    • 컴파일 오류가 있는 경우, Problems 탭에서 오류 메시지를 확인하고 수정할 수 있습니다.
  5. 실행:
    • Run > Run 을 선택하거나 Ctrl + F11 (Windows) 또는 Command + F11 (macOS) 을 눌러 코드를 실행합니다.
    • 실행 결과는 Console 탭에서 확인할 수 있습니다.

이클립스의 장점

  • 자동 컴파일: 코드를 저장할 때마다 자동으로 컴파일하여 시간을 절약할 수 있습니다.
  • 오류 표시: 컴파일 오류가 발생하면 오류가 있는 코드 줄을 표시하고 오류 메시지를 제공하여 디버깅을 쉽게 해줍니다.
  • 디버깅 기능: 코드를 단계별로 실행하고 변수 값을 확인하면서 오류를 찾아낼 수 있는 디버깅 도구를 제공합니다.
  • 코드 자동 완성: 코드를 작성할 때 자동 완성 기능을 제공하여 오타를 줄이고 생산성을 높일 수 있습니다.
  • 다양한 플러그인: 다양한 플러그인을 통해 이클립스의 기능을 확장할 수 있습니다.

이클립스는 강력한 기능을 제공하는 IDE이므로, Java 개발을 처음 시작하는 경우 이클립스를 사용하는 것이 좋습니다. 이클립스를 사용하면 Java 개발을 보다 효율적으로 진행할 수 있습니다.

 

출처

  1. 이클립스에서 Java 실행
  2. 명령프롭프트에서 Java 실행하기, 이클립스에서 Java 실행
  3. Java 통합개발환경(IDE)의 종류

바이트코드란 무엇인가?

바이트코드는 특정 하드웨어가 아닌 가상 컴퓨터에서 실행되도록 설계된 명령어 집합입니다. 쉽게 말해, 사람이 이해하는 Java 코드를 컴퓨터가 이해하도록 번역한 중간 단계의 코드라고 할 수 있습니다.

 

바이트코드의 특징

  • 플랫폼 독립적: 특정 운영체제나 CPU에 종속되지 않아, Java 가상 머신(JVM)이 설치된 어떤 환경에서도 실행 가능합니다. 이것이 "한 번 작성하면 어디서든 실행된다 (Write Once, Run Anywhere)"는 Java의 철학을 가능하게 하는 핵심 요소입니다.
  • 컴팩트: 기계어보다 더 추상적이고 간결하여 파일 크기가 작습니다.
  • 보안: JVM에서 실행되기 때문에 보안 검증 및 제어가 가능합니다.

Java 코드 실행 과정

Java bytecode (https://velog.io/@ha0kim/2020-12-14-kj1ylhp9)

  1. Java 코드 작성: 개발자가 Java 언어로 코드를 작성합니다 (HelloWorld.java).
  2. 컴파일: javac 컴파일러를 사용하여 Java 코드를 바이트코드로 변환합니다 (HelloWorld.class).
  3. 실행: JVM이 바이트코드를 읽어들여 해당 운영체제에 맞는 기계어로 변환하고 실행합니다.

바이트코드의 장점

  • 이식성: 다양한 플랫폼에서 실행 가능하므로 개발 및 배포가 용이합니다.
  • 효율성: JVM이 바이트코드를 최적화하여 실행 속도를 향상시킬 수 있습니다.
  • 보안: JVM의 보안 메커니즘을 통해 안전한 코드 실행을 보장합니다.

자바 보안 참고자료

 

바이트코드 예시

Java 코드 System.out.println("Hello, world!"); 는 다음과 같은 바이트코드로 변환될 수 있습니다.

getstatic java/lang/System.out Ljava/io/PrintStream;
ldc "Hello, world!"
invokevirtual java/io/PrintStream.println(Ljava/lang/String;)V

이 바이트코드는 JVM에 의해 해석되어 "Hello, world!"를 출력하는 기계어로 변환됩니다.

 

결론

바이트코드는 Java의 플랫폼 독립성, 효율성, 보안성을 가능하게 하는 핵심 기술입니다. Java 개발자는 바이트코드에 대한 이해를 통해 Java 프로그램의 동작 방식을 더 깊이 이해하고 효율적인 코드를 작성할 수 있습니다.

 

출처

  1. 위키백과 : 자바 바이트코드
  2. 위키백과 : 바이트코드, 나무위키 : 바이트코드
  3. 자바 컴파일과 JVM의 이해
  4. 이서우 블로그_JVM 그리고 JAVA Code 실행과
  5. JAVA의 플랫폼 독립성
  6. 자바 바이트코드_바다블로그 

JIT 컴파일러란 무엇이며 어떻게 동작하는지

JIT 컴파일러는 Just-In-Time 컴파일러의 약자로, 프로그램 실행 중에 바이트코드를 기계어로 변환하는 컴파일 기법입니다. 즉, 필요한 시점에 즉시 컴파일을 수행하여 프로그램 실행 속도를 향상시키는 역할을 합니다.

 

JIT 컴파일러의 동작 방식

  1. 바이트코드 해석: JVM은 처음에 바이트코드를 인터프리터 방식으로 실행합니다. 인터프리터는 바이트코드를 한 줄씩 읽어들여 해당하는 기계어로 변환하고 실행합니다.
  2. 핫스팟 탐지: JVM은 실행 중에 자주 실행되는 코드 블록(핫스팟)을 식별합니다. 핫스팟은 루프 또는 자주 호출되는 메서드 등이 될 수 있습니다.
  3. JIT 컴파일: 핫스팟으로 탐지된 바이트코드는 JIT 컴파일러에 의해 기계어로 컴파일됩니다. 컴파일된 기계어는 캐시에 저장됩니다.
  4. 기계어 실행: 이후 JVM은 핫스팟에 해당하는 바이트코드를 실행할 때, 캐시에 저장된 기계어를 직접 실행합니다.

JIT 컴파일러의 장점

  • 실행 속도 향상: 자주 실행되는 코드를 기계어로 미리 컴파일하여 실행 속도를 높입니다.
  • 동적 최적화: 실행 중인 프로그램의 동작을 분석하여 최적화된 기계어를 생성할 수 있습니다.

JIT 컴파일러의 단점

  • 컴파일 오버헤드: JIT 컴파일 과정 자체에 시간이 소요됩니다.
  • 메모리 사용량 증가: 컴파일된 기계어를 저장하기 위해 메모리를 추가로 사용합니다.

JIT 컴파일러의 활용

JIT 컴파일러는 Java 뿐만 아니라 JavaScript, .NET Framework 등 다양한 언어 및 플랫폼에서 사용됩니다. JIT 컴파일러는 프로그램 실행 속도를 향상시키는 중요한 기술이며, 현대적인 프로그래밍 언어 및 런타임 환경에서 널리 사용되고 있습니다.

참고

  • JIT 컴파일러는 JVM의 일부로 포함되어 있으며, 별도로 설치할 필요가 없습니다.
  • JIT 컴파일러의 동작 방식은 JVM 구현에 따라 다를 수 있습니다.

 

출처

  1. 위키백과 : JIT 컴파일러
  2. IBM 문서 : JIT 컴파일러
  3. JVM 내부구조와 실행
  4. JVM 코드실행 : https://azderica.github.io/til/docs/java/optimizing-java/ch9/
  5. 나무위키 : JIT
  6. 개발 블로그 JIT 컴파일러가 대체 먼데?
  7. 개발 블로그 hyeinisfree : JIT 컴파일러란?
  8. f-lab : 자바 성능 튜닝을 위한 JIT 컴파일러의 이해

JVM의 구성요소

JVM(Java Virtual Machine)은 Java 바이트코드를 실행하는 가상 머신입니다.

Java 프로그램이 어떤 운영체제에서든 실행될 수 있도록 플랫폼 독립적인 실행 환경을 제공합니다.

JVM은 다음과 같은 주요 구성 요소로 이루어져 있습니다.

 

1. 클래스 로더 (Class Loader)

  • 역할: 컴파일된 Java 클래스 파일(.class)을 JVM 메모리에 로드합니다.
  • 동작 방식:
    • 클래스 로딩 요청이 발생하면 클래스 로더는 클래스 파일을 찾아 로드합니다.
- 로드된 클래스는 메서드 영역에 저장됩니다.



- 클래스 로더는 계층 구조로 이루어져 있으며, 부모 클래스 로더부터 클래스를 찾습니다.

 

  • 종류:
    • 부트스트랩 클래스 로더: Java 핵심 라이브러리를 로드합니다.
- 확장 클래스 로더: 확장 라이브러리를 로드합니다.
- 애플리케이션 클래스 로더: 애플리케이션 클래스패스에 있는 클래스를 로드합니다.

2. 실행 엔진 (Execution Engine)

  • 역할: 로드된 바이트코드를 실행합니다.
  • 동작 방식:
    • 인터프리터: 바이트코드를 한 줄씩 해석하여 실행합니다.
    • JIT 컴파일러: 자주 실행되는 바이트코드를 기계어로 컴파일하여 실행 속도를 향상시킵니다.
    • 가비지 컬렉터: 더 이상 사용되지 않는 객체를 메모리에서 제거하여 메모리 관리를 수행합니다.

3. 런타임 데이터 영역 (Runtime Data Area)

  • 역할: 프로그램 실행 중에 사용되는 데이터를 저장하는 메모리 영역입니다.
  • 구성 요소:
    • 메서드 영역 (Method Area): 클래스 정보, 상수, static 변수 등을 저장합니다.
    • 힙 영역 (Heap Area): 객체를 저장합니다.
    • 스택 영역 (Stack Area): 메서드 호출 정보, 지역 변수 등을 저장합니다.
    • PC 레지스터 (PC Register): 현재 실행 중인 명령어의 주소를 저장합니다.
    • 네이티브 메서드 스택 (Native Method Stack): 네이티브 메서드 호출 정보를 저장합니다.

4. 네이티브 메서드 인터페이스 (JNI)

  • 역할: Java 프로그램이 C/C++ 등 다른 언어로 작성된 네이티브 코드를 호출할 수 있도록 인터페이스를 제공합니다.
  • 동작 방식:
    • JNI를 통해 Java 코드는 네이티브 메서드를 호출하고, 네이티브 코드는 Java 객체에 접근할 수 있습니다.

JVM 동작 방식

  1. Java 컴파일러가 Java 코드를 바이트코드로 변환합니다.
  2. 클래스 로더가 바이트코드를 JVM 메모리에 로드합니다.
  3. 실행 엔진이 바이트코드를 실행합니다.
  4. 실행 엔진은 인터프리터 또는 JIT 컴파일러를 사용하여 바이트코드를 실행합니다.
  5. 런타임 데이터 영역은 프로그램 실행 중에 사용되는 데이터를 저장합니다.
  6. JNI는 Java 프로그램이 네이티브 코드를 호출할 수 있도록 합니다.

JVM의 역할

  • 플랫폼 독립적인 실행 환경 제공
  • 메모리 관리 (가비지 컬렉션)
  • 보안
  • 성능 최적화 (JIT 컴파일)

JVM은 Java 플랫폼의 핵심 구성 요소이며, Java 프로그램의 실행을 담당합니다. JVM의 구성 요소와 동작 방식을 이해하는 것은 Java 개발에 매우 중요합니다.

 

출처

  1. f-lab : 자바 가상 머신의 이해
  2. f-lab : 자바 가상 머신 작동 원리와 구성요소
  3. f-lab : JVM의 동작원리
  4. IBM : 클래스 로더
  5. 개발블로그1 : 자바 클래스 로더
  6. 개발블로그2 : 자바 클래스 로더
  7. 개발블로그3: JVM. 클래스로더 서브시스템(Class Loader Subsystem)
  8. JVM(Java Virtual Machine), 바이트코드(Byte Code)

JDK와 JRE의 차이

JDK와 JRE는 Java 개발 및 실행에 필요한 소프트웨어지만, 그 역할과 구성 요소에 차이가 있습니다.

 

JRE (Java Runtime Environment)

  • 역할: Java 애플리케이션을 실행하기 위한 환경을 제공합니다.
  • 구성 요소:
    • JVM (Java Virtual Machine): 바이트코드를 실행하는 핵심 엔진입니다.
    • Java 클래스 라이브러리: Java API에서 제공하는 클래스 파일들입니다.
    • 기타 실행에 필요한 파일: Java 프로그램 실행에 필요한 추가적인 파일들입니다.

JDK (Java Development Kit)

  • 역할: Java 애플리케이션을 개발하기 위한 도구들을 제공합니다.
  • 구성 요소:
    • JRE: JDK는 JRE를 포함하고 있어 개발한 프로그램을 바로 실행할 수 있습니다.
    • 컴파일러 (javac): Java 코드를 바이트코드로 변환하는 도구입니다.
    • 디버거 (jdb): 프로그램의 오류를 찾아내고 수정하는 도구입니다.
    • javadoc: Java 코드에서 API 문서를 생성하는 도구입니다.
    • jar: 여러 개의 클래스 파일을 하나의 JAR 파일로 압축하는 도구입니다.
    • 기타 개발 도구: Java 애플리케이션 개발에 필요한 추가적인 도구들입니다.

결론

  • Java 프로그램을 실행만 하려면 JRE만 설치하면 됩니다.
  • Java 프로그램을 개발하려면 JDK를 설치해야 합니다. JDK에는 JRE가 포함되어 있으므로 JDK를 설치하면 JRE를 따로 설치할 필요가 없습니다.

참고

  • JDK는 Oracle, OpenJDK 등 다양한 곳에서 제공합니다.
  • JDK와 JRE는 운영체제에 따라 다르게 배포됩니다.

출처

  1. JDK, JRE, JVM이란 무엇인가?
  2. Java 런타임 환경(JRE)이란 무엇인가요?JDK와 JRE의 개념과 차이점
  3. JDK와 JRE의 개념과 차이점

'코딩스터디 > JAVA스터디' 카테고리의 다른 글

Java 자료구조) ArrayList, LinkedList (Stack, Queue)  (2) 2024.11.09
Java 클래스  (12) 2024.11.08
Java 조건문, Java 반복문  (6) 2024.11.03
Java 연산자  (2) 2024.10.26
자바 데이터 타입, 변수 그리고 배열  (2) 2024.10.19