[라이브스터디] JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가

sjhello·2020년 11월 16일
0

자바 파일 컴파일 하는 방법

디렉토리에 사용자가 만든 hello.java 파일을 javac 명령어를 이용해 컴파일 할 수 있다

컴파일된 자바 파일을 실행하는 방법

java "컴파일된 자바 파일명" 명령어로 자바 파일을 실행 할 수 있다
java 명령어를 사용하여 자바 파일을 실행하기 전 반드시 javac를 통하여 컴파일러 작업이 우선되어야 한다 컴파일 하지 않고 파일을 실행하면 에러가 발생한다

오류: 기본 클래스 hello2을() 찾거나 로드할 수 없습니다.

바이트 코드

고수준의 언어(자바)로 이루어진 코드를 자바 컴파일러를 통해 JVM이 이해할 수 있게 만든 형태이다
바이트 코드의 내부는 0과 1로 이루어진 바이너리 코드이다

JVM(Java Virtual Machine)은 javac 컴파일러에 의해 만들어진 바이트 코드를 컴퓨터가 이해할 수 있는 바이너리 코드로 변환해 준다

바이트 코드는 바이너리 코드인데 JVM은 왜 바이너리 코드로 한번 더 변환시키는 걸까?

앞서 바이트 코드는 고수준의 언어(자바)를 JVM이 이해할 수 있게 만든 형태라고 설명했다
하지만 프로그램을 실행시키는 주체는 결국 컴퓨터이다 즉, 컴퓨터가 이해할 수 있는 언어(기계어)로 바이트 코드를 변환 시켜야 한다

기계어는 CPU가 사용하는 명령어 집합이다 이 명령어 집합은 각 CPU 제조사 마다 다르다(명령어 집합을 공유 하기도 한다) 또한 기계어는 0과 1로 이루어진 바이너리 코드이다

이는 동일한 동작을 하는 어떠한 명령어가 A 제조사에서는 1010 1010으로 나열 되어있지만, B 제조사에서는 0101 0101로 나열 될 수도 있다는 말이다

그렇다면 결국 각각의 CPU에 맞는 명렁어 집합을 알아야 한다는 말인가?

그렇지 않다 이 문제를 JVM이 해결해 준다
JVM이 바이트 코드를 이해한 후 다시 CPU에서 이해할 수 있는 바이너리 코드로 변환해 주는 것이다

JVM 덕분에 자바가 플랫폼에 종속적이다는 특징을 가지게 된것이다
여기서 플랫폼은 어떠한 목적을 수행할 수 있는 환경을 말한다

JVM의 역할과 구성요소

바이트 코드에 대해 공부하면서 JVM에 대해 간략하게 알아 보았지만 JVM의 역할과 구성요소에 대해 다시 정리하려 한다

JVM은 Java Virtual Machine의 약자이며 JVM의 역할은, 고수준의 언어(사람이 이해 할 수 있는 언어)인 자바 파일을 바이트 코드(컴파일러로 만들어진 결과)로서 읽어들여 OS간에 구애를 받지 않어떤 OS 이건 실행이 가능하게 해주는 역할을 한다

JVM은 크게 3가지로 구성되어 있다

  • Class Loader
  • Execution Engine
  • Runtime Data Area

Class Loader

.java 파일은 javac 컴파일러에 의해 .class(바이트 코드) 파일로 변환되는데 .class 파일을 메모리에 로드하는 역할을 한다

Execution Engine(JIT, Interpretor, GC)

클래스로더는 런타임 데이터 영역에 바이트코드를 배치시키고 이 바이트코드를 기계어로서의 명령으로 실행시키는 역할을 실행엔진이 수행 한다
실행엔진이 명령을 실행시키는 방식으로는 인터프리터 방식과 JIT 컴파일 방식이 있다

그 전에 코드를 컴파일 하는 방식 2가지에 대해 알아본다

인터프리터(interpretor) 방식

인터프리터 방식은 프로그램을 실행할 때 마다 컴퓨터가 읽을 수 있는 언어로 변환하는 방식을 의미한다
프로그램 실행시 마다 변환 작업을 수행하기 때문에 간편하지만 성능이 느리다

정적 컴파일 방식

정적 컴파일 방식은 프로그램을 실행하기 전 컴퓨터가 읽을 수 있는 언어로 미리 코드를 변환하는 방식이다
변환 작업이 실행 전 한번만 이루어 지기 때문에 반복적인 코드를 실행할때 인터프리터 방식보다 강점을 보인다

JIT 컴파일러

JIT은 Just-In-Time의 약자이며, 쉽게 말해 동적 변환 이라고 보면 된다
또한 JIT 컴파일러의 역할은 컴파일된 바이트코드(class파일)를 컴퓨터가 읽을 수 있게 기계코드로 변환해 주는 작업을 한다

JIT 컴파일러는 인터프리터 방식과 정적 컴파일 방식을 혼합한 방식이라고 보면 된다
인터프리터가 지속적으로 프로그램을 실행할 때마다 변환 작업을 진행하며, 코드의 정보는 캐시(메모리)에 담아두었다가 다시 프로그램을 실행할 때 불러온다

JIT는 반복적인 코드를 사용함에 있어서 좋은 성능을 보이지만 처음 코드를 실행할때에 변환 단계를 거쳐야 하기 때문에 처음 부분에서는 성능이 느리다는 단점이 있다

GC(Garbage Collector)

C언어를 사용하여 개발할때는 메모리를 사용하면 반드시 메모리 해제 작업을 해줘야한다 하지만

자바는 C언어와는 다르게 JVM에서 자동으로 메모리 관리를 해주는데 이때 메모리 관리 해주는것을 가비지 컬렉터 라고 한다

가비지는 무엇일까?
코드가 실행되고, 객체가 만들어지게 되면 메모리를 사용한다 그리고 이 코드가 종료되고 만들어진 객체가 더 이상 쓰이지 않을때 이것을 가비지(쓰레기)라고 부른다 이 쓰레기를 효과적으로 처리하는 방법(알고리즘)이 GC인 것이다(GC는 다른말로 메모리를 관리하는 알고리즘 이라고도 한다)

Runtime Data Area

https://www.kdata.or.kr/info/info_04_view.html?field=&keyword=&type=techreport&page=19&dbnum=183668&mode=detail&type=techreport

프로그램을 실행하기 위해 운영체제로 부터 할당 받은 공간이다
런타임 데이터 영역은 5가지 영역으로 나뉜다

PC(Program Counter) Register

스레드가 시작될때마다 생성된다 스레드 각각 pc register를 갖으며 현재 수행중인 명령어의 주소를 갖는다

Java Virtual Machine Stacks

스레드 마다 각각 하나씩 존재하며 스텍 프레임이라는 구조체를 저장하는 스텍이며 스텍 프레임을 push(추가) 또는 pop(제거)하는 동작만을 수행한다

Method Area(Class Area)

JVM이 시작될때 생성된다 모든 스레드가 공유하는 영역이며 메서드 영역에는 클래스와 인터페이스에 대한 런타임 상수 풀, 필드와 메서드 정보, Static 변수, 메서드의 바이트코드 등이 저장된다

Heap

객체를 저장하는 공간이며 가비지 컬렉터의 대상이다

Native Method Stacks

자바 외의 다른 언어로 작성된 프로그램을 실행시키기 위한 영역 이다
JNI(Java Native Interface)를 통해 코드가 실행 된다

https://hongsii.github.io/2018/12/20/jvm-memory-structure/

쓰레드 하나당 pc register, Java Virtual Machine Stacks, Native Method Stacks을 갖으며
전체 쓰레드는 Heap과 Method Area를 공유한다

JRE와 JDK의 차이점

JRE는 Java Runtime Enviornment 이다 자바를 실행시키기 위한 환경이고

JDK는 Java Development Kit 자바를 개발하기 위한 환경이며 JRE를 포함하고 있다

(추가) javac 컴파일 옵션

-source, -target

예를 들어 java 11에서 컴파일한 java 파일을 java 8버전에서도 실행하게 하려면
source 옵션과 target 옵션을 사용하면 된다

javac -source 1.8 -target 1.8 Hello.java

-encoding

소스파일의 문자열 인코딩을 지정한다

javac -encoding UTF-8 Hello.java

-verbose

클래스 및 컴파일 된 소스 파일에 대한 정보가 포함 되며 그 정보를 출력한다

PS C:\Temp> C:\Java\jdk-11.0.1\bin\javac -verbose Hello2.java
[parsing started SimpleFileObject[C:\Temp\Hello2.java]]
[parsing completed 18ms]
[loading /modules/java.logging/module-info.class]
[loading /modules/jdk.security.jgss/module-info.class]
[loading /modules/java.security.sasl/module-info.class]
[loading /modules/jdk.httpserver/module-info.class]
[loading /modules/jdk.accessibility/module-info.class]
[loading /modules/jdk.crypto.cryptoki/module-info.class]
[loading /modules/java.xml/module-info.class]
[loading /modules/jdk.sctp/module-info.class]
[loading /modules/jdk.internal.jvmstat/module-info.class]
[loading /modules/jdk.internal.vm.compiler/module-info.class]
[loading /modules/jdk.jdi/module-info.class]
[loading /modules/java.net.http/module-info.class]
[loading /modules/jdk.javadoc/module-info.class]
[loading /modules/jdk.internal.vm.compiler.management/module-info.class]
[loading /modules/jdk.compiler/module-info.class]
[loading /modules/jdk.internal.le/module-info.class]
[loading /modules/jdk.aot/module-info.class]
[loading /modules/java.security.jgss/module-info.class]
[loading /modules/jdk.dynalink/module-info.class]
[loading /modules/jdk.jdwp.agent/module-info.class]
[loading /modules/jdk.jconsole/module-info.class]
[loading /modules/jdk.jfr/module-info.class]
[loading /modules/java.management.rmi/module-info.class]
[loading /modules/jdk.jstatd/module-info.class]
[loading /modules/jdk.internal.ed/module-info.class]
[loading /modules/java.datatransfer/module-info.class]
[loading /modules/java.desktop/module-info.class]
[loading /modules/java.smartcardio/module-info.class]
[loading /modules/jdk.jlink/module-info.class]
[loading /modules/jdk.jcmd/module-info.class]
[loading /modules/jdk.security.auth/module-info.class]
[loading /modules/java.compiler/module-info.class]
[loading /modules/jdk.management/module-info.class]
[loading /modules/jdk.scripting.nashorn.shell/module-info.class]
[loading /modules/jdk.xml.dom/module-info.class]
[loading /modules/jdk.management.agent/module-info.class]
[loading /modules/jdk.editpad/module-info.class]
[loading /modules/jdk.net/module-info.class]
[loading /modules/jdk.management.jfr/module-info.class]
[loading /modules/java.scripting/module-info.class]
[loading /modules/jdk.jshell/module-info.class]
[loading /modules/java.base/module-info.class]
[loading /modules/jdk.hotspot.agent/module-info.class]
[loading /modules/jdk.scripting.nashorn/module-info.class]
[loading /modules/jdk.jdeps/module-info.class]
[loading /modules/java.prefs/module-info.class]
[loading /modules/java.naming/module-info.class]
[loading /modules/jdk.internal.opt/module-info.class]
[loading /modules/jdk.localedata/module-info.class]
[loading /modules/jdk.charsets/module-info.class]
[loading /modules/jdk.rmic/module-info.class]
[loading /modules/jdk.zipfs/module-info.class]
[loading /modules/jdk.jartool/module-info.class]
[loading /modules/jdk.naming.rmi/module-info.class]
[loading /modules/java.instrument/module-info.class]
[loading /modules/jdk.internal.vm.ci/module-info.class]
[loading /modules/java.rmi/module-info.class]
[loading /modules/java.xml.crypto/module-info.class]
[loading /modules/java.sql.rowset/module-info.class]
[loading /modules/java.management/module-info.class]
[loading /modules/jdk.pack/module-info.class]
[loading /modules/java.transaction.xa/module-info.class]
[loading /modules/jdk.unsupported.desktop/module-info.class]
[loading /modules/jdk.unsupported/module-info.class]
[loading /modules/jdk.naming.dns/module-info.class]
[loading /modules/jdk.crypto.ec/module-info.class]
[loading /modules/jdk.attach/module-info.class]
[loading /modules/java.sql/module-info.class]
[loading /modules/java.se/module-info.class]
[loading /modules/jdk.crypto.mscapi/module-info.class]
[loading /modules/jdk.jsobject/module-info.class]
[search path for source files: .]
[search path for class files: C:\Java\jdk-11.0.1\lib\modules,.]
[loading /modules/java.base/java/lang/Object.class]
[loading /modules/java.base/java/lang/String.class]
[loading /modules/java.base/java/lang/Deprecated.class]
[loading /modules/java.base/java/lang/annotation/Retention.class]
[loading /modules/java.base/java/lang/annotation/RetentionPolicy.class]
[loading /modules/java.base/java/lang/annotation/Target.class]
[loading /modules/java.base/java/lang/annotation/ElementType.class]
[checking Hello2]
[loading /modules/java.base/java/io/Serializable.class]
[loading /modules/java.base/java/lang/AutoCloseable.class]
[loading /modules/java.base/java/lang/System.class]
[loading /modules/java.base/java/io/PrintStream.class]
[loading /modules/java.base/java/lang/Appendable.class]
[loading /modules/java.base/java/io/Closeable.class]
[loading /modules/java.base/java/io/FilterOutputStream.class]
[loading /modules/java.base/java/io/OutputStream.class]
[loading /modules/java.base/java/io/Flushable.class]
[loading /modules/java.base/java/lang/Comparable.class]
[loading /modules/java.base/java/lang/CharSequence.class]
[wrote Hello2.class]
[total 302ms]

0개의 댓글