자바 스터디 - 1주차

JoongHyeok.Velog·2022년 4월 16일
0

Java

목록 보기
5/5
post-thumbnail

스터디 시작 계기

자바를 좀 더 깊숙하고 자세히 공부하기 위해 백기선님의 자바스터디 레포지토리를 참고하여 15주동안 글을 정리해나가려 합니다.

자바 스터디 1주차 링크 : https://github.com/whiteship/live-study/issues/1

1주차 과제: JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가.

목표

자바 소스 파일(.java)을 JVM으로 실행하는 과정 이해하기.

학습할 내용

JVM이란 무엇인가
컴파일 하는 방법
실행하는 방법
바이트코드란 무엇인가
JIT 컴파일러란 무엇이며 어떻게 동작하는지
JVM 구성 요소
JDK와 JRE의 차이

JVM이란 무엇인가

JVM은 'Java Virtual Machine'을 줄인 것으로 직역하면 '자바를 실행하기 위한 가상 기계'라고 할 수 있습니다.가상 기계라는 말이 좀 어색하겠지만 영어권에서는 컴퓨터를 머신이라고 부르기 때문에 '머신'이라는 용어 대신 '컴퓨터'를 사용해서 '자바를 실행하기 위한 가상 컴퓨터'라고 이해하면 좋을 것 같습니다. 가상 컴퓨터는 실제 컴퓨터(하드웨어)가 아닌 소프트웨어로 구현된 컴퓨터라는 뜻으로 컴퓨터 속의 컴퓨터라고 생각하면 될 것 같습니다.

자바로 작성된 애플리케이션은 모두 이 가상 컴퓨터(JVM)에서만 실행되기 때문에, 자바 애플리케이션이 실행되기 위해서는 반드시 JVM이 필요합니다.

일반 애플리케이션 코드는 OS만 거치고 하드웨어로 전달되는데 비해 Java 애플리케이션은 JVM으 한 번 더 거치기 때문에, 그리고 하드웨어에 맞게 완전히 컴파일된 상태가 아니고 실행 시에 해석(interpret)되기 때문에 속도가 느리다는 단점을 가지고 있다. 그러나 요즘엔 바이트코드(컴파일된 자바코드)를 하드웨어의 기계어로 변환해주는 JIT 컴파일러와 향상된 최적화 기술이 적용되어서 속도의 격차를 많이 줄였습니다.

그림에서 보시다 싶이 일반 애플리케이션은 OS와 바로 맞붙어 있기 때문에 OS종속적입니다. 그래서 다른 OS에서 실행시키기 위해서는 애플리케이션을 해당 OS에 맞게 변경해주어야 합니다. 반면에 Java 애플리케이션은 JVM하고만 상호작용을 하기 때문에 OS와 하드웨어에 독립적이라 다른 OS에서도 프로그램의 변경없이 실행이 가능합니다. 단, JVM은 OS에 종속적이기 때문에 해당 OS에서 실행가능한 JVM이 필요합니다.

그래서 썬에서는 일반적으로 많이 사용되는 주요 OS용 JVM을 제공하고 있고, 이렇게 함으로써 자바의 중요한 장점중의 하나인 "Write once, run anywhere.(한 번 작성하면 어디서든 실행된다.)"이 가능하게 되는 것 입니다.

컴파일 하는 방법

인텔리제이와 같은 개발도구를 이용하지 않고 CMD로 자바로 만든 프로그램을 컴파일하는 흐름은 다음과 같습니다.

1.COMPILE : .java 확장자가 붙은 소스코드를 class 확장자가 붙은 실행파일로 변환
2.RUN : .class 확장자가 붙은 파일을 'Java'로 실행
3.INPUT : 실행할 때, 입력값에 따라서 다르게 동작하여 출력값을 만듦

JVM 컴파일 과정
*.java 파일이 컴파일러를 통해 전달 된 소스코드를 Bytecode로 인코딩합니다.
소스파일에 포함 된 클래스의 내용은 별도의 .class 파일에 저장됩니다. 소스코드를 바이트 코드로 변환하는 동안 컴파일러는 다음 단계를 따르게 됩니다.

  • parse : *.java 소스파일을 읽은 뒤 결과 토큰을 AST(Abstract Syntax Tree)

실행하는 방법

흔히 우리가 JIT Compiler라고 부르는 Compiler는 실행중에 바이트 코드를 여러가지 다양한 테크닉을 사영하여 JVM 해석 엔진 없이 바로 수행되는 기계어 코드를 만들어 낸다. 그럼으로서 바이트코드가 가지는 장점과 기계어가 가지는 장점을 결합할 수 있다.

과정

  1. Java Compiler(javac 명령어 실행)에 의해 Java Source(.java 확장자)로부터 Byte Code(.class 확장자)가 생성된다.
  2. JVM에 있는 Class Loader에 의해 Byte Code는 JVM내로 로드되고 실행엔진에 의해 기계어로 해석되어 메모리 상(Runtime Data Area)에 배치된다.
  3. 실행엔진에는 Interpreter와 JIT(Just-In-Time) Compiler가 있는데, Interpreter에 의해 Byte Code를 한 줄씩 읽어 실행하다가 적절한 시점에 Byte Code 전체를 컴파일하고 더이상 인터프리팅하지 않고 해당 코드를 직접 실행한다.
  4. JIT Compiler에 의해 해석된 코드는 캐시에 보관하기 때문에 한 번 컴파일된 후에는 빠르게 수행할 수 있다는 장점이 있습니다. 하지만 코드 전체를 컴파일하기 때문에 인터프리팅하는 것보다 시간이 오래 걸리므로 한 번만 실행해도 되는 코드에 대해서는 인터프리팅하는 것이 유리합니다.
  • Interpreter : 자바 Byte Code를 한 줄씩 실행. 전체 성능면에서 불리.

  • JIT Compiler : 전체 Byte Code를 컴파일하고 캐시에 보관해놓고 직접 실행. 한 번만 실행해도 되는 코드에 대해서는 Interpreter가 유리.

장점

  • 생성되는 코드의 안정성
    Java가 수행중 만들어내는 기계어 코드는 안전한 공간(sandBox)안에서 돌아가기 때문에 외부 해킹에 안전
  • 동작하는 메모리 공간의 안전성
    모든 자바 객체들은 Heap이라는 독립적인 공간에서만 수행
    다른 Process 와 다른 메모리 공간을 사용하기 때문에 Stack overflow에 강함
  • 최적화 재사용에 유일한 관련 클래스간 상속구조
    메모리 위치상 가깝게 관련된 객체와 메소드들을 위치시킨다.
    method inlining 같은 성능을 높이기 위한 테크닉들이 자바에서 효율적으로 작동
  • 동적 최적화와 그것에 대한 취소, 재 최적화 가능
    static 언어와 다르게 dynamic class loading으로 어떤 방식으로든 수행중 변경 가능 compiler를 통한 최적화가 수시로 이루어 진다.

Compiler 기술들

  • Hot Spot Detection
    JVM이 ByteCode를 해석하다가 루프등을 만나 몇번이나 중복적인 해석이 이루어진다고 판단되면 Byte코드를 기계어로 직접 컴파일하는 방식
    기존의 모든 기본 코드를 수행전에 컴파일 하는 방식은 수행 자체는 빠르지만 프로그램 크기가 커지고 기기별 이식성이 떨어지기도 한다.
  • Method inlining
    클래스 안에서 사용된 다른 클래스에 대해 method inlining을 수행함으로서 다른 메모리 공간에 있는 메소드에 대해 호출하는 것을 피할 수 있다.
    이걸 취소할 수도 있다.
  • reflection
    객체를 명시적으로 코드에서 new하지 않아도 임의의 객체를 동적으로 생성하고 메소드를 호출할수 있는 reflection은 자바 동적 클래스로딩의 핵심

바이트코드란 무엇인가

자바 바이트 코드(Java bytecode)란 자바 가상 머신이 이해할 수 있는 언어로 변환된 자바 소스 코드를 의미합니다.

자바 컴파일러에 의해 변환되는 코드의 명령어 크기가 1바이트라서 자바 바이트 코드라고 불리고 있습니다.

이러한 자바 바이트 코드의 확장자는 .class입니다.

자바 바이트 코드는 자바 가상 머신만 설치되어 있으면, 어떤 운영체제에서라도 실행될 수 있습니다.

JIT 컴파일러란 무엇이며 어떻게 동작하는지

JVM 구성 요소

이미지 출처 : https://www.skyer9.pe.kr/wordpress/?p=280

자바 가상 머신(JVM)은 다음과 같이 구성됩니다.

  1. 자바 인터프리터(interpreter)

  2. 클래스 로더(class loader)

  3. JIT 컴파일러(Just-In-Time compiler)

  4. 가비지 컬렉터(garbage collector)

자바 컴파일러에 의해 변환된 자바 바이트 코드를 읽고 해석하는 역할을 하는 것이 자바 인터프리터(interpreter)입니다.

자바는 동적으로 클래스를 읽어오므로, 프로그램이 실행 중인 런타임에서야 모든 코드가 자바 가상 머신과 연결됩니다.

이렇게 동적으로 클래스를 로딩해주는 역할을 하는 것이 바로 클래스 로더(class loader)입니다.

JIT 컴파일러(Just-In-Time compiler)란 프로그램이 실행 중인 런타임에 실제 기계어로 변환해 주는 컴파일러를 의미합니다.

동적 번역(dynamic translation)이라고도 불리는 이 기법은 프로그램의 실행 속도를 향상시키기 위해 개발되었습니다.

즉, JIT 컴파일러는 자바 컴파일러가 생성한 자바 바이트 코드를 런타임에 바로 기계어로 변환하는 데 사용합니다.

자바 가상 머신은 가비지 컬렉터(garbage collector)를 이용하여 더는 사용하지 않는 메모리를 자동으로 회수해 줍니다.

따라서 개발자가 따로 메모리를 관리하지 않아도 되므로, 더욱 손쉽게 프로그래밍을 할 수 있도록 도와줍니다.

JDK와 JRE 차이

JRE

JRE는 자바 실행환경(Java Runtime Environment)의 약자이다.

JRE는 JVM 이 자바 프로그램을 동작시킬 때 필요한 라이브러리 파일들과 기타 파일들을 가지고 있다. JRE는 JVM의 실행환경을 구현했다고 할 수 있다.

JDK

JDK는 자바 개발도구(Java Development Kit)의 약자이다.

JDK는 JRE + 개발을 위해 필요한 도구(javac, java등)들을 포함한다.


참고 :

profile
영차영차

0개의 댓글