- 덕분에 운영체제에 구애받지 않고 프로그램을 실행할 수 있다.
- Class Loader : JVM 내로 클래스 파일을 로드, 링크를 통해 배치하는 작업을 수행하는 모듈, 런타임 시 동적으로 로드한다.
- Garbage Collector : 힙 메모리 영역 참조되지 않은 객체 탐색 후 제거한다.
- Execution Engine : Runtime Data Area에 배치된 바이트 코드를 명령어 단위로 읽어서 실행한다.
- 인터프리터 방식에서 JIT 컴파일러 방식으로 보완되었다.
- JIT 컴파일러는 반복되는 코드를 발견하면 바이트 코드를 어셈블리어 같은 네이티브 코드로 바꿉니다. 실행이 빠르지만 변환 비용이 비교적 크게 발생한다.
- 그러므로 JVM은 모든 코드를 JIT 컴파일러 방식으로 실행하지 않고 인터프리터 방식을 사용하다가 일정 기준이 넘어가면 JIT 컴파일러 방식으로 실행한다.
- Runtime Data Area : 자바 애플리케이션이 실행될 때 사용되는 데이터들을 적재하는 영역이다. (Method Area, Heap Area, Stack Area, PC Register, Native Method Stack)
- 메소드 영역 : 모든 스레드가 공유하며 바이트코드로 변환된 것들을 저장합니다.(클래스, 인터페이스, 메소드, 필드, static 변수 등)
- 힙 영역 : 모든 스레드가 공유하며, new 키워드로 생성된 객체와 배열이 저장되는 영역입니다. 클래스 영역에 로드된 클래스로 생성이 가능하고 GC가 참조되지 않는 메모리를 확인하고 제거합니다.
- 스택 영역 : 메소드 호출 마다 스택 프레임(그 메소드를 위한 공간)이 생성됩니다. 메소드 안에서 사용되는 값(매개변수, 지역변수, 리턴 값 연산 시 일어나는 값)을 저장하고 메소드 수행이 끝나면 프레임별로 삭제합니다.
- PC 레지스터 : 스레드가 시작될 때 생성되며, 스레드마다 하나씩 존재합니다. 스레드가 어떤 명령으로 실행해야 할 지에 대한 기록을 하는 부분으로 JVM 명령의 주소를 갖습니다.
- 네이티브 메소드 스택 영역 : 자바 외 언어로 작성된 네이티브 코드를 위한 메모리 영역입니다.
- Minor GC : young 영역, 새롭게 생성된 객체가 할당 되는 영역, 먾은 객체가 Young 영역에 생성되었다 사라집니다.
- eden 1개, survivor 2개로 구성되어 있다. eden 영역이 가득차면 survivor로 넘어가면서 실행된다.
- 크기가 작아서 GC 시간이 작다.
- Major GC : old 영역, 특정 횟수 이상을 살아남은 참조 변수가 살아있는 곳입니다.
- survivor 2번쨰까지 들렸다가 사용되면 Old 영역으로 오게된다.
- Old 영역이 가득차면 Major GC가 발생한다.
- Stop The World : GC를 수행하기 위해 JVM이 어플리케이션의 실행을 멈추는 작업을 말합니다. GC를 실행하는 스레드를 제외한 모든 스레드들의 작업이 중단되고 GC가 완료되면 작업이 재개됩니다.
- 스레드의 작업이 중단되면 어플리케이션이 멈추기 때문에 GC 성능 튜닝을 한다고 하면 이 부분의 시간을 줄이는 작업을 말합니다.
- 특히 Old 영역은 크기가 크기 때문에 Major GC 시간이 오래걸린다.
- Mark And Sweep : 모든 작업이 중단되면 GC는 스택의 모든 변수 또는 Reachable 객체(어디선가 사용하고 있는 객체, Unreachable : 아무도 사용하지 않고 자리만 차지하고 있는 객체)를 스캔하면서 각각 어떤 객체를 참조하고 있는지 탐색하게 됩니다. 그리고 사용되고 있는 메모리를 식별하고 사용되지 않는 객체를 제거합니다.
- young 영역에서는 Mark-sweep, old 영역에서는 Mark and Sweep Compact 알고리즘 사용
- compact는 Heap 영역을 정리하기 위한 단계로 유효한 객체들이 연속되게 쌓이도록 힙의 앞부터 채우게 하는 것이다.
- Mark Summary Compact 알고리즘 : Summary 단계에서 살아있는 객체를 식별한다는 점에서 조금 더 복잡하다.
- GC와 프로세서의 리소스를 공유하기 때문이다. 어플리케이션 응답이 늦어질 수 있지만 GC에 의해 어플리케이션이 정지되지 않는다.
- java14 부터 사용 중지
- Eden : 다른 GC의 Eden 역할과 같은 역할, 새로 생긴 객체들이 할당.
- Survivor : 살아있는 객체들이 할당.
- Old : 오래 살아있는 객체들이 할당.
- Humongous : Region 크기의 50%가 넘는 큰 객체들을 할당.
- Available/Unused : 아직 사용되지 않는 영역.
- Minor GC만 수행하다가 Old Generation 비율이 넘으면 Major GC 실행, 그리고 Young Only 끝날 때까지 함께 작동
- Space Reclamation 단계는 Mixed GC 방식 작동, Mixed GC 는 Minor GC 처럼 움직이고 Old 영역의 Garbage까지 수 집한다.
- Z GC 를 실행시키고 싶다면
java -XX:+UseZGC -jar Application.java
- 이름, 매개변수, 리턴타입이 같고, 메소드 내용이 달라야 한다.
- 메소드 이름이 같아야 하며, 매개변수 갯수, 타입이 달라야 한다.
- 리턴타입만 다르면 성립이 되지 않고, 매개변수와 함께 달라져야 성립된다.
- 캡슐화 : 클래스 내부 변수와 메소드를 하나로 패키징하는 것
- 정보 은닉 : 객체 내부 구현을 숨김으로써 객체가 반드시 정해진 메소드를 통해 상호작용하도록 유도하는 것
- 접근 제어자를 통해 구현
- public : 다른 객체에서 해당 객체 인스턴스 생성하여 접근 가능
- protected : 해당 객체를 상속받은 객체 내부에서 접근 가능
- default : 동일한 패키지 내의 객체에서 인스턴스 생성하여 접근 가능
- private : 선언된 객체 내부에서만 사용 가능
- 상속 : 보통 하위 클래스가 상위 클래스를 상속 받게 됩니다. 상속받은 하위 클래스는 상위 클래스의 변수와 메소드를 사용할 수 있게 되고 메소드를 오버라이딩하여 사용할 수 있게 됩니다. 코드의 재사용성이 높아지고 중복을 줄일 수 있게 됩니다.
- 다형성 : 하나의 객체가 여러 가지 타입을 가질 수 있는 것을 의마합니다. 부모 클래스의 참조변수로 자식 클래스의 인스턴스를 참조할 수 있게 구현합니다.
- 추상화 : 공통된 부분을 뽑아서 상위 클래스로 뽑아내는 것을 의미힙니다. 중복 코드를 줄일 수 있고, 재사용성을 높이고 가독성을 상승시킬 수 있다.
- 서버와 데이터베이스에 대한 출입구 역할을 한다.
- 한 클래스는 한 가지 책임에 관한 변경사항이 생겼을 때만 코드를 수정하게 되는 구조가 좋은 구조
- 한 책임의 변경으로의 연쇄작용에서 자유로울 수 있다.
- 코드 가독성 향상, 유지보수 용이, 다른 설계 원칙을 적용하는 기초
- 좋은 프로그램은 응집도를 높게, 결합도는 낮게
- 응집도 : 한 프로그램 요소가 얼마나 뭉쳐있는가를 나타내는 척도, 결합도 : 프로그램 구성 요소들 사이가 얼마나 의존적인지를 나타내는 척도
- 추상화 사용을 통한 관계 구축을 권장을 의미한다.
- EX) OCP 원칙의 가장 잘 따르는 예시 : JAVA 데이터베이스 인터페이스인 JDBC이다.
- 다형성 원리를 이용하고자 하는 원칙 개념이다.
- EX) Collection 인터페이스 : 자료형을 바꿔서 메소드를 실행해도 잘된다. 즉 다형성을 이용해 부모 타입 메소드를 실행해도 의도대로 잘 실행된다.
- SRP는 클래스의 단일 책임, ISP는 인터페이스의 단일 책임을 강조한다.
- 인터페이스는 다중 구현이 가능하기 때문에 클라이언트의 목적과 용도에 적합한 인터페이스만을 제공하는 것을 의미한다.
- DIP를 따르는 인기 있는 방법은 DI(의존성 주입)을 활용하는 것이다.
- 어떤 클래스를 참조해서 사용해야 하는 상황이 생긴다면 직접 클래스를 잡조하는 것이 아니라 그 대상 상위 요소(추상 클래스, 인터페이스)를 참조하라는 원칙이다.
- ArrayList : 단방향 포인터 구조 데이터, 조회가 빠름
- LinkedList : 양방향 포인터 구조 데이터, 삽입 삭제가 빠름
- HashSet : 순서 보장 X, 중복 허용 X
- LinkedHashSet : 입력 순서를 보장, 종복 허용 X
- TreeSet : 입력한 데이터의 크기가 비교 가능한 경우 오름차순으로 정렬, 중복 허용 X, 입력된 데이터가 사용자 정의 객체인 경우 Comparable 구현하여 정렬 기준 설정 가능
- HashMap : 순서 보장 X, 중복 key 허용 X
- LinkedHashMap : Key에 대한 입력 순서 보장, 중복 Key 허용 X
- TreeMap : 레드-블랙 트리 기반으로 Key, Value 저장, Key 데이터 크기가 비교 가능한 경우 오름차순으로 정렬, 중복 Key 허용 X, 입력된 데이터가 사용자 정의 객체인 경우 Comparable 구현하여 정렬 기준 설정 가능
- 레드-블랙 트리 : 자가 균형 이진 탐색 트리의 일종이다.
- 내부반복을 이용하기 때문에 스레드 공유자원에 대한 동기화를 관리해줄 필요가 없습니다.
- 모든 메소드가 추상메소드로 이루어져 있는 것을 말합니다.
- 구현 객체가 같은 동작을 한다는 것을 보장하기 위해 사용합니다.
- 다중 상속이 가능하고 인터페이스를 상속하는 집합 간에는 연관관계가 없습니다.
- 클래스 내 하나의 이상의 추상 메소드(abstract)를 포함한 경우를 말합니다.
- 객체의 추상적인 상위 개념으로 공통된 개념을 표현할 때 사용합니다.
- 단일 상속만 가능하고, 추상 클래스를 상속하는 집합 간에는 연관관계가 있습니다.
- Permanent Generation은 Class, Method Code가 저장되는 영역이며 힙 영역에 속했다.
- Classloader가 현재까지 로드한 Class의 Metadata가 저장되는 공간이며 Native 메모리 영역에 속한다. 또한 크기 제한이 없다.
- Metadata : 데이터에 대한 데이터를 의미한다. 다른 데이터를 설명하기 위한 데이터를 말하고 구조화된 정보를 분석, 분류하고 정보를 추가하기 위해 그 데이터에 뒤를 따라 가는 정보를 말한다.
- 범위를 넘어가면 오버플로우 발생
- @Column(nullable = false)은 JPA가 만든 엔티티 필드 값이 Null로 채워져서 정상적으로 처리되다가 DB에 도착한 순간 NOT NULL 옵션이 발생하여 예외처리가 된다.
- @NotNull은 필드값이 Null로 채워지는 순간 예외가 처리된다. @NotNull이 더 빠른 단계에서 예외를 검출한다.
- @NotNull vs @Column(nullable = false)_현구막
- 멀티 스레드 환경에서 사용하려면 별도의 동기화 처리가 필요합니다.
- 대표적으로 ArrayList, HashMap, StringBuilder, StringBuffer(멀티스레드 환경에서 사용) 등이 있습니다.
- 이 외에도 개발자가 커스텀한 객체가 내부 상태가 변화가 가능하다면 그것도 가변 객체이다.
- 멀티 스레드 환경에서 안전하게 사용할 수 있다는 신뢰성이 보장됩니다.
- 대표적인 불변 객체는 String이 있습니다.
- 이 외에도 개발자가 커스텀 객체를 내부 상태가 변하지 않게 만든다면 그것도 불변 객체이다.
- JVM의 메모리에서만 상주되어 있는 객체 데이터를 영속화가 필요할 때 사용됩니다. 시스템이 종료되어도 저장되는 장점이 있고 영속화된 데이터이므로 네트워크 전송이 가능합니다.
- JVM의 힙, 스택 메모리에 상주한 객체 데이터를 직렬화를 통해 바이트 형태로 변환하여 DB나 파일 외부 저장소에 저장한다. 그리고 다른 컴퓨터에서 이 파일을 가져와 역직렬화를 통해 자바 객체로 변환하여 JVM 메모리에 적재한다.
private ThreadLocal<String> threadStore = new ThreadLocal<>();
threadStore.set("hi"); //값 저장
threadStore.get(); //값 조회
threadStore.remove(); //값 제거
- A 스레드 값 저장, 값 조회, 값 제거 > B 스레드 값 저장, 값 조회, 값 제거
- synchronized 가 선언된 블럭에는 동시에 하나의 스레드만 접근할 수 있다.
- 해당 synchronized 를 남용하면 lock이 걸리는 쓰레드가 많아져 성능상 이슈가 발생할 수 있습니다.
- 하지만 여러 스레드가 공유 자원에 쓰기 연산을 할 경우 가시성을 보장했다고 해서 동시성을 보장하지는 않습니다.
해결책 : 가시성을 보장해야 하는 변수에 volatile
키워드를 붇여줘서 RAM에서 바로 읽도록 해야 합니다.
- 한줄의 프로그램 statement(문장)가 컴파일러에 의해 기계어로 변경되면서, 이를 기계가 순차적으로 처리하기 위한 여러 개의 machine instruction이 만들어져 실행되기 때문에 일어나는 현상을 설명하는 용어.
i++
> 기존 변수 읽고(READ), 연산하고(MODIFY), 저장한다(WRITE) > 여러 스레드가 해당 로직을 처리하면서 꼬이는 문제
synchronized
, atomic
을 통해 원자성을 보장해야 합니다.Reference: