더 자세히 보는 JVM과 메모리

cutiepazzipozzi·2023년 3월 18일
3

지식스택

목록 보기
8/35
post-thumbnail

기본형과 참조형 변수에 대해 설명하며 메모리 영역에 대한 간단한 설명을 덧붙였다. 알아 두면 좋은 기본형과 참조형!
이왕에 알게된 김에 제대로 알아보자! JVM과 메모리!

JVM(Java Virtual Machine)

= 자바 프로그램이 실행되게끔 하는 프로그램

Virtual Machine, 즉 가상 기계라는 말이 우리나라에서는 잘 쓰이는 말이 아니지만 외국에서는 컴퓨터 대신 기계라는 말을 주로 사용한다고 한다. 그래서 자바 프로그램 실행을 위한 가상 컴퓨터로 받아들이는게 좋을 거 같다.

  • 자바가 운영 체제에 구애받지 않게끔 해줌 (종속성 X)
    (JVM이 중간 매체 역할이 되어 운영 체제에 맞는 실행 파일로 바꿔줌)
    (그러나 JVM은 운영 체제에 따라 형태가 바뀌므로 종속성 O)
  • GC(Garbage Collector)를 활용해 메모리 효율적 사용

JVM의 구성

- Garbage Collector

= 이 GC가 자바가 C언어와의 큰 차이점을 지니게 하면서 개발자들에게 편리함을 끌어다주며 인기를 얻게 만든 장본인이다!
(왜냐하면 C언어에서는 자바처럼 new 연산자로 어떤 객체를 선언하면, delete를 통해 마지막에 메모리를 수동으로 지워줘야 하는데 자바는 굳이 개발자가 신경써서 지워주지 않아도 Garbage Collector가 작동해 지워줌)

  • Execution Engine 안에 존재
  • 힙 영역(주로 참조형 변수가 담기는)에서 선언만 되고 쓰이지 않은(참조되지 않은?) 객체들을 일정 시간이 지나면 알아서 삭제해주는 효율적인 친구 (메모리 낭비를 막을 수 있다는 큰 장점이 되지 않을까,,,)
  • 모든 스레드가 공유하는 메모리 영역이 GC의 대상이 됨!

=> Heap 영역에서 GC의 동작과정

  • Minor GC가 발생한 후 살아남을 때마다 객체의 Age를 증가시키는데 이것이 일정 이상이 되면 아래의 Old 영역으로 이동 = Promotion
  • 객체가 Garbage(한번도 참조되지 않은)인지 판별을 위해 reachability라는 개념을 사용하는데, 이때 유효한 참조가 있다면 reachable아니라면 un~을 붙여 구별함 = Mark 과정
  • 위에서 Mark된 객체 + 다른 unreachable 객체를 찾아 Heap에서 제거함 = Sweep

이제 힙의 구성 요소로 나눠 동작 과정을 설명하겠다.

  1. Young Generation
  • 이 영역에서 발생하는 GC = Minor GC
  • eden
    - 최초의 객체가 생성
    - 여기가 꽉 차게 되면 GC가 작동하게 됨
  • Survivor(0, 1)
    - 한 번 이상 참조되어 살아남은 객체가 이동하게 됨
    (그러나 이 중 선택된 하나의 영역으로만 계속 이동)
    - 만약 둘 중 하나가 꽉 찼다면 GC를 통해 비워내고 살아남은 객체는 다른 영역으로 이동
  1. Old Generation
  • Young보다 영역의 크기가 큼, GC도 적게 발생함 (영역이 커서 그런가?)

3. Permanent Generation
(그러나 이 친구는 Java8부터 해당 클래스에 대해 알아야 하는 모든 정보를 담는 영역에 포함되어 Native Memory 영역으로 OS에서 관리받도록 변경되었다.)

- Class Loader

= 자바 클래스를 JVM으로 동적 로드하는 자바 런타임 환경(JRE)의 일부

  • 동적인 자바는 런타임 시에 코드를 읽어오기 때문에 동적으로 클래스를 JVM과 연동시켜줘야 하는데 이 역할을 클래스 로더가 해줌!
  • 컴파일 된 자바 소스 코드는 .class 즉 바이트 코드 형태로 바뀌는데 클래스 로더가 이를 JVM Runtime Data로 옮겨줌

- Execution Engine

직역하면 알겠는데 영어로 보니까 바로 의미가 와닿지 않음 이런 한국인

  • 말 그대로 가져온 (Method Area의) 바이트 코드가 실행 엔진을 통해 코드 대로 실행됨!
  • 명령어 단위로 읽어와 실행
    (뭔가 명령어라고 하니까 어떤 뉘앙슨지 확실히 모르겠는데 아마도 그냥 우리가 작성하는 코드 그 자체를 말할듯
    ex. 문자열 뒤에 어떤 조건을 충족하면 문자열 더해주기, 배열 길이만큼 for문 반복하기 ..?)
  • 바이트 코드는 Interpreter+JIT(Just In Time) 두 가지 방식을 모두 활용
    (기존의 인터프리터 방식은 바이트 코드를 해석하고 실행하여 시간이 오래 걸려, JIT 방식을 도입했다. JIT 방식(네이티브 코드..?)은 캐시를 활용해 컴파일 하며 저장해주어 한 번에 변환하고 실행돼 성능이 좋다. 그러나 많은 비용이 발생하므로 적절히 섞어서 사용한다.

Java ByteCode

= JVM이 실행하는 명령어의 형태

  • 각각의 바이트코드는 1바이트로 구성
  • 얘를 꼭 인지하거나 이해할 필요는 없지만 컴파일러에 의해 바이트코드가 어떻게 생성되는지 정도는 이해하면 좋다!

- 메모리 구조(Runtime Data Area)

= 런타임시 저장되는 데이터이기 때문에 괄호 안의 의미와 같음

Run-Time Constant Pool

= 런타임 시 상수 정보를 저장하는 Pool

  • JVM의 static 영역으로부터 할당됨
  • 클래스나 인터페이스 생성 시 런타임 상수 풀이 JVM의 static 영역의 여분 공간보다 더 많은 메모리를 필요로 한다면, JVM은 OutOfMemoryError이라는 에러를 발생시킬 것임

1. Method Area(Static)

  • 클래스 단위의 구조체(run-time 상수 풀, 필드, 메서드, 생성자, ..)
  • JVM에서 딱 하나만 생성됨
    (=모든 스레드가 이 area를 공유)
  • heap 메서드 안에 포함된다고도 볼 수 있지만, GC의 관리를 받지 않음
  • 요청이 오면 실제 물리 메모리로 변환하여 전달
  • 런타임에 생성되고, 종료까지 유지됨

2. Heap Area

  • 모든 클래스 인스턴스+배열이 저장되는 공간
  • JVM에서 딱 하나만 생성됨
  • 3번의 Stack Area와 비교했을 때 공간이 굉장히 넓기 때문에 속도가 느림 (+동시성 문제 때문에 스레드가 안전하지 않은 문제가 발생할수도)
  • Heap의 공간은 어떤 계산에 의해 확장될수도, 불필요하다고 느끼면 줄어들 수도 있기 때문에 contiguous?? 고정적이지 않다.

3. Stack Area

  • 생성되는 스레드 마다 하나씩 생성됨
  • 지역 변수나 임시적인 결과를 가짐
  • stack은 heap 영역에서 할당되는 push/popframe에 의해서만 직접적인 조종이 가능 -> contiguous(인접한?? 뭐람)할 필요가 없다는데 다 비슷할 필요가 없다는 말인듯..?

+4. PC(Program Counter) Register

  • 스레드마다 생성됨
  • 현재 진행중인 명령어의 참조값을 가짐
    -> Java 명령어라면 주소값을, native라면 undefined

+5. Native Method Stack

  • Native Method는 자바 메서드이지만 구현이 자바 외의 다른 프로그래밍 언어(C/C++)로 쓰여진 메서드
//native code로의 접근
public class DateTimeUtils {
    public native String getSystemTime();
    // ...
}

-> 아무튼 요런 메서드가 호출/생성될 때 요 영역에 쌓임

JVM의 실행 순서

  1. 자바 코드를 작성했다. (~.java로 되어있을것임)
  2. 컴파일러(javac)를 통해 바이트 코드(.class)로 바꿔준다.
    (자바 바이트 코드라고 부르는 이유는 컴파일러에 의해 변환된 명령어 코드의 크기가 1바이트라서)
  3. 바뀐 바이트 코드를 JVM이 읽어들여 운영 체제에 맞는 실행 파일을 만들어 준다. (ex. 운영 체제 = Window, Linux, Mac 등등)
    => (클래스 로더 -> JVM Runtime Data 영역 -> 운영 체제로!)

참고

https://coding-factory.tistory.com
https://1-7171771.tistory.com/140
사진 출처
사진 출처2
사진 출처3
https://velog.io/@blackbean99/JVM-%EC%9D%98-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B5%AC%EC%A1%B0#%EC%9A%94%EC%95%BD-%EC%A7%88%EB%AC%B8
https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html
자바의 정석 2nd Edition

profile
노션에서 자라는 중 (●'◡'●)

0개의 댓글