Language/Java 56

무지성 byte[] 사용하지 않기! (feat. Apache Commons Email)

HTML 삽입 미리보기할 수 없는 소스 포스팅 제목을 무지성byte[] 사용하지 않기라고 했는데 불필요하게 전체 byte[] 할당하지 않기라고 봐주면 좋을 것 같다. 해당 포스팅에서는 서비스 운영 중 byte[]로 인해 심각한 문제가 생겼고, 오픈소스 기여까지 하게된 내용을 작성한다. TPS가 심각하게 낮음 메일 파일(약 20MB)을 읽어서 파일의 내용 중 일부를 화면에 노출하는 기능을 개발했다. 그런데 POD 1대의 TPS가 1.7 정도밖에 나오지 않았다. 전체 HTTP 트랜잭션은 5.42초였다. 그래서 아래와 같이 각 로직의 수행 시간을 측정해봤다. 그 결과 parse 로직이 3787ms가 걸린다는 것을 알 수 있었다. parse parse()의 경우 외부 라이브러리(apache-commons-ema..

Language/Java 2024.03.24

자바 NIO 간략하게 알아보기!

Java NIO 자바에서 InputStream, OutputStream과 같이 *Stream으로 통신하는 모델을 Java IO 모델이라고 한다. 패키지는 java.io.*에 속한다. 자바 NIO란 New Input/Output의 약자이다. 아래는 Java IO와 Java NIO의 차이이다. 구분 IO NIO 입출력 방식 Stream Channel 데이터 단위 Byte, Character Buffer 데이터 흐름 단방향 양방향 논블로킹 지원 X O 가장 큰 차이는 Java IO는 Stream 기반, NIO는 Channel 기반으로 동작한다. NIO는 java.nio.* 패키지에 속한다. NIO는 아래와 같이 Buffer를 통해 데이터를 읽거나 써서 파일과 통신한다. Java NIO의 모든 IO는 Chann..

Language/Java 2024.01.22

자바에서 동시성을 다룰 때 주의할 점!

아래는 이펙티브 자바의 내용 중 동시성에 대한 부분을 정리한 것이다. Effective Java는 동시성을 사용할 때의 몇가지 주의사항과 가이드라인을 제시한다. 동기화된 메서드 설계 시 주의할 점 동기화된 메서드를 작성할 때 중요한 것은 재정의할 수 있는 메서드를 호출해선 안되고 클라이언트가 넘겨준 함수 객체도 사용하면 안된다는 것이다. public class ObservableSet extends ForwardingSet { public void addObserver(SetObserver observer) { synchronized (observers) { observers.add(observer); } } public boolean removeObserver(SetObserver observer) {..

Language/Java 2023.10.17

Java 검사(Checked) 예외와 비검사(Unchecked) 예외

아래는 이펙티브 자바의 내용 중 예외에 대한 부분의 일부이다. 이펙티브 자바도 그렇고, 예외도 그렇고 포스팅할 내용이 너무 너무 많아서 다 정리할 수 없어서 아쉽다..! 일반적으로 검사 예외와 비검사 예외를 CheckedException, UncheckedException이라고 명명하지만, 해당 포스팅에서는 Effective Java의 명칭대로 검사 예외와 비검사 예외라고 명칭한다. 검사 예외와 비검사 예외 Throwable 클래스를 상속하는 것은 Error와 Exception이 있다. Exception을 상속하면서 RuntimeException을 상속하지 않으면 검사 예외이고, RuntimeException을 상속하면 비검사 예외라고 부른다. 참고로 Error는 Throwable을 상속하고 OutOfM..

Language/Java 2023.10.12

Java - switch 대신 Enum을 검토해보자!

아래 내용은 Effective Java 내용에 기반한다. 상수 대신 Enum 아래 코드를 보자. public static final int APPLE_FUJI = 0; public static final int APPLE_PIPPIN = 1; public static final int APPLE_GRANNY_SMITH = 2; public static final int ORANGE_NAVEL = 0; public static final int ORANGE_TEMPLE = 1; public static final int ORANGE_BLOOD = 2; 이 코드의 영향은 어떤 것이 있을까..? 상수의 값이 바뀌면 반드시 다시 컴파일해야 한다. 추적이 어렵다. (0, 1, 2로 저장되니까) 추적이 어렵다는 이..

Language/Java 2023.10.05

Java 21의 주요 패치 내용 살펴보기!

이번 포스팅에서는 Java 21이 2023년 9월(작성일 기준 이번달)에 출시한다. 개인적으로 Java 21의 패치 내용이 되게 인상깊은데 Java 21 버전의 변경사항에 대해 알아보자. SequencedCollection 기존에 List에서 첫 번째 요소와 마지막 요소를 구할 때는 아래와 같이 코드를 작성했다. String first = list.get(0); // 첫 번째 요소 String last = list.get(list.size() - 1) // 마지막 요소 이런 부분들 구현을 외부에 노출하므로 가독성이 많이 떨어진다. Java 21부터는 SequencedCollection이라는 인터페이스를 제공한다. public interface SequencedCollection extends Collec..

Language/Java 2023.09.10

JVM 옵션으로 튜닝 이해하기!

JVM 튜닝에 앞서 고려해야 할 점이 성능 중 어떤 부분을 우선할 것인가를 정해야 한다. 일반적으로 성능이란 TPS와 Latency로 나뉜다. 1. GC 알고리즘 GC 알고리즘을 예로 들면 처리량(TPS)이 목적이면 Parallel GC, 응답 시간이 목적이면 CMS GC, G1 GC가 유리하다. Parallel GC는 Full GC를 수행하면서 GC 소요 시간이 길지만 빈도가 적어서 총 STW 시간이 적다. 그래서 처리량이 높다. CMS, G1 GC의 경우 GC를 짧지만 빈번하게 수행하므로 처리량이 낮지만 응답시간이 빠르다. 추가로 CPU Core의 코어가 싱글이라면 Serial GC를 사용할 수 있고, CPU Core가 멀티 코어이고 Ram이 4GB 이상이라면 한 번에 여러개의 객체를 처리할 수 있는..

Language/Java 2023.08.01

메일 발송 시 OOM 해결하기! (with. FilterOutputStream)

평화롭던 어느날 메일 API에서 OOM이 터졌다. 발생한 End-point는 메일 발송으로 확인했다. 메일 원문은 40MB였고 개발 서버에서 테스트를 해봤다. 동일 본문으로 메일 발송 요청 1번에 결과 메모리 사용량이 117MB 정도 급증했다. 세부적으로는 2단계 메모리가 튀는 것으로 확인된다. 1차: 724MB -> 761MB 2차: 761 MB -> 841MB 바로 의심했던 것이 발송 이벤트였다. 비동기 이벤트가 두 건 발행되고 있었다. Forward Event Archive Event Line Separator 확인 결과 1. 발송, 2. 포워드 이벤트 핸들러, 3. 아카이브 이벤트 핸들러에서 아래 로직을 수행한다. 코드를 보면 ByteArrayOutputStream에 eml 파일 내용을 저장한다...

Language/Java 2023.07.24

JavaMail API 튜닝기! (메모리 성능 개선!)

이슈 Handle dispatch failed: nested exception is java.lang.OutOfMemoryError: Java heap space 어느날 특정 end-point에서 OOM이 터졌다. 아직까지 일부 사용자에게만 운영중인 서버라서 OOM이 터지는 것은 뭔가가 잘못되었다는 것을 의미한다. 리소스를 확인한 결과 실제로 메모리가 들쑥날쑥했고, OOM으로 인해 파드가 여러번 재실행되었다. 본문 내용 해당 본문을 확인해본 결과 아래와 같았다. 원문 크기: 38MB Part (첨부파일): 총 10개 - 하나 당 3~4MB 정도 첨부파일 조회 Flow 아래는 사용자가 Java-Mail-API를 사용하는 해당 서버에서 첨부파일을 조회할 때 발생하는 동작이다. 해당 원문과 Flow를 그려보니..

Language/Java 2023.07.19

Java - (JDK17에서는) String vs StringBuilder

Java 관련된 질문 중 String과 StringBuilder의 차이를 묻는 경우가 많다. 우리는 잘 알고 있는가..? 흔히 알려진 Java 관련 질문 중에서도 잘못된 질문과 답이 아주 많다고 생각한다. 대표적인 것 중 CheckedException과 UncheckedException의 대표적인 차이가 트랜잭션이 롤백된다는 것이다. 사실 CheckedException과 UnCheckedException은 근본적으로 트랜잭션과 아무 관련이 없다 (https://www.youtube.com/watch?v=_WkMhytqoCc) (무지성으로 공부하면서 Ctrl + C, Ctrl + V 한 결과..) String과 StringBuilder의 차이도 너무 무지성으로 외우는 경우가 많다. (나도 그랬다.) Str..

Language/Java 2023.04.04