* 제가 개발을 하면서 알고있었지만 잊어버렸던, 잘못알았던 지식들을 바로잡기 위해 JAVA에 대한 게시글을 작성하는 것이며 잘못된 내용이 있을경우 댓글로 피드백 주시면 감사합니다.
자바를 통해서 개발하기 위해서는 JDK, JRE에 대해서 많이 들어보셨을텐데요.
JDK, JRE가 대체 왜 필요하지라는 의문을 가져보신 분들이 계실겁니다.
이번장에서는 JDK, JRE 그리고 더 나아가 JVM에 대해서 알아보도록 하겠습니다.
JRE(Java Rumtime Environment)
JRE는 JVM과 JVM이 자바 프로그램을 실행시키기 위한 필수 라이브러리들을 가지고 있습니다. 즉 JRE가 설치되어 있어야 자바로 개발된 프로그램들을 실행할 수 있습니다.
JDK(Java Development Kit)
JDK는 자바 프로그램을 개발하기 위해 필요한 도구들(자바 컴파일러 등)와 JRE를 포함합니다. 자바라는 언어를 통해 개발하기 위해서는 반드시 필요합니다.
JVM(Java Virtual Machine)
JVM은 바이트코드를 실행할 수 있는 주체라고 위키백과에 명시되어있습니다.
이게 무슨뜻인지 이해가 가지 않으실텐데요. 이해를 하기 위해서는 우선적으로 JVM의 구조를 살펴봐야합니다.
JVM의 구조를 살펴보면 ClassLoader, Memory, Execution Engine, JNI, NativeMethodLibrary로 구성되어 있습니다.
여기서 JVM의 구조를 하나하나 살펴보겠습니다.
ClassLoader
개발자가 작성한 소스파일은 자바 컴파일러에 의해 바이트코드로 변환합니다(확장자 .java -> .class)
ClassLoader는 로딩, 링커, 초기화라는 과정을 거쳐 바이트코드를 읽어 메모리 공간을 할당합니다.
로딩 : bootstrap ClassLoader, Platform ClassLoader, Application ClassLoader로 구성되어 있으며 각 단계별로 로딩할 수 있는 클래스가 다릅니다. bootstrap ClassLoader, Platform ClassLoader, Application ClassLoader 순으로 실행되며 Application ClassLoader에서 로딩할 수 없다면 ClassNotFound Exception을 발생시킵니다.
링커 : 변환된 바이트코드가 자바문법을 따르는지 검증하는 단계이며, 클래스에 정의된 클래스정보들을 로딩하는 단계입니다.
클래스의 ClassType의 인스턴스가 Heap 메모리 영역에 할당됩니다.ex) MyCustomer.class를 사용할 수 있는 이유
초기화 : 정적변수 값 할당, 정적 블록이 실행되는 단계입니다.
ClassLoader 로딩 방식에는 런타임 로딩, 로드타임 로딩이 존재합니다.
* 런타임 로딩 : 실행하는 프로그램에서 정의된 클래스가 사용될 때 로딩되는 것
* 로드타임 로딩 : 런타임 로딩에 의해 A라는 클래스가 로딩될 때 A라는 클래스 안에 B, C, D 클래스를 참조하고 있다면 B, C, D 클래스가 로딩되는 것
즉, JVM은 모든 클래스 파일들을 한번에 로딩하지 않으며 요청되는 순간 로딩합니다.
다음은 정말로 ClassLoader가 런타임 로딩으로 클래스를 로딩하는지 확인하는 코드입니다.
SingleTon 객체
public class SingleTon {
public SingleTon() {
System.out.println("SingleTon 생성자 호출");
}
}
SingleTon을 생성하는 객체
public class SingleTonTest2 {
private static SingleTon instacne = new SingleTon();
public static SingleTon getInstance() {
return instacne;
}
public static void getText() {
System.out.println("텍스트 호출");
}
}
main 함수
public static void main(String[] args)
{
System.out.println("메인함수 실행");
System.out.println("메인함수 종료");
}
실행결과
SingleTonTest2 객체에서 SingleTon 객체는 static으로 선언하였지만 클래스를 직접 사용하지 않아 생성자가 호출되지 않았음을 알수 있습니다.
이번에는 SingleTon 객체를 사용하는 방식으로 코드를 수정해보겠습니다.
수정된 main 함수
public static void main(String[] args)
{
System.out.println("메인함수 실행");
SingleTonTest2.getInstance();
System.out.println("메인함수 종료");
}
실행결과
SingleTon 클래스의 메소드를 호출할 때 즉, 요청하는 순간에 ClassLoader에 의해 메모리가 할당되는 것을 알수 있습니다.
Memory
크게 Stack, Native Method Area, PC Registers, Heap, Meathod Area로 구성되어 있으며 Heap, Method Area 영역은 모든 스레드가 공유하는 반면 Stack, Natvie Method Area, PC Registers 영역은 각 스레드 별로 할당되며 사용합니다.
Heap : 객체가 생성되면 할당되는 공간
Method Area : 클래스의 정보들이 저장되어 있는 공간, static 변수, 메소드, 클래스들이 저장되어있습니다.
Stack : 함수가 호출 될 때 함수 내 지역변수, 매개변수, 리턴, 임시값이 할당되는 공간
Native Method Area : C, C++언어로 개발된 함수가 JNI에 의해 호출될 때 사용되는 공간
PC Registers : 스레드를 실행시키기 위한 정보들이 포함되어 있는 공간?
Execution Engine
인터프리터, JIT 컴파일러, GC으로 구성되어 있습니다.
인터프리터 : 바이트코드를 한 라인씩 읽어 OS Native Code로 변환합니다.
JIT(Just In Time)컴파일러 : 바이트코드를 한 라인씩 읽으면 성능상 문제가 생길 수 있습니다. 효율적으로 읽어 들이기 위해 반복되는 바이트 코드들을 OS Native Code로 변환한 후 인터프리터가 반복되는 바이트코드를 읽을때 전달해주는 방식으로 인터프리터의 효율을 높이기 위해 사용됩니다.
GC : 자동으로 메모리 관리를 해주는 가비지컬렉터입니다.
참조
'JAVA' 카테고리의 다른 글
코드성 데이터를 Java Enum으로 관리하는 방법에 대한 고찰 (0) | 2021.03.06 |
---|---|
Comparable를 구현한 방식과 comparing을 구현한 방식간 성능차이 (0) | 2020.12.07 |
Rest API 호출 시 HTTP 405 Code 해결방안 (0) | 2020.12.06 |