주제
자바 메모리 영역, 자바는 Call By Value일까, Call By Reference 일까?
목차
- 전반적인 자바의 메모리 할당 및 실행 과정
- 각 메모리 영역 역할
- call by value 메모리 할당 그림까지 꼭 그리기 [Java] Java는 Call by reference가 없다
내용
- 전반적인 자바의 메모리 할당 및 실행 과정
- 각 메모리 영역 역할
- 메모리
- 😒메모리구조를 공부하는 이유
- 같은 기능의 프로그램이더라도 메모리 관리에 따라 성능이 좌우됨.
- 메모리 관리가 되지 않은 경우 속도저하 현상이나 튕김 현상 등이 일어날 수 있음
- 한정된 메모리를 효율적으로 사용하여 최고의 성능을 내기 위함.
- JVM은 Java Virtual Machine의 약자로, 자바 가상 머신이라고 불리운다.
- 자바와 운영체제 사이에서 중개자 역할을 수행하며, 자바가 운영체제에 구애 받지 않고 프로그램을 실행할 수 있도록 도와줌(
Write Once Run AnyWay
) - 가비지 컬렉터를 사용한 메모리 관리도 자동으로 수행하며, 다른 하드웨어와 다르게 레지스터 기반이 아닌 스택 기반으로 동작함.
- 사용자가 생성한 클래스 코드의 문법을 체크한다.
- 사용자가 생성한 클래스 코드에 컴파일러가 추가적으로 필요한 코드와 새로운 문법 코드를 삽입한다.
- java.lang package의 import 기능 등 사용된 클래스들의 전체 패키지 경로를 식별
- 상속이 없으면 object 기본 상속
- 생성자가 없으면 기본생성자 삽입
- 모든 메서드(생성자포함)에 첫번째 매개변수 this 추가
- interface 라면 메소드에 public abstract 처리
- Java 최신 버전의 문법 코드로 변경
- 기본적인 최적화 작업을 수행
- bytecode로 변환
- 자바 컴파일러에 의해 자바 소스 파일은 바이트 코드로 변환됩니다.
- 이러한 바이트 코드를 JVM에서 읽어 들인 다음에, 우리가 자세히 다룰 예정인 과정들을 거쳐서 어떤 운영체제든간에 프로그램을 실행할 수 있도록 만든다.
- 한편으로는 JVM은 운영체제에 종속적이라는 특징을 알 수 있음.
- JVM은 크게 3부분으로 나눌 수 있다.
- 클래스 파일을 로딩한 뒤 검증하고 초기화하는 Class loader subSystem, 클래스 파일을 저장하는 Runtime DataArea( 5가지 영역으로 나누어진다) , 클래스 파일(바이트코드)를 플랫폼에 맞는 기계어로 변환시켜 실행하는 Execution engine 이다.
- Class Loader
- JVM 내로 클래스 파일을 로드하고, 링크를 통해 배치하는 작업을 수행하는 모듈입니다. 런타임 시에 동적으로 클래스를 로드함.
- Runtime 시 동적으로 클래스를 로드(적재)한다.
- jar 파일 내 저장된 클래스들을 jvm위에 탑재하고 사용하지 않는 클래스들은 메모리에서 삭제함. (동적 로딩)
로드 타임 동적 로딩
: 하나의 클래스를 로딩하는 과정에서 필요한 다른 클래스를 동적으로 로딩하는 것런타임 동적 로딩
: 코드를 실행하는 순간에 필요한 클래스를 로딩하는 것- 자바는 컴파일 타임이 아니라 런타임에 참조한다!!!
- 즉 클래스를 처음으로 참조할 때, 해당 클래스를 로드하고 링크한다.
- 해당 역할을 로드가 수행한다.
- Execution Engine
- 클래스 로더를 통해 JVM 내의 Runtime Data Area에 배치된 바이트 코드들을 명렁어 단위로 읽어서 실행.
- 최초 JVM이 나왔을 당시에는 인터프리터 방식이었기때문에 속도가 느리다는 단점이 있었지만 JIT 컴파일러 방식을 통해 이 점을 보완하였습니다.
- JIT는 바이트 코드를 어셈블러 같은 네이티브 코드로 바꿈으로써 실행이 빠르지만 역시 변환하는데 비용이 발생하였습니다.
- 이 같은 이유로 JVM은 모든 코드를 JIT 컴파일러 방식으로 실행하지 않고, 인터프리터 방식을 사용하다가 일정한 기준이 넘어가면 JIT 컴파일러 방식으로 실행합니다.
- Garbage Collector
- Garbage Collector(GC)는 힙 메모리 영역에 생성된 객체들 중에서 참조되지 않은 객체들을 탐색 후 제거하는 역할을 함
- 이때, GC가 역할을 하는 시간은 언제인지 정확히 알 수 없습니다.
- Runtime Data Area
- JVM의 메모리 영역으로 자바 애플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역.
- 모든 쓰레드가 공유하는 메모리 영역
- 메소드 영역은 클래스, 인터페이스, 메소드, 필드, Static 변수 등의 바이트 코드를 보관.
- 클래스 정보를 처음 메모리 공간에 올리 떄 초기화되는 대상을 저장하기 위한 메모리 공간
- 올라가는 메소드의 바이트 코드는 프로그램의 흐름을 구성하는 바이트 코드들이 적재되어 있다.(main 메소드의 호출에서부터 계속된 메소드의 호출로 흐름을 이어가기 때문)
- 대부분의 인스턴스의 생성도 메소드 내에서 명령하고 호출(생성자도 메소드임)
- 전반적으로 대부분이 메소드 바이트 코드들로 이루어져 있기 때문에 거의 모든 바이트코드가 올라간다고 봐도 무방하다
- Runtime Constant Pool이라는 별도의 관리 영영도 함께 존재하며 이는 상수 자료형을 저장하고 참조하여 중복을 막아 불필요한 메모리 생성을 피할 수 있게 됨.
- 모든 쓰레드가 공유하며, new 키워드로 생성된 객체와 배열이 생성되는 영역입니다. 또한, 메소드 영역에 로드된 클래스만 생성이 가능하고 Garbage Collector가 참조되지 않는 메모리를 확인하고 제거하는 영역.
- Permanent Generation- 생성된 객체들의 정보의 주소 값이 저장된 공간
- New Area- Eden : 객체들이 최초로 생성되는 공간- Survivor : Eden에서 참조되는 객체들이 저장되는 공간
- Old Area : New Area에서 일정시간이상 참조되고 있는 객체들이 저장되는 공간
- 메서드 호출 시마다 각각의 스택 프레임(그 메서드만을 위한 공간)이 생성함.
- 메서드 안에서 사용되는 값들을 저장하고, 호출된 메서드의 매개변수, 지역변수, 리턴 값 및 연산 시 일어나는 값들을 임시로 저장한다. 그리고, 메서드 수행이 끝나면 프레임별로 삭제.
- 쓰레드가 시작될 때 생성되며, 생성될 때마다 생성되는 공간으로 쓰레드마다 하나씩 존재.
- 쓰레드가 어떤 부분을 무슨 명령으로 실행해야할 지에 대한 기록을 하는 부분으로 현재 수행중인 JVM 명령의 주소를 갖는다.
- 자바 외 언어로 작성된 네이티브 코드를 위한 메모리 영역.
- 모든 C/C++ 바이너리(JVM뿐만 아니라)는 CPU에서 직접 실행됩니다. 일단 실행되면 이러한 프로그램은 운영 체제에서 제공하는 더 많은 기계어 코드를 호출하여 파일 읽기, 스레드 시작 또는 네트워크 사용과 같은 유용한 작업을 수행할 수 있습니다.
- JVM은 Java 프로그램을 CPU에서 실행되는 명령으로 변환합니다. 그러나 배후에서 Java의 스레드, 파일 I/O 및 네트워크 소켓(몇 가지만 들자면)에는 모두 스레드/파일 등에 대해 운영 체제에서 제공하는 코드를 호출하는 명령이 포함되어 있습니다. 이것이 여전히 OS가 필요한 이유 중 하나입니다. JVM은 JIT 컴파일러에서 얻을 수 없는 기능을 제공합니다. 하루가 끝나면 JVM은 많은 기계 코드를 실행하지만 모든 기계 코드가 JIT(또는 인터프리터)에서 나오는 것은 아닙니다. 예를 들어 그 기계어 코드 중 일부는 가비지 수집을 수행합니다. 이것이 JVM이 필요한 이유입니다.
- JVM은 Java 프로그램을 CPU에서 실행되는 명령으로 변환합니다. 그러나 배후에서 Java의 스레드, 파일 I/O 및 네트워크 소켓(몇 가지만 들자면)에는 모두 스레드/파일 등에 대해 운영 체제에서 제공하는 코드를 호출하는 명령이 포함되어 있습니다. 이것이 여전히 OS가 필요한 이유 중 하나입니다. JVM은 JIT 컴파일러에서 얻을 수 없는 기능을 제공합니다. 하루가 끝나면 JVM은 많은 기계 코드를 실행하지만 모든 기계 코드가 JIT(또는 인터프리터)에서 나오는 것은 아닙니다. 예를 들어 그 기계어 코드 중 일부는 가비지 수집을 수행합니다. 이것이 JVM이 필요한 이유입니다.
background
프로그램을 실행하기 위한 데이터 및 명령어를 저장하는 공간
jvm 메모리 정리
전반적인 실행단계

compiler
컴파일러(javac.exe)는 무엇을 하는가?
예를 들어 자바 소스 파일은 리눅스에서 만들었고 윈도우에서 이 파일을 실행하고 싶다면, 윈도우용 JVM만을 설치한다면 어떤 곳이든 우리가 작성한 프로그램이 동작할 수 있는 특징을 가지고 있다.
(Every AnyWhere)
다른 프로그램과의 실행 구조 차이

jvm 내부 구조

상세하게 보기

전체 흐름 재정리
프로그램이 실행되면, JVM은 OS으로부터 이 프로그램이 필요로 하는 메모리를 할당받고, JVM은 이 메모리를 용도에 따라 여러 영역으로 나누어 관리.
전반적인 구조 설명
동적로딩 종류
번외
해당 영역은 크게 Method Area, Heap Area, Stack Area, PC Register, Native Method Stack로 나눌 수 있습니다.
(1) Method area

상세 화면

(2). Heap area

구조 한눈에 파악하기
(3). Stack area
(4). PC Register
(5). Native method stack
한눈으로 보기

jvm의 객체 소멸 대상 찾기 원리
왜 jvm이 필요할까?
- call by value 메모리 할당 그림까지 꼭 그리기 [Java] Java는 Call by reference가 없다
public class A { public int value; public A(int i) { this.value = i; } }` `public class Test2 { public static void main(String[] args) { A a1 = new A(1); A a2 = new A(2); run(a1, a2); System.out.println(a1.value); // 111 System.out.println(a2.value); // 2 } static void run(A arg1, A arg2){ arg1.value = 111; arg2 = arg1; } }
주소 값을 복사해서 넘기기 때문에 이는 call by value입니다. 복사된 주소 값으로 참조가 가능하니 주소 값이 가리키는 객체의 내용 변경된다.