Java 코드가 실행되는 과정

장숭혁·2023년 11월 3일
0

TIL작성

목록 보기
9/60

.java 파일은 컴파일러에 의해 .class 파일로 바뀐다. 자바 바이트 코드로 번역이 된다.
java바이트 코드는 JVM이 읽고 실행한다.

  • .java 파일 : 자바 프로그래밍 언어로 작성된 소스 코드 파일의 확장자

  • 자바 컴파일러 : 소스코드를 바이트 코드로 바꾸는 역할을 한다.

  • .class 파일 : 컴파일에 의해 바이트코드로 변한 파일이다. JVM에 의해서 실행되는 파일이다.

  • 자바 바이트 코드 : JVM이 이해할 수 있는 바이트 코드이다. 자바 컴파일러에 의해 변환되는 코드의 명령어 크기가 1바이트라 자바 바이트 코드라 불린다.

  • JVM : 자바가 OS에 상관없이 동일하게 동작할 수 있도록 한다. 자바 클래스 파일을 로드, 바이트 코드 해석, 메모리 등의 자원할당 등등의 작업을 한다.

  • ➕바이너리 코드 : cpu가 이해할 수 있는 언어가 바이너리 코드이다. 바이트 코드는 가상머신JVM이 이해할 수 있는 코드이다. 바이너리 코드는 OS에 종속되며 바이트 코드는 JVM에 의해 OS에 맞게 번역 실행되기 때문에 OS에 종속되지 않는다.

JVM의 주요구성은 클래스 로더Class Loader, 실행 엔진Execution Engine, 런타임 데이터 영역Runtime Data Area, 메소드 영역method Area, Heap, 자바 스택java stack, 네이티브 메소드 스택native method stack ... 가 있다.

  • 클래스 로더 : 클래스 로더는 클래스 파일을 로드해 JVM 내의 런타임 데이터 영역에 배치한다. 세가지 클래스 로더를 제공하는데

    • 부트스트랩 클래스 로더 : jvm 핵심 클래스 로드(c/c++로 작성되어 java로 직접 접근 불가)

    • 익스텐션 클래스 로더 : 표준 확장 라이브러리 로드

    • 애플리케이션 클래스 로더 : 애플리케이션의 클래스들을 로드 , 사용자 정의 클래스 로더 생성 가능

  • 실행 엔진 : 로딩된 클래스의 바이트 코드를 해석한다. 해당 OS에서 실행할 수 있는 바이너리 코드로 변환한다. 어셈비어(Assembier)가 어셈블리어를 바이너리 코드로 변환한다.

  • 런타임 데이터 영역 : JVM이 프로세스로서 수행하기 위해 OS로 부터 할당받는 영역 5가지 영역이 있다.

    ⚀ 메소드 영역 : 모든 THREAD에게 공유된다. 클래스 정보, 변수 정보, 메소드 정보 , STATIC 변수 정보, 상수 정보 등의 메타 데이터가 저장되는 영역이다.

    public class MyClass {
      private static int myStaticVariable = 42;
    
      public void myMethod() {
          int localVar = 10;
          // 메소드 내용
      }
    
      public static void myStaticMethod() {
          // 정적 메소드 내용
      }
    }
    • Method Area에는 클래스의 이름, 상위 클래스 정보, 정적 변수, 메소드 코드 등이 저장된다. MyClass의 myStaticVariable, myMethod(), myStaticMethod()와 관련된 정보가 여기에 저장된다. 초기화 , 실행 가능하다.

⚀ 힙 영역 : 모든 THREAD에게 공유된다. NEW 명령어로 생성된 인스턴스와 객체가 저장되는 구역, 공간이 부족해 지면 가비지 컬렉션이 실행딘다.

public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void sayHello() {
        System.out.println("Hello, my name is " + name + " and I am " + age + " years old.");
    }

    public static void main(String[] args) {
        // Person 객체를 힙에 생성
        Person person1 = new Person("Alice", 30);
        Person person2 = new Person("Bob", 25);

        // 객체 메소드 호출
        person1.sayHello();
        person2.sayHello();
    }
}
  • -main 메소드에서 Person 클래스의 두 객체, person1과 person2를 생성하고 초기화한다. 이 객체들은 힙 영역에 저장된다.
    - person1과 person2는 동적으로 할당된 객체이므로 힙 영역에 저장된다. 이러한 객체는 가비지 컬렉션의 대상이 될 때까지 유지된다.
    - person1과 person2 객체는 sayHello 메소드를 호출하여 각각 자신의 name 및 age 필드 값을 출력한다.
    - 힙 영역은 객체의 생성, 사용 및 소멸을 관리하는 곳으로, 객체는 힙에 생성되며, 더 이상 참조되지 않으면 가비지 컬렉션에 의해 제거가 된다. 힙 영역은 Java 프로그램에서 동적 메모리 할당 및 객체 관리를 담당한다.

    ⚀ 스택 영역 : 각 스레드 마다 하나씩 생성된다. 메소드 안에서 사용되는 값들이 저장되는 구역이다. LAST IN FIRST OUT(LIFO)로 하나씩 생성되고, 완료되면 LIFO로 지워진다.

    public class StackExample {
     public static int add(int a, int b) {
         int result = a + b;
         return result;
     }
    
     public static int multiply(int a, int b) {
         int result = a * b;
         return result;
     }
    
     public static void main(String[] args) {
         int x = 5;
         int y = 3;
         int sum = add(x, y);
         int product = multiply(x, y);
         System.out.println("Sum: " + sum);
         System.out.println("Product: " + product);
     }
    }
    
      • main 메소드에서 먼저 int x와 int y를 선언하고 값을 할당한다.
        add(x, y) 메소드 호출 시, add 메소드의 스택 프레임이 생성되고 메소드가 실행한다. int result가 스택 프레임에 저장되고 계산 결과를 반환한다.

      • multiply(x, y) 메소드 호출 시, multiply 메소드의 스택 프레임이 생성되고 메소드가 실행된다. 다시 int result가 스택 프레임에 저장되고 계산 결과를 반환한다.

      • main 메소드에서 계산된 sum 및 product 변수를 출력한다.

⚀ PC 레지스터 : 각 스레드 마다 하나씩 생성된다. CPU의 레지스터 역할과 비슷하다. 현재 수행중인 JVM 명령의 주소값이 저장된다.

⚀ NATIVE METHOD STACK(네이티브 메소드 스택): 각 스레드 마다 하나씩 생성되며, 다른 언어의 머서드 호출을 위해 할당되는 구역 언어에 맞게 STACK이 형성되는 구역이다.

profile
코딩 기록

0개의 댓글

관련 채용 정보