이것이 자바다 - 5~6장
책을 읽으면서 새로 알게된 부분 / 추상적으로 알던 부분을 정리하려고 노력했다.
CS를 잘 모르거나 자바를 진짜 처음보는 초심자에게는 책 내용 이해하기가 너무 힘들 것 같은데 기초...가 맞나? 싶다
현재 시점에서 책을 보며 정리하기를 정말 잘했다고 생각한다.
5장: 참조 타입
JVM Runtime Data Area
오라클 레퍼런스 - Run-Time Data Areas
Method Area
- 클래스 로더에 의해 로드된 클래스/인터페이스 관련 메타데이터(바이트 코드, 시그니처, 런타임 상수 풀 등)가 저장됨
- 모든 스레드가 공유
- HotSpot VM에서 Java 7까지는 PermGen, Java 8부터 Metaspace로 관리됨
Run-Time Constant Pool : 컴파일 타임에 알려진 숫자 리터럴, 런타임에 해석되거나 결정되어야 하는 메서드/필드 참조 등 여러 종류의 상수가 들어있음
Heap Area
- 힙은 모든 클래스 인스턴스(객체) 및 배열의 메모리가 할당되는 런타임 데이터 영역
- 모든 스레드가 공유
- GC 돌아감
Stack
각 JVM 스레드는 스레드 생성과 동시에 만들어지는 자기만의 JVM 스택을 가진다
- 각 스레드마다 존재하는 메서드 호출 실행을 기록
- 스택 프레임이 쌓인다 → 메서드 상태 정보 저장
- Local Variables
- Operand Stacks — 메서드 내 계산을 하기 위한 스택
- Dynamic Linking — 현재 메서드가 속한 클래스의 런타임 상수 풀 참조
- Return values for methods / dispatch exceptions
- Normal Method Invocation Completion : 정상적으로 메서드 호출 완료
- Abrupt Method Invocation Completion : 비정상적으로 메서드 호출 완료
PC Register
자바 가상 머신은 동시에 많은 실행 스레드를 가질 수 있음 → 각 JVM 스레드는 자신만의 pc(program counter) 레지스터를 가진다. 즉, 스레드가 어디까지 실행했는지 기록하고 있음
Native Method Stacks
자바가 아닌 네이티브 코드(C/C++ 등)로 작성된 메서드(JNI)를 실행할 때 사용되는 스택
- 스레드 별로 할당됨
알게된 기능
- System.arraycopy — 배열 복사(shallow copy) 네이티브 메서드임 즉, JNI로 구현되어 있음
열거 타입
열거 상수는 열거 객체로 생성된다.
예를 들어, 열거 타입 Week은 MONDAY부터 SUNDAY까지 있는데 메서드 영역에 생성된 열거 상수가 해당 Week 객체를 각각 참조한다.
java.lang.Enum 클래스 상속
ordinal()→ enum 상수가 선언된 순서(0부터 시작)를 정수로 반환하는 메서드
6장: 클래스
객체 지향 프로그래밍 : 현실 세계의 물건(객체)처럼, 프로그램을 데이터(상태)와 그 데이터를 다루는 기능(행동)을 한 덩어리로 묶은 객체들로 나누고, 그 객체들이 서로 메시지를 주고받으며 협력하게 만들어 코드를 더 이해하기 쉽고, 수정/확장하기 쉽게 만드는 프로그래밍 방식
객체 모델링 : 현실 세계의 객체를 소프트웨어 객체로 설계하는 것
메서드 → 객체의 상호작용 수단
객체 간 관계
- 집합 관계
- 사용 관계 → 객체 간 상호작용
- 상속 관계 : 상위 / 하위. 일반적으로 상위 객체는 종류, 하위 객체는 구체적인 사물에 해당
정보
- 캡슐화 : 객체의 속성(데이터)과 행동(메서드)을 하나로 묶고, 내부 구현은 숨긴 채 필요한 것만 외부에 공개하는 것
- 한 소스 파일에 여러 개 클래스가 있으면 → 컴파일 후 바이트 코드 파일은 클래스 선언한 개수만큼 생긴다
- 필드 초기값 지정되지 않으면 default 벨류 들어감
- 도트(.) 연산자
메서드
varargs(...) : 파라미터 개수를 모를 때 사용 (파라미터를 배열로 받는 방식 대신)
- 맨 마지막 파라미터만 가능
- 내부적으로 배열로 처리됨 (즉, 배열 타입임)
int sum(int ... values) {
int s = 0;
for (int val : values) s += val;
return s;
}
// 둘 다 가능
sum(1, 2, 3, 4, 5);
sum(new int[] { 1, 2, 3, 4, 5 });
메서드 호출할 때, 컴파일러가 인자 타입을 메서드 파라미터 타입에 맞춰 자동 타입 변환을 하는 경우가 있음 (widening conversion, upcasting, autoboxing/unboxing)
static
정적 멤버
- 정적 필드
- 생성자에서 초기화 작업 불가
- 필드 선언과 동시에 초기값을 주거나,
static block을 이용해 초기화 작업
- 정적 메서드
클래스 로더가 클래스를 로딩해서 메서드 메모리 영역에 적재 → 클래스별로 관리됨
접근 제한자 (Access Modifier)
어디에서 이 멤버(클래스/필드/메서드/생성자)에 접근할 수 있나
| 접근제한자 | 최상위 클래스(top-level) | 중첩 클래스(nested) | 필드 | 생성자 | 메서드 |
|---|---|---|---|---|---|
| public | ✅ | ✅ | ✅ | ✅ | ✅ |
| protected | ❌ | ✅ | ✅ | ✅ | ✅ |
| default | ✅ | ✅ | ✅ | ✅ | ✅ |
| private | ❌ | ✅ | ✅ | ✅ | ✅ |
적용 대상
protected같은 패키지면 누구나, 또는 다른 패키지라도 상속받은 클래스에서 접근 가능default는 같은 패키지에서만 접근 가능private은 같은 클래스 내부에서만 접근 가능 (같은 클래스의 다른 인스턴스 접근 가능)
어노테이션
코드에 붙이는 메타데이터 → 컴파일러/도구/프레임워크가 어노테이션을 읽고 동작을 바꾸게 만들 수 있음
@Target — 타겟
어노테이션을 적용할 수 있는 대상 지정하는 데에 사용
java.lang.annotation.ElementType 열거 상수로 정의되어 있음
| ElementType | 설명(붙일 수 있는 위치) | 예시 |
|---|---|---|
TYPE |
클래스/인터페이스/enum/record 선언 | @A class C {} |
FIELD |
필드 선언(enum 상수 포함) | @A int x; / @A ENUM_CONST |
METHOD |
메서드 선언 | @A void m() {} |
PARAMETER |
파라미터 선언(메서드/생성자) | void m(@A int x) {} |
CONSTRUCTOR |
생성자 선언 | @A C() {} |
LOCAL_VARIABLE |
로컬 변수 선언 | @A int t = 0; |
ANNOTATION_TYPE |
어노테이션 타입 선언 | @A @interface X {} |
PACKAGE |
패키지 선언 | @A package p; |
TYPE_PARAMETER |
타입 파라미터 선언 | class C<@A T> {} |
TYPE_USE |
타입이 사용되는 위치 모두(변수 타입/캐스트/제네릭 인자/throws 등) | List<@A String> xs; / (@A String)s / throws @A IOException |
MODULE |
모듈 선언 | @A module m {} |
RECORD_COMPONENT |
레코드 컴포넌트 | record R(@A int x) {} |
@Retention — 유지 정책
java.lang.annotation.RetentionPolicy
Java Platform, Standard Edition Java API Reference
SOURCE: 소스상에만 어노테이션 정보 유지. 컴파일 후에는 사라짐 즉, 바이트 코드(.class)에는 남지 않는다.CLASS: 바이트 코드에는 어노테이션 정보가 남아있음. 근데, 실행 중일 때 VM에선 유지되지 않아서 리플렉션으로 조회할 수 없음RUNTIME: .class에도 기록되고, 실행 중에도 유지되어서 리플렉션으로 조회 가능
(여기서 리플렉션은 실행 중에 JVM이 들고 있는 클래스/메서드/필드 정보(메타데이터)를 조회/조작할 수 있는 기능)
CLASS는 왜 필요한가? → 라이브러리 같은 jar 파일에는 소스 파일이 아닌 .class 파일만 있음 IDE 같은게 이걸 읽어서 정보를 얻을 수 있음
Lombok이 제공하는 어노테이션들을 살펴보면, SOURCE나 CLASS가 사용되고 있음을 볼 수 있다.
@Getter는SOURCE이다. 메서드 만들고 바이트 코드에서는 어노테이션 사라짐@NonNull은CLASS이다. 컴파일 때 null-check 메서드가 삽입되는데, 문서적인 역할(documentary role)도 가지고 있다고 함
'CS > 스터디' 카테고리의 다른 글
| 주니어 백엔드 개발자가 반드시 알아야 할 실무 지식 - 부록 (0) | 2026.01.26 |
|---|---|
| 주니어 백엔드 개발자가 반드시 알아야 할 실무 지식 - 8, 9장 (1) | 2026.01.13 |
| 주니어 백엔드 개발자가 반드시 알아야 할 실무 지식 - 6, 7장 (0) | 2026.01.05 |
| 주니어 백엔드 개발자가 반드시 알아야 할 실무 지식 - 5장 (0) | 2025.12.30 |
| 이것이 자바다 - 1~4장 (0) | 2025.12.28 |