자바 프로그램을 실행시키는 프로그램.
한번의 작성으로, 어디서든 실행된다
자바 코드를 컴파일해서 배포하면, 어떤 플랫폼이든 다시 컴파일하지 않고도 실행시킬 수 있다!
Java가 출시되었던 1996년 당시, 모든 컴퓨터 프로그램은 특정 운영 체제에 따라 다르게 작성해야 했고, 프로그램의 메모리는 그 소프트웨어 개발자들이 관리했었다.
=> 동일한 플랫폼에서 컴파일과 실행을 같이 한다면, 프로그램은 아무 문제 없이 동작하지만, 플랫폼이 달라질 경우, 타겟 플랫폼에서 동작하지 않는다.
(ex:리눅스에서 컴파일하고 리눅스에서 실행하면 문제 없이 동작하지만, 리눅스에서 컴파일하고 윈도우에서 실행하면 안돌아간다.)
jvm이 나오기 이전에는
-> 이걸 해결하기 위해 크로스 컴파일(타켓 플랫폼에 맞춰 컴파일하는 것)
-> C,C++는 크로스컴파일로 해결!
Java는 이 문제를 JVM으로 근본적으로 해결했다.
크로스 컴파일로 해결했는데 굳이 JVM을 사용하는 이유?
-> 네트워크에 연결된 모든 디바이스에서 작동하는 것이 목적이기 때문이다.
JVM의 2가지 기능
1) 어떠한 장치나 운영 체제에서도 자바 프로그램이 실행되도록 한다.
2) 프로그램 메모리를 관리하고 극대화한다. (자동 메모리 관리)
자바가 운영체제로부터 독립적인 것은 JVM이 있기 때문이다.
-> Java가 어떤 운영체제에서 작성되었던 JVM이 실행 환경에 맞게 자바 코드를 해석해 실행할 수 있게 하기 때문이다.
그러나 JVM 자체는 운영체제에 의존적이기 때문에 각자의 운영 체제에 맞는 JVM을 깔아야 한다.
즉, 리눅스의 JVM과 윈도우즈의 JVM은 다르다.(윈도우는 윈도우용 JVM 필요)
단, 컴파일된 코드는 어떤 JVM에서도 동작시킬 수 있다.
JVM은 어플리케이션 메모리를 관리하고, 자바 기반 어플리케이션을 위한 이식성 실행 환경을 제공한다.
그로 인해 개발자들은 성능, 안정성 그리고 예측 가능한 런타임의 성과를 끌어올릴 수 게 되었고 핵심 코드에 집중할 수 있게 되었다.
원래는 Java 전용이었지만 현재는 Scala, Groovy, kotlin 등을 비롯한 많은 스크립팅 및 프로그래밍 언어를 지원하고 있다.
사람이 보기 편하게 만든 소스 코드를 컴퓨터가 이해할 수 있는 기계어로 변환하는 과정
Java 소스 코드가 Javac라는 컴파일러를 거치고 나면 자바 바이트코드가 된다.
이 자바 바이트 코드는 JVM이 설치된 플랫폼이라면 어떤 플랫폼이든 상관없이 문제없이 동작한다.
물론 JVM이 플랫폼과 관련된 복잡한 작업들을 대신 해주기 때문에 가능한 것이다.
자바 바이트 코드는 JVM은 이해할 수 있는 언어이지만 CPU는 이해하지 못하기 때문에 프로젝트를 실행시킬 때 CPU가 이해할 수 있는 언어인 바이너리 코드로 Run-time 환경에서 한번 더 컴파일한 후 동작한다.
그러나 자바 11부턴 .Java를 jvm에서 바로 실행할 수 있다.
cf) 환경,플랫폼 : 운영체제 + CPU아키텍처
개발환경 실행환경 등 어떠한 목적을 수행할 수 있는 환경을 말한다.
가상머신(Virtual Machine)이 이해할 수 있는 이진 코드.
어떤 플랫폼에도 종속되지 않고 실행될 수 있는 가산 머신용 기계어 코드.
고급언어로 작성된 소스코드를 가상 머신이 이해할 수 있는 중간 코드로 컴파일한 것을 말한다.
CPU가 텍스트를 이해하지 못하듯이 가상 머신 또한 텍스트를 이해하지 못한다.
JVM을 위한 바이트 코드를 자바 바이트 코드라고 한다.
cf) 바이너리 코드 : 컴퓨터(CPU)가 인식할 수 있는 0과 1로 구성된 이진코드.
자바 클래스 파일 : 바이트 코드를 담는 파일
런타임 시 바이트 코드를 원시 시스템 코드로 컴파일하여 Java™ 애플리케이션의 성능을 향상시키는 런타임 환경의 컴포넌트
Java Interpreter의 단점을 보완하기 위해 도입된 방식.
인터프리터 방식으로 실행을 하다가 적절한 시점에 바이트 코드 전체를 컴파일 하고 더이상 인터프리팅 하지않고 해당 코드를 직접 실행 하는 것이다.
바이트 코드 전체를 기계어(바이너리코드)로 바꾸는 방식이다.
그래서 빌드 시에 컴파일러는 인터프리터보다 속도가 더 느리다. 그 이후에는 해당 메서드를 더 이상 인터프리팅 하지 않고 바이너리 코드로 직접 실행한다.
즉, 하나씩 인터프리팅하여 실행하는 것이 아니라 만들어 둔 실행파일만 읽으면 되므로 실행속도는 인터프리터보다 빠르다.
JIT Compiler에 의해 해석된 코드는 캐시에 보관하기 때문에 한 번 컴파일 된 후에는 빠르게 수행하는 장점이 있다.
하지만 인터프리팅 방식보다는 훨씬 오래 걸리므로 한번만 실행하면 되는 코드는 인터프리팅 하는 것이 유리하다.
cf) Java Interpreter (인터프리터)
바이트 코드 명령어를 한 문장씩 읽어서 기계어로 바꿔준다. 그 후 변환된 코드를 실행한다. 각각 하나하나의 실행은 빠르지만 전체적인 실행 속도는 느리다는 단점이 있다.
JRE + 개발을 위해 필요한 도구들(javac,java,,,)을 포함한다.
JRE는 JVM이 자바 프로그램을 동작시킬 때 필요한 라이브러리 파일들과 기타 파일들을 가지고 있다.
즉, JVM의 실행 환경을 구현했다고 볼 수 있다.
-Layout Architecture
컴파일러에도 프론트엔트,백엔드 존재
웹에서의 백엔드 : 크게 바뀌지 않음,
프론트엔드 : 클라이언트(서버에 접속하여 서비스를 받는 매체)의 종류에 따라 바뀜
컴파일러에서의 백엔드(JVM) : 중앙계층표현을 어셈블리 언어로 바꿔야 함. 어셈블리 언어가 운영체제나 기기에 의존적. 그래서 백엔드만 윈도우형, 리눅스형,,이 있다.
프론트엔드(javac) : 바뀌지 않음(소스코드 분석해서 의미 파악하는 일-> 플랫폼과 아무 관련이 없음).
c,c++에서는 컴파일러가 이 모든 걸 해주지만 자바에서는 프론트엔드는 javac가 백엔드는 JVM이 수행.(업무 분리)
그래서 장점 : c언어는 한번 컴파일하고 나면 더이상 컴파일할 것이 없음, 더이상 개입 못함.
Runtime Data Area
: jvm이 사용하는 메모리 공간
Bytecode
:
Garbage Collector
JIT(Just In Time) Compiler
추후에 봐야 할 글
https://deepu.tech/memory-management-in-jvm/
참조 :
https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html
https://www.infoworld.com/article/3272244/what-is-the-jvm-introducing-the-java-virtual-machine.html
JIT Compiler
https://www.ibm.com/docs/ko/sdk-java-technology/8?topic=reference-jit-compiler
JVM 구조
https://aljjabaegi.tistory.com/387
https://codingwell.tistory.com/66