본문 바로가기
레거시

2022.02.14 (개념 정리)

by GroovyArea 2022. 2. 15.

 개인 공부 관련

 

7. Garbage Collection(가비지 컬렉션)의 동작 방식

  • Young 영역과 Old 영역은 서로 다른 메모리 구조로 되어 있기 때문에, 세부적인 동작 방식은 다르다. 하지만 기본적으로 가비지 컬렉션이 실행된다고 하면 다음의 2가지 공통적인 단계를 따르게 된다.
  1. Stop The World : JVM이 애플리케이션의 실행을 멈추는 작업이다. GC가 실행될 때는 GC를 실행하는 쓰레드를 제외한 모든 쓰레드들의 작업이 중단된다. 당연히 모든 쓰레드들의 작업이 중단되면 애플리케이션이 멈추기 때문에, GC의 성능 개선을 위해 튜닝을 한다고 하면 보통 stop-the-world의 시간을 줄이는 작업을 하는 것이다.
  2. Mark and Sweep :
  • Mark: 사용되는 메모리와 사용되지 않는 메모리를 식별하는 작업
  • Sweep: Mark 단계에서 사용되지 않음으로 식별된 메모리를 해제하는 작업
  • Stop The World를 통해 모든 작업을 중단시키면, GC는 스택의 모든 변수 또는 Reachable 객체를 스캔하면서 각각이 어떤 객체를 참고하고 있는지를 탐색하게 된다. 그리고 사용되고 있는 메모리를 식별하는데, 이러한 과정을 Mark라고 한다. 이후에 Mark가 되지 않은 객체들을 메모리에서 제거하는데, 이러한 과정을 Sweep라고 한다.
  1. [ Minor GC의 동작 방식 ]
  • Minor GC를 정확히 이해하기 위해서는 Young 영역의 구조에 대해 이해를 해야 한다. Young 영역은 1개의 Eden 영역과 2개의 Survivor 영역, 총 3가지로 나뉘어진다.
  • Eden 영역: 새로 생성된 객체가 할당(Allocation)되는 영역
  • Survivor 영역: 최소 1번의 GC 이상 살아남은 객체가 존재하는 영역
  • 객체가 새롭게 생성되면 Young 영역 중에서도 Eden 영역에 할당(Allocation)이 된다. 그리고 Eden 영역이 꽉 차면 Minor GC가 발생하게 되는데, 사용되지 않는 메모리는 해제되고 Eden 영역에 존재하는 객체는 (사용중인) Survivor 영역으로 옮겨지게 된다. Survivor 영역은 총 2개이지만 반드시 1개의 영역에만 데이터가 존재해야 한다.
  1. 동작 순서
  • 새로 생성된 객체가 Eden 영역에 할당된다.
  • 객체가 계속 생성되어 Eden 영역이 꽉차게 되고 Minor GC가 실행된다.
    1. Eden 영역에서 사용되지 않는 객체의 메모리가 해제된다.
    2. Eden 영역에서 살아남은 객체는 1개의 Survivor 영역으로 이동된다.
  • 1~2번의 과정이 반복되다가 Survivor 영역이 가득 차게 되면 Survivor 영역의 살아남은 객체를 다른 Survivor 영역으로 이동시킨다.(1개의 Survivor 영역은 반드시 빈 상태가 된다.)
  • 이러한 과정을 반복하여 계속해서 살아남은 객체는 Old 영역으로 이동(Promotion)된다.
  • 객체의 생존 횟수를 카운트하기 위해 Minor GC에서 객체가 살아남은 횟수를 의미하는 age를 Object Header에 기록한다. 그리고 Minor GC 때 Object Header에 기록된 age를 보고 Promotion 여부를 결정한다. 또한 Survivor 영역 중 1개는 반드시 사용이 되어야 한다. 만약 두 Survivor 영역에 모두 데이터가 존재하거나, 모두 사용량이 0이라면 현재 시스템이 정상적인 상황이 아님을 파악할 수 있다.
  • 이러한 진행 과정을 그림으로 살펴보면 다음과 같다.

  1. [ Major GC의 동작 방식 ]
  • Young 영역에서 오래 살아남은 객체는 Old 영역으로 Promotion됨을 확인할 수 있었다. 그리고 Major GC는 객체들이 계속 Promotion되어 Old 영역의 메모리가 부족해지면 발생하게 된다. Young 영역은 일반적으로 Old 영역보다 크키가 작기 때문에 GC가 보통 0.5초에서 1초 사이에 끝난다. 그렇기 때문에 Minor GC는 애플리케이션에 크게 영향을 주지 않는다. 하지만 Old 영역은 Young 영역보다 크며 Young 영역을 참조할 수도 있다. 그렇기 때문에 Major GC는 일반적으로 Minor GC보다 시간이 오래걸리며, 10배 이상의 시간을 사용한다.
  1. Garbage Collection(가비지 컬렉션) 내용 요약

[ Garbage Collection(가비지 컬렉션) 내용 요약 ]

 

8. JVM의 구조

  • 자바 소스 파일은 자바 컴파일러에 의해서 바이트 코드 형태인 클래스 파일이 되고 이 클래스 파일은 클래스 로더가 읽어들이면서 JVM이 수행된다.
  1. Class Loader : JVM 내로 클래스 파일을 로드하고, 링크를 통해 배치하는 작업을 수행하는 모듈입니다. 런타임 시에 동적으로 클래스를 로드합니다.
  2. Execution Engine : 인터프리터 방식과 JIT 컴파일러가 있음. 클래스 로더를 통해 JVM 내의 Runtime Data Area에 배치된 바이트 코드들을 명렁어 단위로 읽어서 실행
  • Interpreter 방식 : 컴파일러처럼 고레벨언어를 기계어(저레벨언어)로 해석해주는 번역 프로그램, 컴파일러는 전체 소스코드를 보고 명령어를 수집하고 재구성하는 반면 인터프리터는 소스코드의 각 행을 연속적으로 분석하며 실행 ⇒ 느림
  • Jit (Just In-Time) 컴파일러 : JIT 컴파일러는 바이트 코드를 전체를 읽어 한꺼번에 변환함.
  • 모든 코드는 초기에 인터프리터에 의해 시작되고, 해당 코드를 충분히 많이 사용할 경우 JIT 컴파일러에서 컴파일을 수행. 초기에 인터프리트 방식으로 바이트 코드를 변환하면서 그 코드를 캐싱하여, 같은 함수가 여러 번 불릴 때 매번 코드가 생성되는 것을 방지함.
  • 이렇게 컴파일된 코드를 네이티브 코드 라고 하는데 네이티브 코드는 캐시에 보관되기 때문에 한번 컴파일된 코드는 빠르게 수행가능함. JIT 컴파일러는 JVM의 핵심으로 JVM 내에서 성능에 가장 큰 영향을 준다.
  1. Garbage Collector : Garbage Collector(GC)는 힙 메모리 영역에 생성된 객체들 중에서 참조되지 않은 객체들을 탐색 후 제거하는 역할. 이때, GC가 역할을 하는 시간은 언제인지 정확히 알 수 없다.
  2. Runtime Data Area : JVM의 메모리 영역으로 자바 애플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역. 이 영역은 크게 Method Area, Heap Area, Stack Area, PC Register, Native Method Stack로 나눌 수 있다.
  • 1. Method area (메소드 영역) : 클래스 멤버 변수의 이름, 데이터 타입, 접근 제어자 정보같은 필드 정보와 메소드의 이름, 리턴 타입, 파라미터, 접근 제어자 정보같은 메소드 정보, Type정보(Interface인지 class인지), Constant Pool(상수 풀 : 문자 상수, 타입, 필드, 객체 참조가 저장됨), static 변수, final class 변수등이 생성되는 영역이다.
  • 2. Heap area (힙 영역) : new 키워드로 생성된 객체와 배열이 생성되는 영역이다. 메소드 영역에 로드된 클래스만 생성이 가능하고 Garbage Collector가 참조되지 않는 메모리를 확인하고 제거하는 영역이다.
  • 3. Stack area (스택 영역)

지역 변수, 파라미터, 리턴 값, 연산에 사용되는 임시 값등이 생성되는 영역이다.

int a = 10; 이라는 소스를 작성했다면 정수값이 할당될 수 있는 메모리공간을 a라고 잡아두고 그 메모리 영역에 값이 10이 들어간다. 즉, 스택에 메모리에 이름이 a라고 붙여주고 값이 10인 메모리 공간을 만든다.

클래스 Person p = new Person(); 이라는 소스를 작성했다면 Person p는 스택 영역에 생성되고 new로 생성된 Person 클래스의 인스턴스는 힙 영역에 생성된다.

그리고 스택영역에 생성된 p의 값으로 힙 영역의 주소값을 가지고 있다. 즉, 스택 영역에 생성된 p가 힙 영역에 생성된 객체를 가리키고(참조하고) 있는 것이다.

메소드를 호출할 때마다 개별적으로 스택이 생성된다.

  • 4. PC Register (PC 레지스터)

Thread(쓰레드)가 생성될 때마다 생성되는 영역으로 Program Counter 즉, 현재 쓰레드가 실행되는 부분의 주소와 명령을 저장하고 있는 영역이다. (*CPU의 레지스터와 다름)

이것을 이용해서 쓰레드를 돌아가면서 수행할 수 있게 한다.

  • 5. Native method stack

자바 외 언어로 작성된 네이티브 코드를 위한 메모리 영역이다.

보통 C/C++등의 코드를 수행하기 위한 스택이다. (JNI)

  • 쓰레드가 생성되었을 때 기준으로 1,2번인 메소드 영역과 힙 영역을 모든 쓰레드가 공유하고, 3,4,5번인 스택 영역과 PC 레지스터, Native method stack은 각각의 쓰레드마다 생성되고 공유되지 않는다.

9. 객체지향 한줄 정리

  • 객체 지향 프로그래밍은 컴퓨터 프로그래밍 패러다임 중 하나로, 프로그래밍에서 필요한 데이터를 추상화시켜 상태와 행위를 가진 객체를 만들고 그 객체들 간의 유기적인 상호작용을 통해 로직을 구성하는 프로그래밍 방법
  1. 장점 :
  2. 코드 재사용이 용이 : 상속을 통해 확장 사용이 가능하고, 배포된 클래스를 이용 가능.
  3. 유지보수가 쉬움 : 절차식 프로그래밍에서는 코드를 수정 시 일일히 찾아 수정해야 하지만 객체 지향 프로그래밍에서는 수정해야 할 부분이 클래스 내부에 변수 혹은 메서드로 존재하기 때문에 해당 부분만 수정하면 되기 떄문이다.
  4. 대형 프로젝트에 적합 : 클래스 단위로 모듈화시켜서 개발할 수 있으므로 대형 프로젝트처럼 여러 명, 여러 회사에서 프로젝트를 개발할 때 업무 분담하기 쉽다.
  5. 단점 :
  6. ⇒ 처리 속도가 상대적으로 느림
  7. ⇒ 객체가 많으면 용량이 커질 수 있음
  8. ⇒ 설계 시 많은 시간과 노력이 필요
  • 객체지향 프로그래밍 키워드 5가지
  1. 클래스 + 인스턴스(객체) : 클래스 → 데이터를 만들기 위해 추상화를 거쳐 집단에 속하는 속성(attribute)과 행위(behavior)를 변수와 메소드로 정의한 것, 인스턴스(객체) → 클래스에서 정의한 것을 토대로 실제 메모리에 할당된 것
  2. 추상화 : 클래스를 설계하는 것 자체를 의미, 공통의 속성이나 기능을 묶어 이름을 붙이는 것. ex) 추상 클래스 같은 느낌 : 형태와 속성만 부각 시키는 것, 떡 라면, 만두 라면
  3. 캡슐화 : 캡슐화의 목적 2가지
  • ⇒ 코드를 재수정 없이 재활용 하는 것
  • ⇒ 접근 제어자를 통한 정보 은닉
  • 캡슐화를 통해 객체가 외부에 노출하지 않아야 할 정보 또는 기능을 접근 제어자를 통해 적절히 제어 권한이 있는 객체에서만 접근 가능하다.
  • 관련된 기능과 특성을 한 곳에 모으고 분류하기 때문에 객체 재활용이 원할해졌다. 기능과 특성의 모음을 “클래스”라는 “캡슐”에 분류해서 넣는 것이 캡슐화. 객체가 맡은 역할을 수행하기 위한 하나의 목적을 한데 묶는다.
  1. 상속 : 부모클래스의 속성과 기능을 그대로 이어받아 사용할 수 있게하고 기
  2. 능의 일부분을 변경해야 할 경우 상속받은 자식클래스에서 해당 기능만 다시 수정(정의)하여 사용할 수 있게 하는 것
  3. 다형성 : 하나의 변수명, 함수명 등이 상황에 따라 다른 의미로 해석될 수 있는 것
  • 오버라이딩 ****: 부모클래스의 메서드와 같은 이름, 매개변수를 재정의 하는것.
  • 오버로딩 ****: 같은 이름의 함수를 여러개 정의하고, 매개변수의 타입과 개수를 다르게 하여 매개변수에 따라 다르게 호출할 수 있게 하는 것.

10. primitive type & reference type 차이점

  1. Boxing, Unboxing
  • **Boxing(박싱)**은 원시 타입을 참조 타입으로 변환 시키는 것을 말하고, **Unboxing(언박싱)**은 참조 타입을 원시 타입으로 변환 시키는 것을 말한다.
  • 자바 1.5 이전에는 일일히 변환 과정을 거쳐주어야 했지만, 자바 1.5부터 추가된 Auto Boxing / Unboxing 기능으로 아래의 예시와 같이 명시적으로 원시타입을 참조타입으로 감싸주지 않아도 자동으로 Boxing / Unboxing 해준다. ⇒ 메모리 누수의 원인이 됨.
  1. Null 포함 가능 여부
  • 원시타입은 null을 담을 수 없지만, 참조 타입은 가능하다.
  1. 제너릭 타입에서 사용 가능 여부
  • 원시타입은 제너릭 타입에서 사용할 수 없지만, 참조 타입은 가능하다.
  1. Wrapper 클래스를 사용하는 이유
  • 기본형 변수를 객체로 다루기 위해서 (매개변수로 객체를 요구할 때, 기본형 값이 아닌 객체로 저장해야할 때, 객체간의 비교가 필요할 떄 등등)
반응형

'레거시' 카테고리의 다른 글

2022.02.16의 기록  (0) 2022.02.16
2022.02.15의 기록  (0) 2022.02.15
2022-02-14의 기록  (0) 2022.02.14
2022-02-13의 기록  (0) 2022.02.13
2022-02-11의 기록  (0) 2022.02.13