java9-future

Java 9 특정 정리


1. 개요

Java9 은 많은 기능을 내포하고 출시 되었다. 새로운 언어의 특징을 가지고 있지 않지만, 새로운 API와
정보, 진단을 위한 커멘드 처리 들과 함께 개발자 들을 위해 출시 되었다.

2. 모듈 시스템 - Jigsaw Project

모듈 시스템은 OSGI 프레임워크의 시스템과 비슷한 기능을 제공한다.
모듈은 Defendencies(라이브 러리 종속성)를 가지는 개념이며, public API를 제공 할 수 있으며,
Hidden/Private 로 제공할수 있다.

가장 중심이 되는 기능중에 하나는 장치에서 메모리를 작게 사용하여 실행될수 있게 JVM 에 제공하는 것이며,
JVM 은 어플리케이션에서 필수로 가져야 하는 API 들과 해당모듈로만 실행 할수 있다.

또한, com.sun.*같은 JVM 내부의 API들은 어플리케이션 코드에서 더이상 접근 할수 없다.

간단히, 모듈을 입력하는것은 자바코드의 최상위 계층에서 module-info.java 로 설명한다.

예시:

1
2
3
4
module com.baeldung.java9.modules.car {
requires com.baeldung.java9.modules.engines;
exports com.baeldung.java9.modules.car.handling;
}

해당 모듈은 car 라는 모듈이며 해당 모듈은 engine 모듈을 필수로 가져야 하며 또한 handling 모듈에 package 를 제공한다.

3. 새로운 HTTP Client

기존 사용하던 HttpURLConnection 을 대체하기 위해 제공 된다.
새로운 API는 java.net.http package 하위에 위치 한다.

HTTP/2 ProtocolWebSocket의 처리를 제공하며 성능상 Apache HttpClient, Netty, Jetty 와 비교하여도 뒤지지 않는다.

업데이트: HTTP Client JEP 는 인큐베이터 모듈로 이동하였으며, java.net.http 대신에 jdk.incubator.http 하위로 이동하였다.

3.1. 간단한 GET Request 예제

API 는 빌더 패턴(Builder Pattern)으로 편하고 쉽게 사용이 가능하다.

1
2
3
4
5
6
7
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://postman-echo.com/get"))
.GET()
.build();

HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandler.asString());

4. Proccess API

Proccess API 는 OS 시스템의 처리를 제어하기 위해 개선 되었다.

4.1. Proccess 정보

클래스 java.lang.ProcessHandle 대부분 새로운 기능을 포함한다.

1
2
3
4
5
6
7
8
ProcessHandle self = ProcessHandle.current();
long PID = self.getPid();
ProcessHandle.Info procInfo = self.info();

Optional<String[]> args = procInfo.arguments();
Optional<String> cmd = procInfo.commandLine();
Optional<Instant> startTime = procInfo.startInstant();
Optional<Duration> cpuUsage = procInfo.totalCpuDuration();

현재 메소드는 현재 실행중인 JVM의 프로세스의 객체를 반환한다.
info 서브 클래스는 프로세스의 자세한 정보를 제공한다.

4.2. Proccess들 종료

하위 예제는 destroy() 메소드로 실행중인 모든 프로세스들을 종료한다.

1
2
3
4
childProc = ProcessHandle.current().children();
childProc.forEach(procHandle -> {
assertTrue("Could not kill process " + procHandle.getPid(), procHandle.destroy());
});

5. 약간의 Java 기본 문법 수정

5.1. Try-With-Resources

자바 7에서 try-with-resources 구문은 명령문이 관리하는 각 자원에 대해 새 변수를 선언해야 했다.

자바 9에서는 몆가지의 기능이 개선 되었다. : 만약 객체가 final 변수로 참조 되었다면,
try-with-resources 구문은 새로이 선언되는 변수없이 자원을 관리할수 있다.

1
2
3
4
5
6
7
8
MyAutoCloseable mac = new MyAutoCloseable();
try (mac) {
// do some stuff with mac
}

try (new MyAutoCloseable() { }.finalWrapper.finalCloseable) {
// do some stuff with finalCloseable
} catch (Exception ex) { }

5.2. Diamon Operator 확장.

이제 diamond operator는 익명 이너 클래스들과 함께 사용할수 있다.

1
2
3
4
5
6
7
8
9
FooClass<Integer> fc = new FooClass<>(1) { // anonymous inner class
};

FooClass<? extends Integer> fc0 = new FooClass<>(1) {
// anonymous inner class
};

FooClass<?> fc1 = new FooClass<>(1) { // anonymous inner class
};

5.3. 인터페이스 Private 모드.

인터페이스는 JVM 버전에서 private 메소드들을 사용할수 있으며, 해당 메소드는 default 메소드에서
사용이 가능하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
interface InterfaceWithPrivateMethods {

private static String staticPrivate() {
return "static private";
}

private String instancePrivate() {
return "instance private";
}

default void check() {
String result = staticPrivate();
InterfaceWithPrivateMethods pvt = new InterfaceWithPrivateMethods() {
// anonymous class
};
result = pvt.instancePrivate();
}
}}

6. JShell Command 라인 툴

자바의 선언문이나, 문법, 그리고 자바의 표현식을 JShell 로 API를 통해 검증 할수 있다.
자바의 메인 메소드와 함께 코드 스니펫, 그리고 클래스를 생성하는 필수적인 속성을 테스트하는데 편한 툴을 제공한다.

하위 예제는 JShell<JAVA_HOME>/bin 폴더를 찾아 자바 코드를 바로 실행하는것을 보여준다.

1
2
3
4
5
jdk-9\bin>jshell.exe
| Welcome to JShell -- Version 9
| For an introduction type: /help intro
jshell> "This is my long string. I want a part of it".substring(8,19);
$5 ==> "my long string"

JShell 은 파일 저장이나 파일 불러오기 같은 기능들을 shell 에서 처리할수 있게 한다.

1
2
3
jshell> /save c:\develop\JShell_hello_world.txt
jshell> /open c:\develop\JShell_hello_world.txt
Hello JShell!

코드 스니펫은 또한 파일 로딩을 실행할 수 있다.

7. JCMD 서브 커멘드

JCMD 서브 커멘드는 jcmd 커멘드라인을 통해 모든 클래스들을 로드할 수 있으며 상속 구조를 보여줄수 있다.

하위의 예제에서 JVM 이 실행 중일때 java.lang.Socket 이 로드되어 해당 클래스의 상속구조를 볼수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
jdk-9\bin>jcmd 14056 VM.class_hierarchy -i -s java.net.Socket
14056:
java.lang.Object/null
|--java.net.Socket/null
| implements java.io.Closeable/null (declared intf)
| implements java.lang.AutoCloseable/null (inherited intf)
| |--org.eclipse.ecf.internal.provider.filetransfer.httpclient4.CloseMonitoringSocket
| | implements java.lang.AutoCloseable/null (inherited intf)
| | implements java.io.Closeable/null (inherited intf)
| |--javax.net.ssl.SSLSocket/null
| | implements java.lang.AutoCloseable/null (inherited intf)
| | implements java.io.Closeable/null (inherited intf)

해당 예제에서 첫번째 파라메터는 JVM 의 프로세스 아이디(PID) 이며 해당 커멘드로 실행 할 수 있다.
다른 특징은 set_vmflag 이다. 해당 명령어로 서비스의 재시작 없이 JVM 을 온라인으로 수정가능하다.

모든 가능한 VM flags는 서브커멘드인 jcmd 14056 VM.flags -all 으로 찾을수 있다.

8. Multi-Resolution Image API

java.awt.image.MultiResolutionImage 는 다른 이미지를 다루는 방법을 하나의 객체로 요약하여 처리한다.
처리되는 이미지의 DPI 메트릭 을 기반으로 새로운 방법으로 변경하며 처리된다.

java.awt.Graphics 클래스는 현재 디스플레이 DPI 메트릭과 모든 추가되는 변경사항의 기반으로 여러개로 이미지를 처리하여
변경된 값을 가져온다.

java.awt.image.BaseMultiResolutionImage 는 기본 구현을 제공한다.

1
2
3
4
5
BufferedImage[] resolutionVariants = ....
MultiResolutionImage bmrImage
= new BaseMultiResolutionImage(baseIndex, resolutionVariants);
Image testRVImage = bmrImage.getResolutionVariant(16, 16);
assertSame("Images should be the same", testRVImage, resolutionVariants[3]);

9. 변수 처리

해당 API 는 java.lang.invoke 에 포함되어 있으며, VarHandle 과 MethodHandle 으로 구성되어 있다.
java.util.concurrent.atomic 클래스와 sun.misc.Unsafe 클래스와 비슷한 기능을 제공하고 있다.

10. Publish-Subscribe Framework

java.util.concurrent.Flow 는 Reactive Stream publish-subscribe 프레임워크를 지원하는 인터페이스들을 제공한다.
제공하는 인터페이스들은 JVM들이 실행될때 많은수의 비동기 시스템을 지원한다.

11. 통일된 JVM 로그

해당 특징은 JVM 의 모든 컴포넌트를 위한 기본적인 로그 시스템을 설명한다.
해당 기능은 로그처리를 위한 기반을 제공한다.
하지만 JVM의 모든 컴포넌트에서 현재 로그들을 호출하여 추가하지 않는다.
또한 자바 코드에서 추가되지 않는다.

로그 프레임워크는 테그들의 설정으로 정의된다. Ex - gc, compiler, threads, etc
커멘드 라인 파라메터인 -Xlog 로 시작시에 로그 시스템을 실행하여 사용한다.

하위 커멘드는 gc 테그로 디버그 레벨의 로그메세지를 사용하며 해당 로그는 gc.txt 파일로 어떠한 추가 정보 없이 저장된다.

1
java -Xlog:gc=debug:file=gc.txt:none ...

-Xlog 는 예제에서 아웃풋의 옵션을 가능하게 한다. 로그의 설정은 jcmd 커멘드를 실행하여 변경될수 있다.
하위 예제는 CG 로그의 정보를 설정하고 -gc_logs 파일로 재 전송하는 처리를 한다.

1
jcmd 9615 VM.log output=gc_logs what=gc

12. 새로운 API 들

12.1. 불변한 Set 클래스

java.util.Set.of()- 속성들을 불변하게 설정한다. Java8 에서는 각각의 설정된 속성이 각각 코드라인에서 필수이어야 한다.
이제 하위와 같이 간단히 설정한다.

1
Set<String> strKeySet = Set.of("key1", "key2", "key3");

Set 타입으로 리턴된 현재 메소드는 JVM 인터넬 클래스 이다. : java.util.ImmutableCollections.SetN 클래스는 public java.util.AbstractSet
클래스를 상속 받는다. 이 클래스는 변경이 불가능 하다. - 만약 속성을 추가하거나 삭제 하면 UnsupportedOperationException 예외가 발생한다.

또한 커다란 배열을 Set 클래스로 동일한 메소드를 사용하여 변경할수 있다.

12.2. Optional to Stream

java.util.Optional.stream() 은 Optional 속성으로 편하게 Stream 클래스를 사용할 수 있다.

1
2
3
4
List<String> filteredList = listOfOptionals
.stream()
.flatMap(Optional::stream)
.collect(Collectors.toList());

13. 원문

Java 9 New Features By baeldung

영어 공부를 위해 퍼왔습니다. 저작권이 문제가 된다면 삭제 하겠습니다.

Share