본 게시글은 백기선님의 자바 라이브 스터디를 진행하기 위한 정리 자료입니다
1주차 과제: JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가.
JVM이란 무엇인가
자바 가상 머신(JVM, Java Virtual Machine)
- 자바 바이트 코드를 실행시키기 위한 가상 머신이라고 할 수 있다.
- 자바로 작성된 모든 프로그램은 JVM에서만 실행이 가능하고 자바 프로그램을 실행하기 위해서는 반드시 JVM이 있어야한다
- C 프로그램은 기계어로 컴파일하고 하드웨어 기종에 맞게 각각 컴파일 되어있어야 한다. 즉 '플랫폼에 종속적'이다. Java 같은 경우 JVM만 설치 되어있으면 기기의 기종에 상관없이 사용이 가능하며 한번만 컴파일이 가능하고 플랫폼에 독립적이다.
JVM 구성
클래스 로더 (class loader)
-
JVM 내로
.class
파일들을 load하고 로딩된 class들은 runtime data area에 배치된다. (로딩) -
자바는 동적으로 클래스를 읽어오고 프로그램이 실행 중일때 런타임에서 모든 코드들이 JVM에 연결된다 (링크)
- 클래스에 있는
static
값을 초기화한다 (초기화) -
로딩 방법에는 두가지의 로딩 방법이 있다. 런타임 동적로딩과 로드타임 동적 로딩이 있다.
-
런타임 동적 로딩(Run-time dynamic loading)
public class HelloWorld { public static void main(String[] args) { Class c = Class.forName(args[0]); } }
HelloWorld
클래스를 실행하였다고 가정하겠다.
객체를 참조하는 순간에 동적으로Loading
하는 방식이다. 위 코드에서,Class.forName(args[0])
은 파리미터로 받은(args[0]
에 해당하는 클래스를 로딩한 후에, 그 클래스에 해당하는 Class 인스턴스를 리턴하게 된다.Class.forName()
메소드가 실행되기 전까지는HelloWorld
클래스에서 어떤 클래스를 참조하는지는 알 수 없고 이것을 알려면 인자로 넘어오는args[0]
가 인수로 넘어온 후에나 알 수 있다. 이처럼 클래스를 로딩할 떄가 아닌 코드를 실행하는 순간에 클래스를 로딩하는 것을 런타임 동적 로딩이라고 한다. -
로드타임 동적 로딩(load-time dynamic loading)
public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!!!"); } }
HelloWorld
클래스를 실행하였다고 가정하겠다.
부트스트랩 클래스로더가 생성된 후에 모든 클래스가 상속 받고 있는 Object클래스를 읽어오고 그 후에 클래스로더는 명령행에서 지정한HelloWorld
클래스를 로딩하기 위해서, 컴파일된HelloWorld.class
파일을 읽는다.HelloWorld
클래스를 로딩하는 과정에서 필요한 클래스가 존재하는데 현재 예시에서는java.lang.String
과java.lang.System
클래스이다. 이 두 클래스는 HelloWorld 클래스를 읽어오는 과정에서 로드타임에 로딩이 된다.이렇게 하나의 클래스를 로딩하는 과정에서 동적으로 클래스를 로딩하는 것을 로드타임 동적 로딩이라고 한다.
간략하게 순서를 나열해보면Object Class
를 읽는다 ->HelloWorld
클래스를 Loading 하기 위해서HelloWorld.class
파일을 읽는다 -> 로딩 과정에서java.lang.String
,System Class
를 읽는다 -> 클래스를 읽어오는 과정에서 로드타임에 로딩한다
-
JIT 컴파일러(Just-In-Time compiler)
- 바이트 코드에서 반복되는 코드 부분은 JIT 컴파일러가 미리 네이티브 코드로 변환 시켜 놓는다
- 반복되는 코드가 읽힐 때 인터프리터로 읽지 않고 바로 네이티브 코드로 변환 시켜 놓는다
- 인터프리터의 단점인 속도 효율성을 보완하기 위해 도입이 되었다
- 프로그램이 실행 중인 런타임에 실제 기계어로 변환해주는 컴파일러를 의미한다
- 동적 번역(dynamic translation)이라고 불리는 이 기법은 프로그램의 실행 속도를 향상시키기 위해 개발되었다
- 동적 번역 - 일부만 컴파일
- 자바 컴파일러가 생성한 자바 바이트 코드를 런타임에 바로 기계어로 변환하는데 사용한다
가비지 컬렉터(garbage collector)
- 더이상 사용하지 않는 메모리를 자동으로 회수한다
- 필요에 따라서 성능 효율을 높이기 위해 커스터 마이징을 하여 사용이 가능하다
Runtime Data Area
- 메모리 영역을 목적에 따라 5개로 나눌 수 있다.
- Method Area
- Class 정보, 변수 정보, Method 정보, static 변수 정보, final 정보등 저장 되는 영역이다
- 모든 쓰레드에게 공유
- Heap Area
- new 명령어로 생성된 인스턴스와 객체들이 저장되는 구역이고 공간이 부족해지면 GC(Garbage Collection)이 실행되어 메모리 공간을 정리해준다.
- 모든 쓰레드에 공유
- Stack Area
- Method 안에서 사용되는 값들인 매개변수, 지역변수, 리턴값 등이 저장되는 구역 메소드가 호출될 때 push되고 메소드가 실행되어 완료되면 pop으로 지워진다
- 각 쓰레드마다 하나씩 생성
- JVM Stack
- Stack Frame을 저장하는 스택이다. JVM은 Stack Frame을 push하고 pop하는 작업을 한다.
- PC Register
- 각 쓰레드마다 하나씩 생성되고 현재 수행 중인 JVM 명령의 주소값이 저장된다.
- Native Method Stack
- Java 언에 이외의 다른언어의(C, C++) 메소드 호출을 위해 할당되는 언어에 맞게 Stack이 형성되는 구역이다.
- 각 쓰레드마다 하나씩 생성
컴파일 하는 방법
-
컴파일이란
- 고급 프로그래밍 언어에서 쓰여진 프로그램으로 소스코드에서 오브젝트로 변환 되는 것이다
-
컴파일러, 인터프리터
- 고레벨 언어를 저레벨언어로 변경하기 위해 필요한 장치 또는 도구이다
-
컴파일러는 전체소스코드를 보고 명령어를 수집하고 재구성
- 컴파일러는 고레벨언어를 바로 기계어로 변환한다.
-
인터프리터는 소스코드의 각 행을 연속적으로 분석하며 실행한다.
- 고레벨 언어를 바로 기계어로 변는 것이 아닌 중간형태로 변환 한다음 실행한다.
인터프리터의 특성 4가지
- 컴파일러는 소스코드 전체를 한 번 훑고 컴퓨터 프로세서가 실행 할 수 있도록 바로 기계어로 변환한다.
인터프리터는 고레벨 언어를 중간 코드(intermediate code)로 변환하고 이를 각 행마다 실행한다. 이 중간 코드는 다른 프로그램에 의해 실행된다 - 일반 적으로 컴파일러가 각 행마다 실행하는 특성을 가진 인터프리터보다는 실행시간이 빠르다
- 컴파일러는 전체 소스코드를 변환한 뒤 에러를 보고하지만 인터프리터는 각 행마다 실행하는 도중 에러가 보고되면 이후 작성된 코드를 살펴보지 않는다. 이는 보안적인 관점에서 도움이 된다.
- 예를 들어 파이썬은 인터프리트 언어이고 C, C++는 컴파일러 언어이다. 자바는 컴파일러와 인터프리터 모두 사용한다
자바 컴파일러와 인터프리터의 차이
자바 컴파일러는 .java
파일을 javac(java compiler)
가 바이트코드로 쓰여진 .class 파일로 변환한다.
컴파일러는 JVM을 위해 기계어로 변환을한다.
JDK의 컴파일 설명
파일명 | 역할 | 설명 |
javac.exe | 컴파일러 | 자바소스코드를 바이트코드로 컴파일 |
java.exe | 인터프리터 | 컴파일러가 생성한 바이트 코드를 해석하고 실행 |
javap.exe | 역어셈블러 | 컴파일된 클래스파일을 원래의 소스로 변환 |
jar.exe | 압축프로그램 | 클래스파일과 프로그램과 프로그램의 실행에 관련된 파일을 하나의 jar파일(.jar)로 압축/해제 |
실행하는 방법
cmd 창에서 간단하게 컴파일 과정을 확인하기 위해
text로 HelloWorld.java
을 만든다.
HelloWorld.java 자바소스파일 생성
public class HelloWorld {
public static void main (String[] agrs) {
System.out.println("Hello World");
}
}
HelloWorld.java > HelloWorld.class (바이트코드로 컴파일)
C:\javaTest>javac HelloWorld.java
- ! javac.exe: 자바소스코드를 바이트코드로 컴파일
자바소스파일인 HelloWorld.java
을 자바 바이트코드로 컴파일 해서 HelloWorld.class
만들어짐
HelloWorld.class 파일 실행
jre에서 실행을 담당하는 파일로 아래와 같이 실행을 하면 우리가 작성한 자바소스코드 Hello World가 찍힌다.
C:\javaTest>java HelloWorld.java
Hello World
! java.exe: 컴파일러가 생성한 바이트코드를 해석하고 실행
컴파일된 HelloWorld.class 원래의 소스로 변환
C:\javaTest>javap HelloWorld.class
! javap.exe: 컴파일된 클래스파일을 원래의 소스로 변환
자바 바이트 코드(Java bytecode)란
JVM이 이해할 수 있는 언어로 변환된 자바 소스 코드를 의미이다.
자바 컴파일러에 의해 변환되는 코드의 명령어 크기가 1바이트라서 자바 바이트 코드라고 불리고 있다.
JDK와 JRE의 차이
JDK(자바 개발 도구 ,Java Development Kit)
- JRE 의 상위 집합이고 JRE에 있는 모든 항목과 개발 툴이 추가된 것이다
JRE(자바 실행 환경, Java Runtime Environment)
- JVM이 자바 프로그램을 동작 시킬 때 필요한 라이브러리이며 JVM 및 기타 구성 요소를 제공합니다.
'스터디 > LiveStudy' 카테고리의 다른 글
7주차 과제: 패키지 (0) | 2020.12.30 |
---|---|
6주차 과제: 상속 (0) | 2020.12.21 |
5주차 과제: 클래스 (0) | 2020.12.19 |
4주차 과제: 제어문 (0) | 2020.12.09 |
2주차 자바 데이터 타입, 변수 그리고 배열 (0) | 2020.11.20 |