Reflection 메소드 매개변수 필드명이 arg0, arg1로 나오는 문제 해결

메소드 필드명이 필요했던 이유 AOP를 이용해 다양한 곳에서 유연하고 범용성 있게 사용하기 위해 메소드의 매개변수 필드명이 필요했습니다. 문제 상황 원하는 출력 값은 lockName과 userId의 값이었지만, 예상했던 것과는 다르게 arg0, arg1과 같은 변수명을 가져왔습니다. Parameter.getName() 분석 클래스 구조도 Method 클래스는 Executable 클래스를 상속하고 있고 getParameters는 Executable 클래스에서 구현되어 있었습니다. Executable 클래스 분석 getParameters 메소드 (시작) getParameters() 메소드에서 시작해서 내부 구현을 추적했습니다. ...

April 28, 2024 · Lee WooJin

TreeSet의 구조와 Comparator 주의사항

TreeSet 구조 TreeSet은 필드로 NavigableMap 인터페이스를 가지고 있으며, TreeMap 클래스가 해당 인터페이스를 구현하는 구조를 가지고 있습니다. TreeSet 생성자가 호출되면 m 필드에 TreeMap 클래스가 할당됩니다. 문제점 발견 TreeSet을 사용하면서 예상한 결과값과 다르게 결과가 나와서 원인을 찾아보기로 했습니다. 예시: x만 비교할 때 Comparator<Point> comparator = Comparator.comparingInt(p -> p.x); TreeSet<Point> treeSet = new TreeSet<>(comparator); treeSet.add(new Point(1, 1)); treeSet.add(new Point(1, 2)); System.out.println(treeSet.size()); // 결과: 1 x만 비교하여 TreeSet 자료구조를 사용했을 때는 1개의 요소밖에 존재하지 않았습니다. HashSet이라면 객체의 hashCode()와 equals()를 비교하여 2라는 결과가 나왔을 텐데… ...

February 29, 2024 · Lee WooJin

해시(Hash) 자료구조와 충돌 회피 기법

해시 자료구조는 16자리의 번호의 일부분을 index로 사용하는 자료구조입니다. 해시 함수란? 임의 길이의 데이터를 고정된 길이의 데이터로 대응시키는 함수 왜 일부분만 사용하는가? 모든 해시를 배열로 가지고 있으면 10^16의 배열이 필요합니다. 이는 40페타 바이트를 차지하게 됩니다. 그렇기에 모든 hash 값을 사용하는 게 아닌 일부분만의 값을 사용하여 해시 테이블을 생성합니다. 충돌 회피 방법 1. Chaining Key가 중복된 노드를 LinkedList로 연결하여 관리합니다. Java의 STL 자료구조는 Chaining 방식을 사용합니다. 주의사항: 충돌이 빈번할수록 성능이 안 좋아지고, 해시 충돌이 한 곳으로 몰렸다면 O(N)의 시간 복잡도를 가질 수 있습니다. ...

February 5, 2024 · Lee WooJin

이펙티브 자바 - 다 쓴 객체 참조를 해제하라

다 쓴 객체 참조를 해제하라 JDK 8버전 Stack 코드 문제점 public class Stack { private Object[] elements; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() { elements = new Object[DEFAULT_INITIAL_CAPACITY]; } public void push(Object e) { ensureCapacity(); elements[size++] = e; } public Object pop() { if (size == 0) throw new EmptyStackException(); return elements[--size]; // 문제 발생! } private void ensureCapacity() { if (elements.length == size) elements = Arrays.copyOf(elements, 2 * size + 1); } } JDK 8버전에서는 현재 index를 변경해서 stack의 top을 관리하지만, pop()을 할 때 TOP의 값을 줄이기만 합니다. 이 부분에서 메모리 누수가 발생합니다. ...

December 20, 2023 · Lee WooJin

Java 동적 프록시 (Dynamic Proxy) 이해하기

프록시의 문제점 프록시는 기존 코드에 영향을 주지 않으면서 타깃의 기능을 확장하거나 접근 방법을 제어할 수 있는 유용한 방법입니다. 하지만 데코레이터 패턴을 활용해서 부가적인 기능을 하는 코드를 클래스마다 매번 정의해야 하고, 클래스도 매번 넣어야 했습니다. 여기서 오는 코드의 중복과 다수의 클래스가 생겨났습니다. 이러한 문제점들을 해결해주는 것이 바로 동적 프록시입니다. 자바에서 동적 프록시를 사용하기 위한 클래스 Proxy InvocationHandler 서비스 로직 인터페이스 서비스 로직 구현체 부가 기능 구현체 (InvocationHandler를 구현한) Proxy 클래스를 기반으로 동적 프록시가 생성되고, 필드에 클래스 로더, 서비스 로직 인터페이스, 부가 기능 구현체를 넣어주면 됩니다. ...

November 28, 2023 · Lee WooJin

Java GC (Garbage Collection) 이해하기

GC란? 프로그램이 동적으로 할당했던 (heap 영역) 메모리 영역 중 필요 없게 된 영역을 여러 알고리즘을 통해 해제하는 것입니다. 장점 메모리 누수 방지 해제된 메모리에 접근 방지 해제한 메모리 또 해제 방지 단점 GC 작업은 순수 오버헤드 개발자는 언제 GC가 메모리를 해제하는지 모릅니다 GC 알고리즘 Reference Counting 객체에 접근할 수 있는 카운팅 넘버를 통해 현재 참조 중인지 확인하는 알고리즘 문제점: 힙 객체가 서로 참조하고 있으면 순환 참조로 GC 제거 대상에서 제외됨 ...

November 9, 2023 · Lee WooJin

프레임워크와 라이브러리의 차이

라이브러리란? 라이브러리는 특정 기능을 수행하는 코드의 집합입니다. 개발자가 필요할 때 호출하여 사용합니다. 실행 함수 public static void main(String[] args) { double library_time = System.nanoTime(); double library = round(20.555d, 2); double library_endTime = System.nanoTime(); double custom_time = System.nanoTime(); double custom = notUseLibrary(20.555d, 2); double custom_endtime = System.nanoTime(); System.out.println("라이브러리: " + library + " 걸린시간: " + (library_endTime-library_time)); System.out.println("커스텀: " + custom + " 걸린시간: " + (custom_endtime - custom_time)); } 직접 구현 코드 구현 시간: 약 10분 ...

July 19, 2023 · Lee WooJin

정적 팩토리 메소드의 장단점

들어가며 오늘 이펙티브 자바를 읽으면서 정적 팩토리의 장점에 대해서 읽는데 뭔가 체감이 되지 않았습니다. 그래서 책에서 말하는 장점 코드에 대해서 작성해보고 설명해보는 시간을 가지려고 합니다. 정적 팩토리 메소드의 장점 1. 이름을 가질 수 있다 일반 public 생성자는 많이들 익숙하시죠? 하지만 우리가 생성자를 만들 때 함수명처럼 이름이 존재하지 않았어요. 정적 팩토리 메소드는 이름을 가질 수 있어 무슨 일을 하고 어떤 걸 만드는지 파악할 수 있어요! public class Car { private String model; private int year; private Car(String model, int year) { this.model = model; this.year = year; } public static Car createSportsCar() { return new Car("Sports Car", 2023); } public static Car createFamilyCar() { return new Car("Family Car", 2023); } } 2. 호출될 때마다 인스턴스를 새로 생성하지 않아도 된다 DatabaseConnection 객체를 가져오고 싶을 때마다 새로 생성하는 게 아닌 기존에 존재하면 재사용하고 없다면 생성해서 반환하는 형식을 가질 수 있습니다. ...

July 7, 2023 · Lee WooJin

스프링부트 터미널 build 실행 오류 (JDK 17)

문제: JAVA 17 버전을 호환하지 못함 터미널로 gradlew build를 실행했지만 classpath를 찾지 못할 뿐더러 jdk 17버전이 아니라는 경고가 발생한다. 주의 사항 스프링부트 2.6.x 버전 이상부터 사용이 가능하다. build.gradle에서 17버전인지 확인! 인텔리제이 빌드, 실행, 테스트 설정하기 jdk 17버전을 다운받는다. Oracle JDK 17 다운로드 설정 - build - gradle - 17ver 설정 프로젝트 구조 - SDK - 17ver 생성 프로젝트 구조 - 프로젝트 프로젝트 구조 - 모듈 - 17ver 설정 ...

April 4, 2023 · Lee WooJin