일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
- covariant
- HDFS
- Generic
- Perfect Watermark
- event time
- watermarks
- contravariant
- Perfect Watermarks
- 공변
- coroutines
- ingestion time
- flink watermark
- processing time
- java
- Coroutine
- Stream
- MapReduce
- apache flink
- Heuristic Watermarks
- Hadoop
- kotlin
- lambda
- flink watermarks
- watermark
- 가변성
- flink
- Heuristic Watermark
- 불공변
- Generics
- Today
- Total
mm Home
Java 9 features 본문
최근 발표된 Java 9의 새로운 피쳐들에 대해 많은 글들이 올라온다.
능력은 안되지만 나도 나름대로 공부한걸 정리해보았다.
try-with-resources
- java 7 에서 추가되었던 try-with-resources 구문을 더 간결하게 사용할 수 있다.
- try-with-resources : AutoCloseable 를 구현한 클래스에 대해 try 구문이 끝날때 자동으로 close 처리해주는 기능
변경된 내용
- 추가 사항
- try-with-resources 는 동작은 아래와 같다.
- 조금 더 쉽게 표현하면
- try 구문이 실행되고 나서 바로 close 처리를 진행한다.
- try 구문에서든 close() 메소드 안에서 에러가 발생했다면 catch() 로직을 타게 된다.
- try → close() → catch() → finally 순.
- 따라서 close()에서 에러가 발생할 수 있는 가능성이 있다면 catch나 finally에서 예외처리를 해주어야 할 것이다.
interface에 private 접근자 사용 가능
- java 8 에서 인터페이스에 대해 default와 static 메소드 선언이 가능해짐.
- 추상화를 하는 과정중에 default와 static 메소드를 캡슐화할 필요가 생겼기 때문에 java 9에서는 private 접근자가 가능해지도록 변경함.
immutable collection factory 추가
- java 9 미만에서 Collection 에 대해서 immutable 하려면 Collections(java8 util)을 사용하거나 Third-party 쓰거나 직접 구현하거나... 하여튼 사용에 불편했음
- immutable Collection Factory 추가
Java 9 Diamond Operator for Anonymous Inner Classes
- 익명클래스에 대한 타입 추론 가능
Optional Class imporvement
- or() 메소드 추가 : value가 비어있을 때 or 메소드를 실행한 결과의 Optional을 돌려줌 (lazy)
- ifPresentOrElse() 메소드 추가 : value에 값이 있을 때 특정 행동을 하고 싶다면..
- Stream() 메소드 추가 : Optional 클래스도 Stream 처리가 가능해짐.
Stream API Improvements
- takeWhile/dropWhile 추가
- takeWhile : Predicate가 만족하는 때까지만 순회하여 요소들만 take함.
- dropWhile : Predicate가 만족할 때까지 순회하여 drop함. (순회한 subset을 drop)
- iterate 메소드 추가
- 기존에 있던 iterate 는 무한한 iterate
- ofNullable 메소드 추가
- 스트림의 요소에 null이 포함되지 않기를 바라는 경우에, ofNullable을 사용할 수 있다. 값이 비어있다면 Optional.empty() 반환.
@Deprecated Improvements
- 기존 Deprecated는 컴파일할 때 warning 경고만 해주고 언제부터 시작됐는지, 앞으로 삭제될 예정인지에 대한 명세가 없었음.
- since(언제부터)와 forRemoval(이후에 삭제될 예정인지)이라는 변수 추가.
Java 9 REPL(Read Evaluate Print Loop) : JShell
- JDK 내에 JShell 이라는 Interpreter 제공.
- $ jshell
- https://docs.oracle.com/javase/9/jshell/introduction-jshell.htm#JSHEL-GUID-DA9FA090-7015-4F30-BBD0-5F6ED0EBDF91
- 학습 용도나 간단한 검증에 사용할수 있을것 같으나.. 이외에는 유용하지 않을것 같다.
HTTP 2 Client
- HTTP/2.0 을 지원하는 HttpClient 클래스가 추가됨.
- sendAsync 메소드를 통해 CompletableFuture를 반환하는 비동기 개발도 가능.
- 간략히 HTTP/2.0 의 장점을 보면
- Multiplexed Stream : 한 커넥션으로 동시에 여러개의 메시지를 주고 받을 수 있음. (응답도 순서에 상관없이 받는다.) - HTTP/1.1의 Keep-Alive, Pipelining 의 개선
- Stream Prioritization : 특정 자원의 수신이 늦어질 경우, 의존성있는 자원도 렌더링이 늦어지는 문제가 발생할 수 있다. 2.0에서 자원간 의존관계를 설정하여 해결할 수 있음.
- Server Push : 클라이언트의 요청없이도 서버는 자원을 마음대로 보내줄 수 있다.
- Header Compression : HTTP 특성상 헤더가 중복적으로 전송하는 경우가 많다. 여러 요청에 대해 중복값이 존재하는 경우 압축을 통해 성능을 향상시킴
Process API Improvements
- 프로세스의 정보를 가져오고 특정 행동을 handle 할 수 있는 API가 추가되었다.
- 자세한 내용은 http://javasampleapproach.com/java/java-9-process-api
Unified JVM Logging
- 로깅을 하기 위한 최소한의 로깅 API와 해당 메시지의 사용자를위한 서비스 인터페이스를 제공한다.
- 기존에 로깅을 이용하려한다면 logback이나 log4j 를 클래스패스내에 두어야 했다. (slf4j 의존성도 추가해야함.. 귀찮)
- Java 9에서 특정 로깅 구현체가 존재하지 않는다면, JDK의 기본 로거가 사용된다.
- 실제 서비스에서 사용할 용도는 아닌것 같다.
CompletableFuture API Improvements
- java 8 에서 비동기지원을 위해 CompletableFuture가 도입되었었다.
- 비동기 개발시에 불편함(callback-hell). callback 을 통한 비동기 지원의 편이성을 위해 도입.
- method chaining 으로 콜백 등록, 예외처리 등을 편리하게 개발 가능
- delay와 timeout에 대한 강화
- CompletableFuture 완료를 특정 시간만큼 지연시킨다던지, 제한시간을 두도록 할 수 있음
- defaultExecutor()
- 비동기 처리를 위한 default Executor 생성.
- newIncompleteFuture()
- 기존의 서브 클래스를 유지한, 새로운 CompletableFuture 를 생성해서 되돌려줌. (주로 CompletableFututure 내부적으로 사용됨)
- copy()
- 새로운 CompletableFututure 를 리턴한다.
- minimalCompletionStage()
- 기존과 같은 동작을 하는 새로운 CompletionStage를 반환하지만, 결과를 가져오려고 하면 UnsupportedOperationException 예외를 던짐.
- completeAsync ()
- orTimeout ()
- completeOnTimeout ()
- 유틸리티 메소드도 추가됨
- Executor delayedExecutor(long delay, TimeUnit unit, Executor executor)
- Executor delayedExecutor(long delay, TimeUnit unit)
- <U> CompletionStage<U> completedStage(U value)
- <U> CompletionStage<U> failedStage(Throwable ex)
- <U> CompletableFuture<U> failedFuture(Throwable ex)
Java Platform Module System (Jigsaw project)
- 기존 자바의 라이브러리 문제점
- classpath내에 있다면 모든 public 클래스는 접근 가능함.
- public API의 무분별한 사용이 일어남.
- classpath 내의 의존성 관리가 어려움
- 필요한 라이브러리가 이미 있는지, 중복된 항목은 얼마나 잇는지 파악하기 어려움
- 특정 버전에 대한 선택 문제
- ex. A클래스는 특정 라이브러리의 v1 을 바라보아야 하고, B클래스는 v2를 바라보아야 하는 경우
- 성능 문제
- Hadoop 을 예로 살펴보면.
- 110 개의 jar가 있음.
- public 클래스를 로드하기위해 클래스 로더는 110개의 jar를 다 찾아야 한다. 110개의 jar는 클래스간 12,000 개 이상의 interaction이 있다.
- 모두 뒤지면서 찾으려면 당연히 성능이 안좋다.
- classpath내에 있다면 모든 public 클래스는 접근 가능함.
- 자바 9에서는?
- JDK, JRE, JAR 등을 더 작은 모듈 단위로 나눔.
- 프로젝트마다 모듈 구성을 위한 설정을 할 수 있음.
- 모듈간 public 접근에 대한 제한
- 모든 클래스 단위의 제한을 두는 것이 아니라, 패키지 단위의 접근 컨트롤을 한다.
- 원하지 않는 로직 내부를 감출 수 있음 → 캡슐화!
- 모듈간 종속성도 표현 가능
- 성능 개선
- 단일 책임 (SRP)
- 아쉽게도 특정 버젼에 대한 선택문제는 해결되지 않았다.
- JVM은 클래스 로더에 의해 클래스들을 로드 하는데, 버전에 따른 로드를 하는게 불가능함.
- JDK, JRE, JAR 등을 더 작은 모듈 단위로 나눔.
- 모듈은 어떻게??
- 패키지의 상위 디렉토리에 module-info.java 라는 파일을 생성해 모듈 설정을 해야한다.
- 해당 모듈의 이름을 설정한다
- 설정 내부에 접근 가능한 패키지는 export (export 선언이 되어있지 않은 패키지는 모두 접근 불가능함)
- 설정에 해당 모듈이 필요로 하는 패키지는 requires 로 필요 패키지를 명시적으로 선언한다.
- 패키지의 상위 디렉토리에 module-info.java 라는 파일을 생성해 모듈 설정을 해야한다.
- JVM 경량화
- 임베디드 시스템같이 자원이 제한적인 상황에서 JVM의 경량화가 가능해짐.
- JDK도 모듈들로 이루어져 있다. 여기서 필요한 모듈만 사용할 수 있다.
- 새로 추가된 jlink 를 통해 런타임 이미지를 생성할 수 있음.
- 실행에 필요한 것들을 패키징 하는 것. (JDK 전체를 다운받을 필요가 없다)
- JRE에서 jlink를 실행.
- Modular Jar
- 기존 라이브러리로 jar를 매우 많이 사용 중.
- 컴파일된 module-info.class를 포함하는 것 빼곤 동일하다
- 있으면 Modular Jar.
- 없으면 비모듈 Jar (기존에 쓰던 일반 Jar)
- 하위 버전과 호환된다. (module-info.class가 이전 JVM에서 무시됨)
- 모듈과 비모듈을 어떻게 구분?
- 모듈은 애플리케이션 module-path에 존재하고,
- 비모듈은 기존과 동일하게 classpath에 존재한다.
- cli 로 모듈 빌드하려니 너무 빡셈..
Reactive Streams API 추가
여기 참고
개인적으로 Java 9는 Java 8만큼의 큰 메리트는 없는 것 같았다.
Module 시스템도 웹 어플리케이션 개발자 입장에서는 큰 관심이 생기지 않았다, 기존의 라이브러리가 가지는 문제에 완전한 해결책은 아닌것 같다라는 생각이 들기도 했고.
Stream API를 공식 지원하는게 개발자로서 그나마 관심이 가지는 부분이었다. 다만 이마저도 스프링에서 추가된 Reactor 가 내부적으로 Java 9의 Stream API를 사용하고 있지 않고 범용성면에서 훨씬 더 유용하다는 느낌이다. 스프링5를 쓰면 Java 9의 Stream API를 많이 쓸것 같지 않았다.
'개발 > Java' 카테고리의 다른 글
Java - Generics (0) | 2019.12.04 |
---|---|
Java - static (0) | 2017.09.06 |
Java 8 - Stream (0) | 2017.08.11 |
Java 8 - Lambda Translation (0) | 2017.08.10 |
Java 8 - 람다 표현식 (2) | 2017.08.10 |