JDK(Java Development Kit)
저희는 보통 프로젝트를 진행할때, JDK 버전을 직접 선택하게 됩니다. 그러면 이러한 JDK란 무엇일까요??
JDK란 자바 개발 키트(Java Development Kit)의 약자로 Java 언어로 소프트웨어를 개발하기 위한 소프트웨어 개발 도구 모음을 뜻합니다.
이러한 JDK안에는 자바에서 개발 시 필요한 라이브러리뿐 아니라 여러 개발 도구 등이 있습니다.
이러한 개발 도구로는 자바 소스 코드를 바이트 코드로 컴파일 하는데 사용하는 Java Compiler(javac), 컴파일된 바이트 코드를 실행하는데 사용되는 Java Interpreter(Java), 여러 java 클래스 파일을 하나의 아카이브 파일로 패키징하는데 사용하는 Java Archive(jar) , Java 프로그램을 실행하는데 필요한 라이브러리 파일들과 JVM이 포함되어 있는 JRE(Java Runtime Environment)등이 있습니다.
위 그림에서 볼 수 있듯이 JDK는 JVM,JRE를 모두 포함하고 있고, 자바로 개발하는데 필요한 development tools 또한 포함하고 있습니다.
사용자가 많은 Java 언어는 JDK 또한 여러 가지 종류로 나뉩니다.
- Oracle JDK : Oracle Corporation에서 제공하는 JDK. java 8 까지는 상업적 사용이 무료였지만 Java 11부터는 상업적 사용을 위해서 유료 라이센스를 구매해야 함
- Open JDK : Oracle이 주도하여 개발하고 있는 오픈 소스 프로젝트. 이는 Java 플랫폼의 공식 참조 구현으로, 자유롭게 사용하고 수정할 수 있음
- AdoptOpenJDK : 커뮤니티 주도로 개발되고 있는 OpenJDK의 빌드입니다. 무료로 사용할 수 있으며, 많은 사용자들이 Oracle의 상업적 라이센스 정책 변화 이후 이 버전 사용
- Amazon Corretto : Amazon이 지원하고 있는 무료의 OpenJDK 빌드. Amazon 자체의 프로덕션 환경에서 주로 사용됨
- Azul Zulu JDK : Azul System에서 제공하는 Open JDK 빌드
JRE(Java Runtime Environment)
JRE는 자바 실행환경(Java Runtime Environment)의 약자로, JVM과 자바 프로그램을 실행 시키는데 필요한 라이브러리를 함께 묶어서 배포되는 패키지를 의미합니다.
이러한 JRE는 기본적으로 JDK에 포함되어있기에, JDK를 설치하면 함께 설치됩니다.
간단히 정리하자면, Java로 프로그램을 직접 개발하려면 JDK가 필요하고, 컴파일 된 Java 프로그램을 실행시킬려면 JRE가 필요하다고 이해하시면 됩니다
JVM(Java Virtual Machine)
JVM이란 Java Virtual Machine의 약자로, 자바 바이트 코드를 실행하는 가상의 컴퓨터입니다. 이러한 JVM은 실제로 하드웨어가 아닌 소프트웨어로, 다양한 플랫폼에서 동작할 수 있도록 설계되어있습니다.
JVM은 이후 포스팅에서 좀더 상세히 다루어볼 내용이니, 지금은 기초적인 내용만 다루고 가겠습니다 :)
이러한 JVM은 왜 필요할까요???
JAVA로 작성된 소스파일은 직접 운영체제로 가서 실행하는 것이 아닌, JVM을 거쳐서 운영체제와 상호작용을 하게 되며 JVM만 있으면 운영체제가 무엇이든 관계 없이 독립적으로 프로그램을 실행할 수 있습니다.
어떻게 이것이 가능할까요??
JVM은 바이트 코드를 해당 OS나 하드웨어 아키텍처에 알맞은 기계어로 해석 또는 실행하게 해주기 때문입니다.
이 말이 모호할 수 있으니 우선 자바 컴파일 과정을 간단히 살펴보자면, 자바 컴파일러(javac)가 자바 코드(.java 파일)를 바이트코드(.class 파일, 중간언어)로 컴파일 합니다. 이후 JVM은 이 바이트 코드를 실행하는 과정에서 해당 OS나 하드웨어 아키텍처에 맞게 기계어로 해석하며 이러한 과정은 바이트 코드가 실행되는 시점에 이루어집니다.
여기서 바이트코드란 특정 하드웨어가 아닌 가상머신에서 실행되도록 고안된 특별한 형태의 중간 코드 입니다. 이러한 바이트 코드는 JVM과 같은 가상 머신에서 실행될 수 있으며, 보통 Java,Kotlin, Scala 등의 언어에서 사용하고 있습니다.
반면 기계어란 컴퓨터의 CPU가 직접 이해할 수 있는 저수준의 언어입니다. 이것은 CPU의 구조에 따라 다르며, 각 CPU는 ISA(Instruction Set Architecture)라고 부르는 특정한 기계어 명령어 세트를 가집니다.
자바는 WORA(Write Once, Run Anywhere)이라는 철학을 가지고 있습니다. 이는 한번 작성한 프로그램을 어떤 플랫폼에서도 실행할 수 있다는 의미이며, 이를 가능하게 만드는 기술이 앞서 설명 드린 JVM입니다. 따라서 같은 자바 프로그램을 다른 운영체제에서 실행하려면 해당 운영체제용 JVM만 설치되어 있으면 됩니다.
자바 프로그램과 달리 JVM은 운영체제에 종속적이므로, 각 운영체제에 맞는 가상 머신을 설치해야 한다는 점은 유의해야 합니다
다른 프로그래밍 언어도 그렇지않나요?? 라고 생각하시는 분이 계실수 있으니 C언어 컴파일 과정을 간단히 살펴보겠습니다.
C 언어는 컴파일 과정에서 바로 특정 운영체제와 하드웨어 아키텍처에 맞는 기계어로 변환됩니다. 이러한 과정은 특정 컴파일러에 의해 수행되며, 이 컴파일러는 특정 운영 체제와 특정 하드웨어 아키텍처에 맞게 설계되어있습니다.
따라서 C 프로그램을 다른 운영 체제나 하드웨어에서 실행하려면, 그에 맞는 컴파일러를 사용해 다시 컴파일 해야합니다.
이러한 특성 때문에 C언어는 Write Once, Compile AnyWhere이라는 WOCA 특성을 가지고 있다고 말할 수 있습니다.
그렇다면 무조건 가상 머신을 두는 것이 좋을까요???
결론적으로는 아닙니다. 앞서 보았듯이 자바 코드는 C로 작성된 코드에 비해 JVM이라는 한 단계를 더 거쳐야 하므로, 상대적으로 실행 속도가 느리다는 단점을 내포하고 있습니다.
이러한 단점을 보완하기 위해 JIT(Just-In-Time)컴파일러라는 내부 프로그램을 사용해서 필요한 부분만을 기계어로 바꾸어 줌으로써 성능 향상을 가져오도록 했지만, 그럼에도 C언어의 실행 속도를 따라잡지는 못하였습니다.
JIT 컴파일러에 대해 처음 보시는 분이 계실수 있으니 간단히 살펴보고 가겠습니다!
초기 자바 환경에서는 JVM이 바이트 코드를 한줄 씩 해석해서 실행하는 방식, 즉 인터프리터 방식만을 사용했습니다. 이 방식은 다음과 같은 과정을 거칩니다.
우선 자바 소스코드(.java)는 자바 컴파일러에 의해 바이트코드(.class 파일)로 변환됩니다. 이렇게 생성된 바이트 코드는 JVM 위에서 실행되는 동안, JVM 내부의 인터프리터에 의해 해당 시스템의 기계어로 해석 된 후 실행됩니다. 이러한 과정은 모든 코드라인에 대해 반복되며, 한줄 씩 해석하고 실행하는 방식으로 진행됩니다.
이러한 방식의 플랫폼 독립성을 보장하지만, 중복된 코드에 대해서도 매번 다시 해석해야하므로 효율성이 떨어집니다.
이러한 인터프리터의 단점을 극복하기 위해 JVM에서는 JIT(Just-in-Time) 컴파일러가 도입되었습니다. JIT 컴파일러는 프로그램이 실행되는 동안 어떤 코드가 자주 실행되는지, 즉 어떤 코드가 핫스팟 인지 분석합니다.
JIT 컴파일러는 이런 핫스팟을 발견하면 해당 코드를 기계어로 변환하고 이 변환된 결과를 캐시에 저장해둡니다. 그럼 이후에는 원래 바이트코드를 다시 해석해서 실행하는 대신에 이미 변환해둔 기계어 코드를 사용하여 실행할 수 있습니다. 그래서 같은 코드가 반복해서 나타나더라도 다시 해석할 필요 없이 저장해둔 기계어 코드를 재사용하게 됩니다.
그런데 이렇게 핫스팟을 파악하려면 해당 프로그램의 일부가 이미 몇 번 실행된 상태여야 합니다. 즉, JIT 컴파일러는 프로그램이 동작하면서 그 동작 패턴을 분석하고 학습하게 됩니다.
현재의 자바는 인터 프리터 방식과 JIT 컴파일러 방식을 모두 사용하고 있습니다. 처음에 프로그램이 실행되면 JVM의 인터프리터가 바이트 코드를 한줄씩 해석하고 실행합니다. 하지만 이렇게 인터프리터 방식으로 실행되는 동안 JVM 내부에서는 동시에 어떤 코드가 자주 실행되는지 분석하며, 이를 핫스팟이라고 부릅니다.
이러한 핫스팟을 발견하면, JIT컴파일러가 해당 바이트 코드를 기계어로 컴파일하고, 이 결과를 캐시에 저장합니다. 그래서 이후에는 같은 코드가 다시 실행될때는 인터프리터로 다시 해석하는 대신, 이미 컴파일 해둔 기계어 코드를 사용해서 실행하게 됩니다.
참고
지금까지 JDK,JRE,JVM과 이와 관련된 개념에 대해 다루어보았습니다!
틀린 내용이 있다면 댓글 부탁드리겠습니다! 곧바로 수정하도록 하겠습니다
https://tecoble.techcourse.co.kr/post/2021-07-12-jvm-jre-jdk/
https://inpa.tistory.com/entry/JAVA-☕-JDK-JRE-JVM-개념-구성-원리-💯-완벽-총정리
https://cryptosalamander.tistory.com/4
'JAVA' 카테고리의 다른 글
Garbage Collection 한 눈에 알아보기! (0) | 2023.06.01 |
---|---|
JVM(Java Virtual Machine) 한눈에 알아보기 (0) | 2023.05.31 |
Collection Framework 완전 정복 6탄(마지막편) - Map인터페이스(HashMap, LinkedHashMap,HashTable, TreeMap) (2) | 2023.05.29 |
Collection Framework 완전 정복 5탄 - Set인터페이스 (HashSet, LinkedHashSet) (0) | 2023.05.28 |
Hash, HashFunction, HashCollision 완벽 정복하기! (0) | 2023.05.26 |