1. 자바 프로그램 실행방식
프로그램은 일반적으로 다음과 같은 순서들에 따라 개발된다.

프로그래밍 언어로 코드를 작성한 후엔 이를 파일 형태로 저장하는데, 이를 소스 파일(Source File)이라고 한다. 다음은 각각 C와 자바로 작성한 소스 파일이다. C는 소스 파일을 저장할 때 파일 확장자가 ".c"인 반면, 자바는 ".java"이다.
// test.c
printf("%s", "직진하시오");
printf("%s", "50M 앞에서 좌회전하시오");
// test.java
System.out.println("직진하시오");
System.out.println("50M 앞에서 좌회전하시오");
한편 소스 파일은 사람에 의해 C나 자바와 같은 고급 언어로 작성되지만, 고급 언어로 작성한 파일을 컴퓨터에서 실행시키기 위해선 컴퓨터가 인식할 수 있는 저급 언어(기계어)로 변환하는 과정이 필요하다. 이렇게 고급 언어로 작성된 소스 파일을 기계어로 변환하는 작업을 컴파일(Compile)이라고 하며, 변환 프로그램을 컴파일러(Compiler)라고 한다.
컴파일 과정을 거쳐 1과 0으로 변환된 파일은 컴퓨터에서 바로 실행할 수 있으므로 실행 파일(Execute File)이라고 한다. C에서는 "*.c" 소스 파일을 컴파일하면 "*.exe" 실행 파일이 생성되며, 자바에서는 ".java" 소스 파일을 컴파일하면 ".class" 실행 파일이 생성된다.

컴파일은 소스 파일을 기계어로 변환해 실행 파일을 생성하는 작업이다. 그리고 컴파일 과정을 거쳐 생성된 파일은 기계어 코드이므로 컴퓨터에서 바로 실행될 수 있다. 그런데 자바는 다른 프로그래밍 언어와 다르게 컴파일 작업을 통해 바이트 코드(byte code)를 만들어낸다. 바이트 코드는 기계어로 변환하기 전 중간 단계의 코드다. 여기서 중요한 점은 바이트 코드는 기계어가 아니므로 컴퓨터에서 바로 실행할 수 없다는 것이다.

사실 위 그림에서 오른쪽은 잘못되었다. test.class 파일은 기계어로 작성된 파일이 아니므로 컴퓨터에서 바로 실행될 수 없기 때문이다. 따라서 소스 파일에서 컴파일된 바이트 코드를 다시 기계어 코드로 변환하는 작업이 필요하다.
자바에서 이 작업은 개발자가 아닌 프로그램이 한다. 자바 개발자는 소스 파일을 작성하고 컴파일하여 바이트 코드 생성까지만 하고, 바이트 코드를 기계어 코드로 변환하는 작업과 자바 프로그램 실행에 관련된 모든 작업은 자바 가상 머신(JVM, Java Virtual Machine)에서 담당한다.

2. JVM 개요
자바 개발자는 소스 파일을 작성하고 컴파일한 후 생성된 바이트 코드 파일을 배포하는 작업까지만 한다. 이렇게 배포된 바이트 코드를 사용자가 실행하기 위해선 반드시 컴퓨터에 JVM이 설치되어 있어야 한다. 오라클 공식 홈페이지에서 운영체제별로 각기 다른 JVM을 다운받을 수 있다.
JVM은 자바 실행 파일이 각 컴퓨터의 운영체제에 맞게 실행될 수 있도록 기계어 코드로 변환 작업을 한 후 자바 실행 파일을 구동한다. 이러한 자바 실행 구조의 큰 장점은 자바 실행 파일이 실행되는 컴퓨터(OS)가 달라져도 추가적인 작업을 할 필요가 없다는 것이다. 즉, 운영체제와 자바 실행 파일 사이에서 JVM이 처리를 해주기 때문에 실행 파일은 어떤 운영체제에서도 실행될 수 있다. 이러한 맥락에서 자바를 플랫폼(실행하는 환경)에 독립적인 언어라고 한다. 이를 C와 비교해서 살펴보면 좀 더 쉽게 이해할 수 있다.

C는 자바처럼 하나의 컴파일러만 존재하는 것이 아니라 프로그램을 실행할 운영체제별로 컴파일러를 선택해 컴파일해야 한다. 예를 들어 윈도우 운영체제를 사용하는 컴퓨터에서 실행하기 위해서 윈도우용 컴파일러를 사용하다가, 해당 파일을 리눅스 운영체제에서 실행하고자 하면 리눅스용 컴파일러를 사용해서 다시 컴파일해야 한다. 이처럼 C는 플랫폼에 독립적인 자바와 달리, 운영체제가 달라지면 새로 작업해야 하므로 플랫폼에 종속적인 언어이다.

3. JVM 실행 환경
자바 프로그램은 윈도우, 리눅스, 맥 운영체제에 최적화된 JVM에서 실행된다. 자바 프로그램이 실행될 때 JVM은 항상 다음과 같은 일정한 처리 과정을 거친다. JVM이 자바 프로그램을 실행하는 과정을 자세히 살펴보자. 보다 자세한 JVM의 구성은 여기를 참고하자.

1) 클래스 로더(Class loader)
- 자바 프로그램이 실행될 때 가장 먼저 동작하며 실행에 필요한 모든 실행 파일(*.class)을 찾아준다
- 클래스 파일을 메모리에 올린다
- 메모리에 올린다는 것은 자바 소스 파일에 정의한 클래스에 관한 정보와 코드를 JVM의 코드 영역에 만들어주는 것을 의미한다
2) 바이트 코드 검증(Byte code verifer)
- 클래스 로더가 모든 실행 파일(*.class)을 준비한 후에는 이 파일의 코드가 올바른지 검증한다
- 예를 들어 코드가 정해진 규칙에 따라 작성되었는지, 또는 컴퓨터에 문제를 일으킬만한 코드는 없는지 검증한다
- 이처럼 자바 프로그램은 실행 시점에 코드의 유효성을 검증하는 과정을 거치므로 보안에 강하다는 장점이 있다
3) JIT 컴파일러
바이트 코드로 된 자바 프로그램을 컴퓨터에서 실행시키기 위해서는 기계어 코드로 변환하는 작업을 거쳐야 한다. 기계어 코드로 변환하는 방식에는 인터프리터(Interpreter) 방식과 JIT(Just In Time) 방식이 있다. 자바 초기에는 인터프리터 방식을 사용했는데, 이 방식은 처리 속도가 느리다는 단점이 있다. JIT는 이를 보완하기 위해 나온 방식으로 미리 컴파일해놓고 실행하므로 처리 속도가 좀 더 빠르다.
인터프리터 방식
- 기계어로 변환하는 작업을 명령문 단위로 처리한다
JIT 방식
- 소스 파일을 실행 파일로 변환하는 것처럼 파일 전체를 한 번에 기계어로 변환하다.

4. 참고
- 처음해보는 자바 프로그래밍(오정임 저)
'프로그래밍 언어 > Java + Kotlin' 카테고리의 다른 글
[Java] 생성자 총정리 (0) | 2023.01.06 |
---|---|
[Kotlin] 코틀린에서 애너테이션 사용하기 (vs 자바) (0) | 2022.12.19 |
[Kotlin] BigDecimal을 비교할 때 주의하라 (0) | 2022.11.08 |
[Kotlin] scope function - let, run, also, apply, with 차이 (0) | 2022.08.13 |
[Kotlin] 코틀린 유용한 함수 - padEnd (0) | 2022.07.19 |
1. 자바 프로그램 실행방식
프로그램은 일반적으로 다음과 같은 순서들에 따라 개발된다.

프로그래밍 언어로 코드를 작성한 후엔 이를 파일 형태로 저장하는데, 이를 소스 파일(Source File)이라고 한다. 다음은 각각 C와 자바로 작성한 소스 파일이다. C는 소스 파일을 저장할 때 파일 확장자가 ".c"인 반면, 자바는 ".java"이다.
// test.c
printf("%s", "직진하시오");
printf("%s", "50M 앞에서 좌회전하시오");
// test.java
System.out.println("직진하시오");
System.out.println("50M 앞에서 좌회전하시오");
한편 소스 파일은 사람에 의해 C나 자바와 같은 고급 언어로 작성되지만, 고급 언어로 작성한 파일을 컴퓨터에서 실행시키기 위해선 컴퓨터가 인식할 수 있는 저급 언어(기계어)로 변환하는 과정이 필요하다. 이렇게 고급 언어로 작성된 소스 파일을 기계어로 변환하는 작업을 컴파일(Compile)이라고 하며, 변환 프로그램을 컴파일러(Compiler)라고 한다.
컴파일 과정을 거쳐 1과 0으로 변환된 파일은 컴퓨터에서 바로 실행할 수 있으므로 실행 파일(Execute File)이라고 한다. C에서는 "*.c" 소스 파일을 컴파일하면 "*.exe" 실행 파일이 생성되며, 자바에서는 ".java" 소스 파일을 컴파일하면 ".class" 실행 파일이 생성된다.

컴파일은 소스 파일을 기계어로 변환해 실행 파일을 생성하는 작업이다. 그리고 컴파일 과정을 거쳐 생성된 파일은 기계어 코드이므로 컴퓨터에서 바로 실행될 수 있다. 그런데 자바는 다른 프로그래밍 언어와 다르게 컴파일 작업을 통해 바이트 코드(byte code)를 만들어낸다. 바이트 코드는 기계어로 변환하기 전 중간 단계의 코드다. 여기서 중요한 점은 바이트 코드는 기계어가 아니므로 컴퓨터에서 바로 실행할 수 없다는 것이다.

사실 위 그림에서 오른쪽은 잘못되었다. test.class 파일은 기계어로 작성된 파일이 아니므로 컴퓨터에서 바로 실행될 수 없기 때문이다. 따라서 소스 파일에서 컴파일된 바이트 코드를 다시 기계어 코드로 변환하는 작업이 필요하다.
자바에서 이 작업은 개발자가 아닌 프로그램이 한다. 자바 개발자는 소스 파일을 작성하고 컴파일하여 바이트 코드 생성까지만 하고, 바이트 코드를 기계어 코드로 변환하는 작업과 자바 프로그램 실행에 관련된 모든 작업은 자바 가상 머신(JVM, Java Virtual Machine)에서 담당한다.

2. JVM 개요
자바 개발자는 소스 파일을 작성하고 컴파일한 후 생성된 바이트 코드 파일을 배포하는 작업까지만 한다. 이렇게 배포된 바이트 코드를 사용자가 실행하기 위해선 반드시 컴퓨터에 JVM이 설치되어 있어야 한다. 오라클 공식 홈페이지에서 운영체제별로 각기 다른 JVM을 다운받을 수 있다.
JVM은 자바 실행 파일이 각 컴퓨터의 운영체제에 맞게 실행될 수 있도록 기계어 코드로 변환 작업을 한 후 자바 실행 파일을 구동한다. 이러한 자바 실행 구조의 큰 장점은 자바 실행 파일이 실행되는 컴퓨터(OS)가 달라져도 추가적인 작업을 할 필요가 없다는 것이다. 즉, 운영체제와 자바 실행 파일 사이에서 JVM이 처리를 해주기 때문에 실행 파일은 어떤 운영체제에서도 실행될 수 있다. 이러한 맥락에서 자바를 플랫폼(실행하는 환경)에 독립적인 언어라고 한다. 이를 C와 비교해서 살펴보면 좀 더 쉽게 이해할 수 있다.

C는 자바처럼 하나의 컴파일러만 존재하는 것이 아니라 프로그램을 실행할 운영체제별로 컴파일러를 선택해 컴파일해야 한다. 예를 들어 윈도우 운영체제를 사용하는 컴퓨터에서 실행하기 위해서 윈도우용 컴파일러를 사용하다가, 해당 파일을 리눅스 운영체제에서 실행하고자 하면 리눅스용 컴파일러를 사용해서 다시 컴파일해야 한다. 이처럼 C는 플랫폼에 독립적인 자바와 달리, 운영체제가 달라지면 새로 작업해야 하므로 플랫폼에 종속적인 언어이다.

3. JVM 실행 환경
자바 프로그램은 윈도우, 리눅스, 맥 운영체제에 최적화된 JVM에서 실행된다. 자바 프로그램이 실행될 때 JVM은 항상 다음과 같은 일정한 처리 과정을 거친다. JVM이 자바 프로그램을 실행하는 과정을 자세히 살펴보자. 보다 자세한 JVM의 구성은 여기를 참고하자.

1) 클래스 로더(Class loader)
- 자바 프로그램이 실행될 때 가장 먼저 동작하며 실행에 필요한 모든 실행 파일(*.class)을 찾아준다
- 클래스 파일을 메모리에 올린다
- 메모리에 올린다는 것은 자바 소스 파일에 정의한 클래스에 관한 정보와 코드를 JVM의 코드 영역에 만들어주는 것을 의미한다
2) 바이트 코드 검증(Byte code verifer)
- 클래스 로더가 모든 실행 파일(*.class)을 준비한 후에는 이 파일의 코드가 올바른지 검증한다
- 예를 들어 코드가 정해진 규칙에 따라 작성되었는지, 또는 컴퓨터에 문제를 일으킬만한 코드는 없는지 검증한다
- 이처럼 자바 프로그램은 실행 시점에 코드의 유효성을 검증하는 과정을 거치므로 보안에 강하다는 장점이 있다
3) JIT 컴파일러
바이트 코드로 된 자바 프로그램을 컴퓨터에서 실행시키기 위해서는 기계어 코드로 변환하는 작업을 거쳐야 한다. 기계어 코드로 변환하는 방식에는 인터프리터(Interpreter) 방식과 JIT(Just In Time) 방식이 있다. 자바 초기에는 인터프리터 방식을 사용했는데, 이 방식은 처리 속도가 느리다는 단점이 있다. JIT는 이를 보완하기 위해 나온 방식으로 미리 컴파일해놓고 실행하므로 처리 속도가 좀 더 빠르다.
인터프리터 방식
- 기계어로 변환하는 작업을 명령문 단위로 처리한다
JIT 방식
- 소스 파일을 실행 파일로 변환하는 것처럼 파일 전체를 한 번에 기계어로 변환하다.

4. 참고
- 처음해보는 자바 프로그래밍(오정임 저)
'프로그래밍 언어 > Java + Kotlin' 카테고리의 다른 글
[Java] 생성자 총정리 (0) | 2023.01.06 |
---|---|
[Kotlin] 코틀린에서 애너테이션 사용하기 (vs 자바) (0) | 2022.12.19 |
[Kotlin] BigDecimal을 비교할 때 주의하라 (0) | 2022.11.08 |
[Kotlin] scope function - let, run, also, apply, with 차이 (0) | 2022.08.13 |
[Kotlin] 코틀린 유용한 함수 - padEnd (0) | 2022.07.19 |