반응형
1. JVM의 개념
( 출처: https://backendcode.tistory.com/161)
1) JVM의 개념
Java Virtual Machine, 자바 가상 머신의 약자를 따서 줄여 부르는 용어
(가상 머신이란 프로그램을 실행하기 위해 물리적 머신과 유사한 머신을 소프트웨어로 구현한 것)
2) JVM의 역할 및 기능
- 자바 애플리케이션을 클래스 로더를 통해 읽어 들여 자바 API와 함께 실행하는 것
- JVM은 Java와 OS(운영체제) 사이에서 중개자 역할을 수행하여 Java가 OS(운영체제)에 구애받지 않고 독립적으로 작동이 가능
- 가장 중요한 메모리 관리, Garbage collection(가비지 컬렉션)을 수행
3) JVM의 특징
- 컴파일된 바이트 코드를 기계가 이해할 수 있는 기계어로 변환
- 스택 기반의 가상 머신
- 메모리 관리와 GC를 수행
4) JVM 구조와 작동 원리
JVM의 큰 구조
①Class Loader, ②Runtime data Area, ③Execution Engine, ④GC
① Class Loader
- 클래스 파일을 Runtime Data Area의 메서드 영역으로 불러오는 역할
② Runtime Data Area
- 런타임 시 클래스 데이터와 같은 메타 데이터와 실제 데이터가 저장되는 곳
- 프로그램을 수행하기 위해 OS로부터 할당받은 메모리 영역 (Java 메모리 공간)
Runtime Data Area의 큰 구조
ⓐMethod Area, ⓑHeap, ⓒPC Registers, ⓓJava Stacks, ⓔNative Method Stacks
( Java는 멀티 스레드 환경으로 모든 스레드는 Heap, Method Area를 공유함)
ⓐ💾Method Area
- 클래스 정보를 처음 메모리에 올릴 때 초기화되는 대상을 저장하기 위한 영역
- 올라가는 정보들 :
Field Information 멤버 변수에 대한 정보 (이름, 타입, 접근 지정자 등)
Method Information 메서드에 대한 정보 (이름, 리턴 타입, 파라미터, 접근 지정자 등)
Type Information Class 인지 Interface 인지 혹은 Type의 속성, 이름, super class의 이름 등 - 또한 Method Area에는 상수형을 저장하고 중복을 막는 Runtime Constant Pool이 존재
ⓑ💾Heap
- ④GC(가비지 컬렉션)의 대상이 되는 영역
- 객체를 동적으로 생성하게 되면 인스턴스가 Heap 영역의 메모리에 할당된다.
- 단, 레퍼런스 변수의 경우, Heap에 인스턴스가 저장되는 것이 아닌 포인터가 저장된다.
ⓒ PC Registers
- JVM은 스택 기반의 가상 머신으로, CPU에 직접 접근하지 않고 Stack에서 주소를 뽑아서 가져옴
- 가져온 주소는 PC Register에 저장됨
- 따라서, 현재 어떤 명령을 실행해야 할 지에 대한 기록을 담당
ⓓ🏃🏻♀️Java Stacks
- 호출된 메서드의 파라미터, 지역 변수, 리턴 값 및 연산 값 등이 저장되는 영역
- 프로그램 실행 시 임시로 할당되었다가 메서드를 빠져나가게 되면 소멸되는 특성의 데이터들이 저장되는 영역
- 메서드 호출 시마다 스택에 각각의 스택 프레임이 생성되고, 수행이 끝나면 스택 포인트에서 해당 프레임을 제거
ⓔ Native Method Stacks
- Java 이외의 언어에 제공되는 Method의 정보가 저장되는 공간
- Java Native Interface를 통해 바이트 코드로 저장
- Kernel이 자체적으로 Stack을 잡아 독자적으로 프로그램을 실행시키는 영역
2. JVM이 사용하는 메모리(Memory)
- 운영체제에서 할당받은 메모리 영역(Runtime Data Area)을 세부적으로 구분해 사용함
- Method Area
- Heap Area
- Stack(JVM stack) - pop & push
- 이 외 다양한 영역들이 존재함
- 3가지 영역 외 다른 영역에 접근하는 언어 = c언어
- c언어는 기계를 제어하기 위해 사용
3. 사용 메모리 영역 (Static,Heap,Stack)
- 다른 프로그램도 마찬가지로 동작(Static,Heap,Stack) 단 ,자바처럼 가비지컬렉터가 없기 때문에 만들었으면 반드시 정리해줘야함
💾 정적영역(Static Area)
- Java에서는 메소드영역(Method Area)이라 부름
- JVM이 실행될 때 생성 , 모든 스레드가 공유하는 영역
- 클래스 파일(확장자가 XXX.class인 바이트코드)의 자바 자료형(클래스,인터페이스,나열형)을 읽어서 저장하는 메모리 영역
- 클래스파일 = 컴파일된 파일
- 자바의 자료형들이 메모리에 저장됨 : 클래스(class) , 인터페이스(Interface) , 열거형(Enum)
- 자바는 내부적으로 garbage collector가 특정시점에 실행되는데(우리도 모름), 메모리를 알아서 청소해줌
- 메모리에 이름 만들어줄 수 있음, 변수이름, 식별자, 고유한 이름으로 접근 가능
💾 힙영역 (Heap Area)
- 참조형의 데이터들 저장,no name
- 배열 및 객체가 저장되는 메모리 영역 (우리가 실제로 필요로한 값들이 저장됨)
- 여기에 생성된 배열 및 객체는 스택영역의 변수나 다른 객체의 필드에서 참조함
- 힙영역을 이용하기 위해 new연산자 사용한다!
- 힙은 이름이 없어서 메모리에 직접 접근할 수 없음 BUT 메모리에는 주소가 있기 때문에 메모리주소를 이용해 접근함
- 메모리의 이름 설정 불가능 : 참조변수 필요
- 가장 많은 메모리를 저장할 수 있음
- 자바는 내부적으로 garbage collector가 특정시점에 실행되는데(우리도 모름), 메모리를 알아서 청소해줌
- 만일 참조하는 변수나 필드가 없다면 JVM이 쓰레기로 취급하고 메모리 청소
- 자동소멸아니고, Garbage Collector가 지워줘야함
- 원하면 메모리를 할당받고, 원하면 메모리 제거 가능
int[] num = new int[] {3,4,5};
num = null;
//Garbage Collector가 특정시점에 지워줌
- 일반적으로 대부분의 값들은 힙에 저장해서 사용 - 효율적임
🏃🏻♀️ 스택영역(Stack Area)
- JVM 스택영역, call stack, 잠시 사용, push & pop
- 지역변수(기본변수 또는 참조변수)가 저장되는 메모리 영역
- 지역변수는 모두 스택영역에 만들어짐
- 기본변수 저장, 제거
- 참조변수 저장, 제거
- 기본변수는 스택 영역에 직접 값을 가지고 있지만, 참조변수는 스택 영역에 힙 영역의 객체 주소를 가짐
- 스택 영역에 변수가 생성되는 시점은 초기화될 때, 즉 최초로 변수에 값이 저장될 때임
- 스택영역에 생성된 메모리(변수)는 선언된 블럭 안에서만 존재하고 블록이 끝나면 자동 소멸
- JVM 스택은 메소드를 호출할 때마다 프레임을 추가하고 메소드가 종료되면 해당 프레임을 제거함
- 스택이 생각보다 공간이 작아서 아주 많은 값을 저장할 수 없기 때문에 더 많은 값을 저장하려고 힙메모리를 이용함 단, 힙은 이름 설정 불가능이라 주소로 접근함
- 스레드마다 하나씩 존재
- First In Last Out : FILO / 가장 먼저 들어온 데이터가 가장 나중에 나감
- push & pop : 넣기 & 빼기
4. 데이터 타입 따라JVM이 메모리에 저장하는 방법
//1.
String name = "JAVA"; //참조형 String
String hobby1 = new String("여행"); //참조형 String
String hobby2 = null; //참조형 String
//Object.toStroing을 String.toString으로 오버라이드 선언하여 주소번지가 아닌 문자열로 출력가능해짐,
//단, 참조변수 출력 시 메소드 호출 생략이 가능
System.out.println("name = " +name); //name = JAVA
System.out.println("hobby1 = "+ hobby1); //hobby1 = 여행
System.out.println("hobby2 = "+ hobby2); //hobby2 = null
//2.
int[] arr1 = new int[6]; //참조형 배열
int[] arr2 = null; //참조형 배열
int[][] doubleArr = new int[][]{ {10,20,30,40,50,60}, {70,80,90,100,110,120} }; //참조형 2차원배열
//int[][] doubleArr = new int[2][6];
//doubleArr[0] = new int[] {10,20,30,40,50,60};
//doubleArr[1] = new int[] {70,80,90,100,110,120};
System.out.println("arr1 = " +arr1); //arr1 = [I@ea30797
System.out.println("arr2 = " +arr2); //arr2 = null
System.out.println("doubleArr = "+doubleArr); //doubleArr = [[I@3f8f9dd6
for(int[] row:doubleArr) {
for(int element:row) {
System.out.print(element + " ");
}
System.out.println();
}
//0 20 30 40 50 60
//70 80 90 100 110 120
5. JVM이 메모리에 클래스를 로드하는 순서
OOP > CarApp.java
- 클래스를 로드한다.
- main을 제외한 static멤버를 초기화한다.
- 상속관계를 파악한다. (상속이 있을 경우 1~3번 반복)
- main을 수행한다.
package oop;
//1. JVM이 CarApp이라는 클래스를 [Static]메모리에 로드한다.
//2. main메소드를 제외한 static멤버를 [Static]메모리에 초기화한다.
//3. 상속관계를 파악한다. (extends Object)
//=>Object클래스를 로드한 적이 있는가?
//=>없다면 Object클래스를 [Static]메모리에 로드한다.
//=>(rt.jar에서 Object.class라는 파일을 바이트코드로 만들어서 로드한다.)
//=>참고로 Object : static멤버 없음 / 상속관계 없음
//=>Object : 클래스의 최종 아버지
public class CarApp /*extends Object*/ {
//4. 메인메서드가 [stack]메모리에 호출되면서 프로그램이 실행된다.
public static void main(String[] args) {
//5. 가장먼저, 할당연산자 new를 발견하고 Car를 위한 공간이 [Heap]영역에 할당된다.
//6. new 다음 Car를 만난다.
//=>그럼 다시 JVM이 Car클래스를 로드한 적이 있는가? 라고 묻는다.
//=>로드한 적이 없으면 Car클래스를 [stack]메모리에 로드한다.
//=>Car클래스에 대해 [1~3] 과정을 Object클래스가 로드될때까지 반복실행한다.
//7. 그리고나서 ()을 수행한다.
//=>()는 기본생성자를 가리킨다.
//=>생성자는 [Heap]영역에 할당된 Car를 위한 공간에 non-static멤버들을 초기화해준다.
Car carOne=new Car();
Car carTwo=new Car();
Car carThree=carTwo;
System.out.println("carOne = "+carOne);
System.out.println("carTwo = "+carTwo);
System.out.println("carThree = "+carThree);
carOne.setModelName("티코");
carOne.setEngineStatus(true);
carOne.setCurrentSpeed(100);
System.out.println("첫번째 자동차의 모델명 = "+carOne.getModelName());//필드값 출력
System.out.println("첫번째 자동차의 엔진상태 = "+carOne.isEngineStatus());
System.out.println("첫번째 자동차의 현재속도 = "+carOne.getCurrentSpeed());
carTwo.setModelName("싼타페");
System.out.println("두번째 자동차의 모델명 = "+carTwo.getModelName());
System.out.println("두번째 자동차의 엔진상태 = "+carTwo.isEngineStatus());
System.out.println("두번째 자동차의 현재속도 = "+carTwo.getCurrentSpeed());
carTwo.startEngine();
carTwo.speedUp(50);
carTwo.speedUp(30);
carTwo.speedDown(40);
carTwo.speedZero();
carTwo.stopEngine();
}
}
반응형
'java > java' 카테고리의 다른 글
[java] 9. @ Java 어노테이션 (3가지) (0) | 2024.04.22 |
---|---|
[java] 8. JAVA 입출력 프로그램 만들기 (0) | 2024.04.13 |
[java] 6. 배열(Array) (0) | 2024.04.11 |
[java] 5. 제어문 (선택문, 반복문, 기타제어문) (2) | 2024.04.11 |
[java] 4. 변수(Variable)와 연산자(Operator) (0) | 2024.04.11 |