본문 바로가기

Language/Java

(22)
[Java] invokevirtual과 invokeinterface — 바이트코드부터 vtable/itable까지 이전 포스트에서 클래스 로딩과 Klass 구조를 다뤘습니다. 이번엔 그 위에서 메서드 호출이 실제로 어떻게 이뤄지는지를 살펴보겠습니다. 1. invoke 명령어 종류Java 메서드 호출은 상황에 따라 다른 바이트코드로 컴파일됩니다.바이트코드대상invokevirtual일반 인스턴스 메서드invokeinterface인터페이스 메서드invokespecial생성자, private, super 호출invokestaticstatic 메서드invokedynamic람다, 동적 호출 이 중 invokevirtual과 invokeinterface가 동적 디스패치(dynamic dispatch)가 일어나는 핵심 명령어입니다. 둘 다 런타임에 실제 객체 타입을 확인해 메서드를 찾지만, 내부 구조는 다릅니다. 2. 바이트코드 ..
[Java] Java 배포의 흐름: 클래스패스부터 Spring Boot + Docker까지 자바 애플리케이션을 실행하고 배포할 때 꼭 알아야 할 개념을 흐름 순으로 정리합니다.클래스패스의 기본 원리부터 시작해 현대 실무에서 주로 쓰는 Spring Boot + Docker 배포 방식까지 다룹니다.1. 클래스패스 (Classpath)클래스패스란?JVM이 클래스 파일(.class)을 찾을 때 참조하는 경로 목록입니다. 소스코드를 컴파일하고 실행할 때 JVM은 이 경로를 따라 필요한 클래스를 로드합니다. 클래스패스 지정 방법환경 변수로 설정 (비권장)export CLASSPATH=/home/user/myapp:/home/user/libs/mylib.jar프로젝트마다 경로가 달라서 전역으로 관리하기 어렵고, 충돌이 생기기 쉽습니다. 실행 시 -cp 옵션 사용 (권장)# 컴파일javac -cp .:lib..
[Java] JVM 클래스 로딩 Deep Dive 4편 — 리플렉션 2편에서 Class 객체와 InstanceKlass가 양방향 포인터로 연결된다는 것을 살펴봤습니다. 리플렉션은 바로 이 연결을 타고 동작합니다. 이번 편에서는 리플렉션이 내부적으로 어떻게 동작하는지, 왜 느린지, 그리고 프레임워크들이 어떻게 활용하는지를 다룹니다. 리플렉션 기본 흐름리플렉션을 사용할 때 거치는 단계는 크게 세 가지입니다.Class 객체 획득모든 리플렉션의 시작점은 Class 객체입니다. 세 가지 방법으로 얻을 수 있습니다.Class clazz1 = MyClass.class; // 컴파일 타임에 결정Class clazz2 = obj.getClass(); // 런타임 타입 기준Class clazz3 = Class.f..
[Java] JVM 클래스 로딩 Deep Dive 3편 — ClassLoader 동작 원리와 예외 1편에서 ClassLoader의 계층 구조와 부모 위임 모델을 간략히 살펴봤습니다. 이번 편에서는 ClassLoader가 내부적으로 어떻게 동작하는지, 커스텀 ClassLoader가 실제로 어디에 활용되는지, 그리고 ClassLoader와 관련된 예외들이 왜 발생하는지를 다룹니다. loadClass(), findClass(), defineClass() — 세 메서드의 역할ClassLoader의 핵심은 세 메서드가 역할을 나눠 협력한다는 점입니다.loadClass() — 진입점loadClass()는 클래스 로드 요청의 진입점입니다. 내부적으로 다음 순서로 동작합니다.캐시 확인 — findLoadedClass()로 이미 로드된 클래스인지 먼저 확인합니다. 같은 클래스를 중복 로드하지 않기 위해서입니다.부모 ..
[Java] JVM 클래스 로딩 Deep Dive 2편 — InstanceKlass, Class 객체, Initialization 1편에서는 .class 파일이 JVM에 로드되고 Linking을 거치는 과정을 살펴봤습니다. 이번 편에서는 그 결과물인 InstanceKlass와 Class 객체가 실제로 어떤 구조인지, 그리고 마지막 단계인 Initialization이 언제 어떻게 동작하는지를 다룹니다. InstanceKlass — JVM이 클래스를 이해하는 방식InstanceKlass의 위치와 역할JVM은 .class 파일을 로드하고 나면 그 정보를 내부적으로 InstanceKlass라는 C++ 구조체로 표현합니다. JVM이 클래스를 실행하기 위해 필요한 모든 메타데이터를 담아두는 그릇입니다. InstanceKlass는 Metaspace에 위치합니다. Metaspace는 Java 8에서 기존의 PermGen을 대체한 영역으로, JVM..
[Java] JVM 클래스 로딩 Deep Dive 1편 — Loading & Linking 자바 코드를 실행하면 .class 파일이 JVM 메모리에 올라갑니다. 이 과정을 클래스 로딩(Class Loading) 이라고 부릅니다. 대부분의 자바 개발자는 이 과정이 "알아서 된다"고 넘어가는데, 막상 ClassNotFoundException이나 NoClassDefFoundError를 마주치거나, 리플렉션이나 동적 로딩을 다루게 되면 내부 동작을 모른다는 게 발목을 잡습니다. 이 글에서는 클래스 로딩의 두 단계인 Loading과 Linking이 JVM 내부에서 어떻게 동작하는지 살펴봅니다. 클래스 로딩의 전체 흐름클래스 로딩은 Loading → Linking → Initialization 순서로 진행됩니다. Linking은 다시 세 단계(Verification → Preparation → Resol..
[Java] CountDownLatch 완벽 정리 — 멀티스레드 동기화의 핵심 Java 동시성 프로그래밍에서 "특정 작업들이 모두 끝날 때까지 기다려야 하는" 상황, CountDownLatch 하나면 깔끔하게 해결됩니다. 1. CountDownLatch란?CountDownLatch는 Java 5(java.util.concurrent)에서 도입된 동기화 보조 클래스입니다.내부에 카운터(count) 를 가지고 있으며, 이 카운터가 0이 될 때까지 하나 이상의 스레드를 대기시키는 역할을 합니다.패키지: java.util.concurrent.CountDownLatch핵심 개념: 카운터가 0이 되는 순간 대기 중인 스레드가 일제히 진행을 재개 2. 핵심 메서드메서드설명CountDownLatch(int count)카운터 초기값을 설정하여 생성await()카운터가 0이 될 때까지 현재 스레드..
[Java] Java Concurrent 패키지 - Concurrent Collections 완벽 정리 java.util.concurrent 패키지의 동기화 컬렉션들을 실전 코드와 함께 알아봅니다.synchronized 래퍼와의 차이점, ConcurrentHashMap 내부 구조, 적재적소 사용법까지. 1. 왜 Concurrent Collection이 필요한가?멀티스레드 환경에서 일반 컬렉션(ArrayList, HashMap 등)을 그대로 쓰면 데이터 경쟁(race condition)이 발생합니다. Java는 크게 두 가지 방식으로 이를 해결합니다. Collections.synchronizedMap() 같은 래퍼는 모든 메서드에 전체 락을 걸어 스레드 안전성을 확보하지만, 락 구간이 넓어 성능이 낮습니다. 반면 java.util.concurrent의 컬렉션들은 내부를 버킷/세그먼트 단위로 나누거나, 아예 ..