[GO] Go map 내부 구조 뜯어보기 - Swiss Table, group, probing, growth
·
Language/Go
Go에서 map은 겉으로 보면 평범한 키-값 저장소다. 하지만 런타임 안쪽으로 들어가면 버전마다 꽤 다른 구현을 만난다. Java를 공부할 때 HashMap 내부가 linked list에서 red-black tree로 바뀌는 구조를 본 적이 있다. Go의 map도 같은 궁금증으로 들여다봤는데, 버전마다 설명이 달라서 직접 소스를 찾아보게 됐다. 이 글은 그 과정에서 정리한 내용이다. 예전 Go map 설명을 보면 hmap, bmap, tophash, overflow bucket, oldbuckets, evacuate 같은 단어가 자주 나온다. 그 설명이 틀린 것은 아니다. 다만 현재 Go 1.25 기준의 기본 구현을 설명하는 글로 읽으면 방향이 어긋난다. 현재 Go 런타임의 map은 Swiss Table..
[Kotlin] sealed class를 처음 이해할 때 가장 헷갈렸던 것들
·
Language/Kotlin
Kotlin을 공부하다 보면 sealed class 문법을 꽤 빨리 마주치게 된다. 특히 상태를 모델링하거나, 성공/실패 결과를 타입으로 표현하려고 할 때 자주 등장한다. 그런데 처음 보면 가장 먼저 막히는 지점이 있다. object Success : Result() 같은 문법이 대체 무엇을 의미하는지 직관적으로 들어오지 않는다는 점이다. 이번 글은 이 헷갈림에서 출발해, sealed class의 기초 개념부터 object, data class, when exhaustive 체크, 그리고 활용까지 정리한 글이다.sealed class란 무엇인가sealed class는 하위 타입이 제한된 추상 클래스라고 이해하면 된다. 즉, 어떤 부모 타입 아래에 올 수 있는 자식 타입들을 닫힌 집합으로 관리하고 싶을 때..
[JAVA] 생성자에서 리스너 등록하다가 this escape 나는 이유
·
Language/Java
1. 문제 코드: 생성자 안에서 리스너 등록public class EarlyPublish { private final String config; public EarlyPublish(EventBus eventBus) { this.config = "default"; eventBus.register(new EventListener() { @Override public void onMessage(Message msg) { handle(msg); } }); } private void handle(Message msg) { // config를 사용한다고 가정 ..
[JAVA] 스레드 안전한 공유 객체를 만드는 세 가지 축: 불변, 공개, confinement
·
Language/Java
1. 이 글에서 정리할 것이 글은 공유 객체를 어떻게 설계·공개해야 안전한가를 JMM(Java Memory Model)과 JIT 관점까지 엮어서 정리한 것이다. 핵심 축은 세 가지다.공유 가변 상태를 가능한 줄이고, 불변/결과적 불변으로 최대한 끌어올릴 것객체를 어떻게 공개하느냐(safe publication) 를 설계에 포함할 것아예 공유하지 않을 수 있을 때는 thread confinement로 escape 자체를 막을 것2. 공유 상태의 세 단계: 불변 / 결과적으로 불변 / 가변공유 상태는 다음 세 수준으로 나눠서 보는 게 이해가 쉽다.2.1 완전 불변(Immutable)조건은 세 가지 정도로 정리할 수 있다.생성 이후 상태가 절대 변하지 않는다 (setter 없음, 내부 가변 구조도 변경되지 않..
[JAVA] 자바 synchronized 를 바이트코드로 까보며 이해하기
·
Language/Java
자바에서 synchronized는 모니터 락을 잡는다 정도로 보통 설명하지만, 실제로 JVM 바이트코드 레벨에서는 어떻게 구현되는지 궁금해졌다. 간단한 Account 예제를 작성해서 javap -c -v로 디스어셈블하고, synchronized 블록과 메서드가 어떤 바이트코드로 바뀌는지 직접 확인해 보았다.1. 예제 코드와 디스어셈블 결과이번에 사용한 예제 바이트코드는 대략 다음과 같다.public class Account minor version: 0 major version: 65 flags: (0x0021) ACC_PUBLIC, ACC_SUPER this_class: #8 // Account super_class: #2 ..
[JAVA] 자바 동시성 프로그래밍: 기초부터 메모리 모델, 설계 전략까지 한 번에 정리하기
·
Language/Java
1. 왜 이 글을 쓰는가?단일 스레드 환경에서는 코드가 위에서 아래로 순차적으로 실행되기 때문에 상태 변화를 추적하기 쉽다. 하지만 멀티코어 환경에서 여러 스레드가 동시에 실행되면, CPU 캐시와 메인 메모리 사이의 데이터 불일치로 인해 예상치 못한 버그가 발생한다. 단순히 synchronized 를 쓰면 안전하다고 외우기보다, 자바 메모리 모델(JMM)이 어떻게 작동하고 JVM 내부에서 스레드와 모니터 락이 어떤 구조로 관리되는지를 정리하는 것이 목적이다. 이 글은 다음 질문들에 답하는 것을 목표로 한다.왜 스레드를 늘린다고 무조건 성능이 좋아지지 않는가? (암달의 법칙)자바 스레드의 실제 상태는 어떻게 변하며 인터럽트는 왜 중요한가?JMM의 Happens-Before 관계란 무엇인가?synchroni..
[JAVA] JVM Class Loading, Metaspace, 그리고 메서드 바이트코드까지 한 번에 이해하기
·
Language/Java
1. 왜 이 글을 쓰는가? 요즘 JVM의 클래스 로딩, 링킹, 그리고 ClassLoader.defineClass() 구현까지 따라가면서 공부하고 있다. 단순히 클래스 로딩 → 메서드 영역 → 실행 처럼 외워서는 금방 잊어버리게 되어, .class 파일의 바이트코드가 JVM 내부에서 어떤 객체/메모리 구조로 변해서 실제로 실행되는지를 한 번에 정리해 보려고 한다.이 글은 다음 질문에 답하는 것을 목표로 한다..class 파일 안의 메서드 코드는 어떻게 저장돼 있을까?ClassLoader.defineClass(byte[])가 바이트 배열을 받아서 내부에서 무슨 일을 할까?메서드의 바이트코드는 JVM 메모리 어디(Method Area / Metaspace)에 저장될까?인터프리터는 이 메타데이터를 어떻게 읽어서..
[EFFECTIVE JAVA 3/E] #2 생성자에 매개변수가 많다면 빌더를 고려하라
·
Language/Java
목차중점적으로 봐야 하는 내용선택적 매개변수가 많은 클래스는 생성자나 정적 팩터리 메서드만으로 표현하기 어렵다.점층적 생성자 패턴이나 자바빈즈 패턴은 유지보수성·안정성 측면에서 한계가 있다.이런 경우 빌더 패턴을 사용하면 가독성과 객체 일관성 면에서 유리하다.주요 개념 요약빌더 패턴은 복잡한 객체를 구성할 때 필수 매개변수와 선택 매개변수를 분리하고, 단계별 설정을 가능하게 하는 설계 기법이다.보통 클래스 내부에 정적 멤버 클래스로 Builder를 두고, 메서드 체인 방식으로 속성들을 설정한 뒤 build() 메서드로 객체를 생성한다.장점매개변수가 많은 경우 코드 가독성이 좋아진다.필수 매개변수와 선택 매개변수를 명확히 구분할 수 있다.메서드 체인(Fluent API)을 통해 설정이 직관적이다.계층적으로..