[TIL][02.06] JAVA, JVM, TYPE, Garbage Collection

2025. 2. 6. 22:52· [LG 유플러스] 유레카/Today I Learned
목차
  1. JAVA 특징
  2. JVM의 역할 (기능)
  3. JVM 실행 과정
  4. printf 대신 println을 써야하는 이유
  5. public static void main(String[] args)
  6. 자료형
  7. Java 프로그램 실행 과정
  8. Java 메모리 구조
  9. 데이터 타입의 메모리 할당과 성능 영향
  10. byte로 저장하지 않고 int로 저장하는 이유
  11. System.out.println(age)
  12. finalize()
  13. 가비지 컬렉션(GC)
  14. 메서드를 작게 분할해야하는 이유
  15. MyStr name = new MyStr();
  16. System.out.println(name)

JAVA 특징

  1. 플랫폼 독립성
    • Java 코드는 컴파일되면 바이트코드(Bytecode)로 변환됨.
    • 특정 운영체제에 의존하지 않고, JVM(Java Virtual Machine) 이 설치된 환경에서 실행 가능.
  2. 객체 지향 프로그래밍(OOP)
    • 캡슐화, 상속, 다형성, 추상화 등의 OOP 개념을 지원.
    • 코드의 재사용성 과 유지보수성 이 뛰어남.
  3. 멀티스레딩 지원(Thread-Multi)
    • 여러 작업을 동시에 수행할 수 있는 멀티스레딩(Multithreading) 기능 제공.
    • 병렬 처리를 쉽게 구현 가능.
  4. 가비지 컬렉션(Garbage Collection)
    • Java는 자동 메모리 관리 를 지원.
    • 사용되지 않는 객체를 GC(Garbage Collector) 가 자동으로 제거하여 메모리 누수를 방지.
  5. 보안(Security)
    • 바이트코드 검증 등으로 보안성이 높음.
  6. 예외 처리(Exception Handling) 지원
    • try-catch-finally, throws 를 활용한 예외 처리 기능 제공.
    • 프로그램의 안정성을 높이고, 예외 상황을 효과적으로 관리 가능.

JVM의 역할 (기능)

  1. 바이트코드 실행
    • Java 컴파일러(javac)가 변환한 바이트코드(.class 파일) 를 실행.
    • 운영체제(OS)와 독립적으로 동작하여 플랫폼 독립성 제공.
  2. 메모리 관리 및 가비지 컬렉션(GC)
    • 프로그램 실행 시 Heap, Stack, Method Area, PC Register 등의 메모리를 관리.
    • 사용하지 않는 객체를 GC(Garbage Collector) 가 자동으로 제거.
  3. 클래스 로딩(Class Loading)
    • 실행 시 필요한 클래스를 클래스 로더(Class Loader) 가 동적으로 로드.
  4. 런타임 환경 제공
    • Java 프로그램이 실행되도록 JRE(Java Runtime Environment) 를 제공.
    • 표준 라이브러리(API)와 함께 동작.
  5. 바이트코드 검증(Security & Verification)
    • 바이트코드가 변조되지 않았는지 검사하고, 보안 위반 여부를 확인.

JVM 실행 과정

.java파일로 코드 작성 >> javac로 컴파일 >> .class 파일 생성 후 바이트 코드로 변환 >> .class 파일을 메모리에 로드 >> 바이트 코드 검증 >> 기계어로 변환 >> 실행

 

printf 대신 println을 써야하는 이유

printf는 포맷 지정자를 사용하기 때문에 포맷 문자열 공격을 받을 수 있음

System.out.printf("Hello, %s!\n", "World"); // "Hello, World!\n" 출력

printf : 일반적으로 위와 같이 동작하는데, %s같은 포맷 지정자를 외부 입력과 함께 사용하는 경우 문제 발생 가능

String userInput = "%x %x %x %x";
System.out.printf(userInput);

printf(인수가 없는 경우) : printf는 인수를 찾으려고 스택에서 임의의 메모리를 읽어옴 (인수를 안 줬는데도 %x를 해석하려 하니, 스택에 저장된 데이터가 그대로 출력됨)

String userInput = "%x %x %x %x";
System.out.println(userInput);  // 그냥 "%x %x %x %x" 그대로 출력됨

println : println의 경우에는 포맷 지정자를 해석하지않고 단순히 문자열만 출력함

 

 

public static void main(String[] args)

public

  • 접근 제어자(Access Modifier)
  • public이기 때문에 JVM이 어디서든 접근 가능해야 함.
  • 만약 private으로 하면, JVM이 실행할 수 없어서 프로그램이 동작하지 않음.

static

 

  • static 키워드는 객체를 생성하지 않고도 호출 가능하다는 의미.
  • 만약 static이 없으면, main()을 호출하려면 먼저 클래스의 객체 인스턴스를 만들어야 함.
  • JVM이 main()을 실행할 때 빠르게 실행해야함 >> 객체 생성 없이 바로 호출해야 하기 때문에 static이 필요함.

void

  • 반환 타입이 없다는 뜻. 즉, 이 메서드는 값을 반환하지 않음.
  • 만약 int 같은 반환 타입을 지정하면, main() 실행 후 어떤 값을 반환해야 하는데, 그런 기능이 필요하지 않음.

main

  • 메서드 이름으로, JVM이 프로그램 실행을 시작하는 진입점(entry point) 메서드.
  • 이름을 바꾸면 실행되지 않음 (start(), execute() 등은 JVM이 찾지 않음).
  • main이라는 이름으로 JVM에 미리 정의되어 있음

(String[] args)

  • 문자열 배열을 args라는 이름의 매개변수로 받는다는 의미

 

자료형

primitive(기본) : 숫자형(정수형(byte, short, int, long), 실수형), 단일 문자형, 논리형

primitive(기본) reference(참조)
숫자형 단일 문자형 논리형 사용자가 정의하는 데이터 타입
정수형 실수형 char (2byte) boolean (1byte) (class, interface, enum)
byte (1byte) float (4byte) String
short (2byte) System
int (4byte) double (8byte) Object
long (8byte) PrintStream
...

 default value

Java 프로그램 실행 과정

  1. Java 파일 컴파일 (javac)
    • .java 파일을 javac로 컴파일하면 .class 파일이 생성됨. 이 파일은 바이트코드로 변환된 상태
  2. 클래스 로딩 (JRE의 클래스 로더)
    • .class 파일이 JRE에 있는 클래스 로더에 의해 로드됨
    • 클래스 로더는 클래스 파일이 JDK에서 컴파일된 것인지 확인(외부에서 심어졌을 수도 있기 때문에)하고, 이를 안전하게 메모리로 가져옴
  3. 바이트코드 검증 (바이트코드 베리파이어)
    • 바이트코드 베리파이어는 로드된 바이트코드를 검수하여 올바른 코드인지 검사
    • 검수를 통해 코드가 보안상의 문제를 일으킬 수 없도록 함
  4. 기계어 변환 (JVM)
    • 검증된 바이트코드는 JVM에 의해 실행됨. JVM은 바이트코드를 기계어로 변환하여 실제 하드웨어에서 실행될 수 있도록 함
  5. 메인 메서드 실행
    • 실행이 시작되면 main() 메서드가 호출
    • static 멤버는 메모리에 초기화 됨

Java 메모리 구조

Java 프로그램이 실행될 때, JVM은 메모리를 여러 영역으로 나누어 관리함

  1. 스택(Stack) 영역
    • 로컬 데이터 (지역 변수, 메서드 호출 정보 등)가 저장됨
  2. 힙(Heap) 영역
    • 객체와 배열이 저장됨
    • 이 영역은 동적으로 할당되며, 객체가 가비지 컬렉션에 의해 관리됨
    • 힙 영역은 Young Generation과 Old Generation으로 나뉘고, Young Generation은 다시 Eden Space, Survivor Space, Old Generation으로 나눠짐
    • Young Generation에서 새로운 객체가 생성되고, 객체가 살아남은 경우 Old Generation으로 이동
  3. 메소드(Method) 영역
    • 클래스 정보, 메서드와 필드 정보, 정적 변수(static variables), 상수(final constants), 클래스의 런타임 데이터 등이 저장됨
    • 정적 메서드, 정적 변수는 Method Area에 저장됨
    • 상수 문자열(String literals)은 String Pool에 저장됨
  4. PC 레지스터 (Program Counter Register)
    • 각 스레드마다 프로그램의 현재 실행 위치를 추적
  5. Non-Heap
    • 힙 영역 외부에서 관리되는 JVM 메모리 영역
    • 클래스 메타데이터, 정적 변수 등과 같은 데이터가 저장됨

데이터 타입의 메모리 할당과 성능 영향

 

  • int age = 30;에서 30은 값이고, 이 값은 age라는 변수에 할당됨
  • int는 4바이트 크기의 기본 데이터 타입이기 때문에, 30이라는 값을 4바이트 공간에 저장함
  • 즉, JVM은 4바이트 크기의 공간을 할당하여 30을 그 공간에 저장하고, age 변수는 스택에 위치하게 됨

byte로 저장하지 않고 int로 저장하는 이유

  • int는 4바이트를 차지하는데, 만약 1바이트로 저장하면, 3바이트가 낭비되게 됨
  • JVM은 이와 같은 비효율적인 저장 방식 대신 적절한 메모리 크기를 사용하여 성능을 최적화하려 함
  • 성능 최적화 과정을 한 번 더 수행하게 되기 때문에 오히려 성능이 안좋아질 수 있음

 

  1.  

System.out.println(age)

System 클래스는 JVM이 클래스 로더를 이용해 메모리에 로드됨. 로딩은 System.out.println(age) 실행 시 필요한 클래스를 로드하고 초기화하는 과정. System 클래스의 out, in, err은 각각 4바이트 공간을 할당받고, 기본적으로 null로 초기화됨

finalize()

객체가 가비지 컬렉션 대상이 될 때 호출되는 메서드. 이 메서드를 오버라이딩하면, 객체가 수거되기 전에 특정 작업을 할 수 있음. 그러나 finalize()를 오버라이딩하면, 수거가 늦어질 수 있기 때문에 성능에 영향을 줄 수 있음.

가비지 컬렉션(GC)

가비지 컬렉터는 더 이상 사용되지 않는 **객체(쓰레기 객체)**를 자동으로 제거하고, 메모리 공간을 회수

 

  1. 사용되지 않는 객체는 가비지로 간주됨
  2. 가비지 컬렉터는 기존 메모리 공간에서 유효한 객체들을 다른 공간으로 옮김
  3. 비어있는 메모리 공간은 모두 정리됨

메서드를 작게 분할해야하는 이유

  • 작은 메서드들은 빠르게 실행되고, 메모리에서 할당된 공간을 빠르게 해제함
  • 가비지 컬렉터는 메서드 내에서 쓰지 않는 객체들을 찾아서 쓰레기 객체로 간주하고 처리함. 이를 위해 메서드가 빨리 종료되도록 적절하게 메서드를 분할하는 것이 좋음

 

 

 

 

MyStr name = new MyStr();

  • new MyStr()로 생성된 객체는 힙 영역에 할당됨. 만약 MyStr 객체가 char 배열을 포함하고 있다면, 그 char 배열이 힙 영역에 저장됨
  • name이라는 참조 변수가 스택 영역에 저장됨. 이 참조 변수는 객체의 메모리 주소를 저장하며, 객체 자체는 힙 영역에 존재함

System.out.println(name)

  • name.toString()이 자동 호출되어 객체의 값이 출력됩니다. String 클래스에서는 toString() 메서드가 오버라이드되어 실제 문자열을 반환합니다.
  • name.toString()이 자동으로 호출됨. 만약 MyStr 클래스에서 toString()을 오버라이드하지 않으면, 기본적으로 Object 클래스의 toString() 메서드가 호출되어 객체의 해시코드를 출력.
  MyStr name = new MyStr("홍길동"); String name = new String("홍길동");
출력 오버라이드 하지 않은 경우 MyStr 객체의 해시코드가 출력 "홍길동" 출력

'[LG 유플러스] 유레카 > Today I Learned' 카테고리의 다른 글

[TIL][02.10] 배열, 상속, 다형성, abstract  (0) 2025.02.10
[TIL][02.07] String, Method, Arrays  (0) 2025.02.10
[TIL][02.05] implements, inheritance, override, abstract, generic, utility  (0) 2025.02.05
[TIL][02.04] Array Iteration, Map, TS  (0) 2025.02.04
[TIL][02.03] ES6, SSR, CSR, SSG, SOP, CORS  (0) 2025.02.04
  1. JAVA 특징
  2. JVM의 역할 (기능)
  3. JVM 실행 과정
  4. printf 대신 println을 써야하는 이유
  5. public static void main(String[] args)
  6. 자료형
  7. Java 프로그램 실행 과정
  8. Java 메모리 구조
  9. 데이터 타입의 메모리 할당과 성능 영향
  10. byte로 저장하지 않고 int로 저장하는 이유
  11. System.out.println(age)
  12. finalize()
  13. 가비지 컬렉션(GC)
  14. 메서드를 작게 분할해야하는 이유
  15. MyStr name = new MyStr();
  16. System.out.println(name)
'[LG 유플러스] 유레카/Today I Learned' 카테고리의 다른 글
  • [TIL][02.10] 배열, 상속, 다형성, abstract
  • [TIL][02.07] String, Method, Arrays
  • [TIL][02.05] implements, inheritance, override, abstract, generic, utility
  • [TIL][02.04] Array Iteration, Map, TS
leeemingyu
leeemingyu
leeemingyu
ye
leeemingyu

블로그 메뉴

  • GitHub
  • Instagram
    전체
    오늘
    어제
    • 전체보기 (68)
      • GDSC (4)
        • 실시간 채팅 구현 (4)
      • [LG 유플러스] 유레카 (63)
        • Today I Learned (37)
        • 코딩테스트 (22)
        • 프로젝트 (4)

    공지사항

    인기 글

    최근 댓글

    최근 글

    hELLO · Designed By 정상우.v4.2.2
    leeemingyu
    [TIL][02.06] JAVA, JVM, TYPE, Garbage Collection
    상단으로

    티스토리툴바

    단축키

    내 블로그

    내 블로그 - 관리자 홈 전환
    Q
    Q
    새 글 쓰기
    W
    W

    블로그 게시글

    글 수정 (권한 있는 경우)
    E
    E
    댓글 영역으로 이동
    C
    C

    모든 영역

    이 페이지의 URL 복사
    S
    S
    맨 위로 이동
    T
    T
    티스토리 홈 이동
    H
    H
    단축키 안내
    Shift + /
    ⇧ + /

    * 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.