JVM (Java Virtual Machine)
- 자바 프로그램이 실행되는 환경 제공
- 메모리를 체계적으로 관리하기 위해 여러 영역으로 나뉘어져 있음
- 메서드
- 힙
- 스택
- PC 레지스터
- 네이티브 메서드 스택
- GC(Garbage Collection) : JVM은 가비지 컬렉터를 통해 자동으로 메모리를 관리, 사용되지 않는 객체를 메모리에서 해제

메서드 영역
- 클래스의 정보를 저장하는 영역
- 정적 변수, 상수, 메서드 등이 저장된 (+클래스 정보) → 정적 : 즉각적으로 값을 가져올 수 있음 (person.name)
- 일부 JVM에 따라 GC가 관리해주는 경우도 있음
- 모든 스레드가 공유 (= 멀티 태스킹이 가능)
- static 쓰면 바로 메서드 영역에 올라감
- 클래스 로더에 의해 클래스가 로드될 때 저장되는 공간 → 회사 메뉴얼(설계도), 지침
- 인스턴스 안의 필드는 고유함, 메서드는 공통으로 활용됨
- 메서드를 인스턴스마다, 객체마다 따로 관리할 필요가 없음
힙 영역
- 객체 인스턴스를 저장하는 공간
- 인스턴스 변수, 배열 등이 해당 영역에 저장
- GC가 관리하는 영역(사용되지 않는 객체를 자동으로 삭제)
- 객체화시키면 힙에 올라감.
- 어플리케이션이 사용할 수 있는 가장 큰 메모리
- 가장 많이 사용되는 영역
- 모든 스레드가 공유 (private가 아닌 이상) → 프로젝트 자료 같은 것들
스택 영역
- 지역 변수, 메서드 호출 시 사용되는 값, 연산 결과 등 저장
- 메서드 호출 시 스택 프레임이 생성되며, 끝나면 스택 프레임 제거
- 접시를 쌓듯 쌓이는 형태
- 스택 영역 가장 아래는 main 메서드, 그 위에는 지역 변수나 사용자가 생성한 메서드들이 쌓인다…?
- 스메드마다 생성 → 작업 중인 문서 or 책상 (곧 치워질 예정)
PC 레지스터
- 현재 실행 중인 메모리의 주소를 저장하는 영역
- 프로그램 실행 흐름을 제어하는 데 사용
- 스레드마다 생성 → 지금 하고 있는 작업 위치
네이티브 메서드 스택
- 네이티브 언어(C,C++)로 작성된 메서드 호출 시 사용하는 메모리 영역
객체 생성과 메모리 할당
Person p1 = new Person();
p1.name = "김하리";
p1.age = 24;
p1.hobby = "Jazz";
Person p2 = new Person();
p2.name = "이준호";
p2.age = 33;
p2.hobby = "Dance";
static 키워드
- 클래스 수준에서 공유되는 멤버(필드, 메서드, 중첩 클래스)를 정의하는 데 사용
- static 키워드를 작성하면 객체와 무관하게 클래스 자체에 속함
- 특정 객체에 속하지 않고 모든 객체가 동일한 static 멤버 참조
- 클래스의 이름을 통해 직접 호출 가능(권장)
- JVM 메서드 영역에 저장
public class PersonTest {
public static void main(String[] args) {
Person p = new Person();
p.name = "Yan";
System.out.println(p.name);
System.out.println(p.pCount++);
Person p2 = new Person();
System.out.println(++p2.pCount);
System.out.println(Person.pCount);
}
}
public class Person {
static int pCount=1;
String name;
int age;
String hobby;
}
static 메서드
- 정적 메서드는 클래스 이름을 통해 직접 호출할 수 있는 메서드
- 객체와 무관하게 동작, 전역적인 작업에 적합(보통 알고리즘 문제 풀 때 사용)
- ClassName.methodName[];
static 블록
- 정적 블록은 클래스 로드시 한 번만 실행되는 블록
- 정적 필드 초기화에 사용
public class Person {
static int pCount=1;
String name;
int age;
String hobby;
static {
pCount = 1000;
}
public static void eat() {
pCount =100;
}
public void study() {
pCount = 1000;
name = "Yan";
}
}
public class PersonTest {
public static void main(String[] args) {
Person p = new Person();
p.name = "Kim";
System.out.println(p.name);
System.out.println(p.pCount++);
Person p2 = new Person();
System.out.println(++p2.pCount);
System.out.println(Person.pCount);
p.eat();
p.study();
Person.eat();
}
}
패키지
- 클래스와 인터페이스를 묶는 디렉토리 구조
- 클래스 이름 충돌 방지 (패키지명까지 해서 네임 스페이스 제공)
- 클래스 파일 첫 번째 줄에 package 키워드를 사용하여 선언
- .(dot)을 이용하여 패키지 구분
- 일반적으로 소속이나 회사의 도메인 역순으로 작성
임포트
- 다른 패키지 안에 있는 클래스 사용하기 위해서 import 과정 필요
- 단일 import → import [풀 패키지명]
- 전체 import → import [풀 패키지명].*
- 자바는 클래스가 실제로 사용되는 시점에서 메모리에 로드 → import 많다고 느려지지 않음
캡슐화
- 필드와 메서드를 하나의 단위로 묶고, 외부로부터 데이터를 숨기며 안전하게 보호하는 것
- 정보 은닉 → 내부 데이터를 외부에서 직접 접근하지 못하게 하고 특정 메서드를 통해서만 접근하도록 제한
접근 제한자
- 클래스, 메서드, 변수 등에 대한 접근 범위를 지정
- 캡슐화와 정보은닉으 가능하게 함
- 다른 제한자들과는 달리 접근 제한자는 하나만 작성이 가능
접근 제한자 종류
- public : 모든 위치에서 접근 가능
- protected : 같은 패키지 또는 패키지가 달라도 상속 관계에서 접근 가능
- default(package-private) : 같은 패키지 안에서만 접근 가능 → 안 쓰면 default값
- private : 같은 클래스 내부에서만 접근 가능
클래스와 접근 제한자
- 최상위 클래스 (외부 클래스) : public default
- 중첩 클래스 (내부 클래스) : 4가지 종류 모두 가능

접근자 (Getter)/ 설정자(Setter)
- 캡슐화를 구현하는데 사용되는 메서드
- Getter : private 필드 값을 외부에서 읽을 수 있게 함
- Setter : private 필드 값을 외부에서 수정할 수 있게 함 → 직접 접근이 아닌 안전하게 읽고 쓰는 방식 제공
- 접두사 get/set 이용하여 메서드 작성
객체 배열 관리
- 여러 객체를 하나의 배열로 묶어 관리하는 방식
- 객체 배열의 요소는 객체 참조 값을 저장
- 기본값은 null로 초기화
- 객체를 추가, 조회, 수정, 삭제할 수 있음 (CRUD)
- 싱글턴 패턴을 사용하여 관리할 수 있음
싱글턴 패턴
- 객체를 하나만 생성하도록 보장하는 디자인 패턴
- 객체의 유일성 보장 → 하나의 인스턴스만 생성 (전역적으로 동일한 객체 공유)
- 생성자를 private으로 만들어 클래스 내부에서만 생성 가능
- 정적 메서드를 통해 전역적으로 접근 가능
public class Manager{
private static Manager manager = new Manager();
private Manager(){}
public static Manager getManager(){
return manager;
}
}