본문 바로가기
JAVA/버전.

자바 버전별 신규기능, 특징 정리 - JDK9

by 램쥐뱅 2018. 7. 2.


2017년 9월 21일 Java SE 9, JDK9 가 발표되었다.


근래에 JDK8의 람다와.. 심층학습 관련에 꼿혀 새로운 버전이 나왔음에도 정리를 미뤄왔다.


OpenJDK 를 살펴보니 ..


102: Process API Updates
110: HTTP 2 Client
143: Improve Contended Locking
158: Unified JVM Logging
165: Compiler Control
193: Variable Handles
197: Segmented Code Cache
199: Smart Java Compilation, Phase Two
200: The Modular JDK
201: Modular Source Code
211: Elide Deprecation Warnings on Import Statements
212: Resolve Lint and Doclint Warnings
213: Milling Project Coin
214: Remove GC Combinations Deprecated in JDK 8
215: Tiered Attribution for javac
216: Process Import Statements Correctly
217: Annotations Pipeline 2.0
219: Datagram Transport Layer Security (DTLS)
220: Modular Run-Time Images
221: Simplified Doclet API
222: jshell: The Java Shell (Read-Eval-Print Loop)
223: New Version-String Scheme
224: HTML5 Javadoc
225: Javadoc Search
226: UTF-8 Property Files
227: Unicode 7.0
228: Add More Diagnostic Commands
229: Create PKCS12 Keystores by Default
231: Remove Launch-Time JRE Version Selection
232: Improve Secure Application Performance
233: Generate Run-Time Compiler Tests Automatically
235: Test Class-File Attributes Generated by javac
236: Parser API for Nashorn
237: Linux/AArch64 Port
238: Multi-Release JAR Files
240: Remove the JVM TI hprof Agent
241: Remove the jhat Tool
243: Java-Level JVM Compiler Interface
244: TLS Application-Layer Protocol Negotiation Extension
245: Validate JVM Command-Line Flag Arguments
246: Leverage CPU Instructions for GHASH and RSA
247: Compile for Older Platform Versions
248: Make G1 the Default Garbage Collector
249: OCSP Stapling for TLS
250: Store Interned Strings in CDS Archives
251: Multi-Resolution Images
252: Use CLDR Locale Data by Default
253: Prepare JavaFX UI Controls & CSS APIs for Modularization
254: Compact Strings
255: Merge Selected Xerces 2.11.0 Updates into JAXP
256: BeanInfo Annotations
257: Update JavaFX/Media to Newer Version of GStreamer
258: HarfBuzz Font-Layout Engine
259: Stack-Walking API
260: Encapsulate Most Internal APIs
261: Module System
262: TIFF Image I/O
263: HiDPI Graphics on Windows and Linux
264: Platform Logging API and Service
265: Marlin Graphics Renderer
266: More Concurrency Updates
267: Unicode 8.0
268: XML Catalogs
269: Convenience Factory Methods for Collections
270: Reserved Stack Areas for Critical Sections
271: Unified GC Logging
272: Platform-Specific Desktop Features
273: DRBG-Based SecureRandom Implementations
274: Enhanced Method Handles
275: Modular Java Application Packaging
276: Dynamic Linking of Language-Defined Object Models
277: Enhanced Deprecation
278: Additional Tests for Humongous Objects in G1
279: Improve Test-Failure Troubleshooting
280: Indify String Concatenation
281: HotSpot C++ Unit-Test Framework
282: jlink: The Java Linker
283: Enable GTK 3 on Linux
284: New HotSpot Build System
285: Spin-Wait Hints
287: SHA-3 Hash Algorithms
288: Disable SHA-1 Certificates
289: Deprecate the Applet API
290: Filter Incoming Serialization Data
291: Deprecate the Concurrent Mark Sweep (CMS) Garbage Collector
292: Implement Selected ECMAScript 6 Features in Nashorn
294: Linux/s390x Port
295: Ahead-of-Time Compilation
297: Unified arm32/arm64 Port
298: Remove Demos and Samples
299: Reorganize Documentation



많군.


주요 내용을 보면.



102: Process API Updates


운영 체제 프로세스 제어 및 관리를 위한 API가 향상되었다.


// current Process

ProcessHandle processHandle = ProcessHandle.current();

 

processHandle.getPid();

processHandle.isAlive();

processHandle.children().count();

processHandle.supportsNormalTermination();

 

ProcessHandle.Info processInfo = processHandle.info();

 

processInfo.arguments();

processInfo.command();

processInfo.totalCpuDuration();

processInfo.user();

 

// all Processes

Stream<ProcessHandle> processStream = ProcessHandle.allProcesses();

 

// destroy Process

processHandle.destroy();




110: HTTP 2 Client


HTTP/2 와 WebSocket을 구현하는 새로운 HTTP 클라이언트 API가 제공되어 기존 HttpURLConnection API를 대체할수 있다.


// Sync Call

HttpResponse response = HttpRequest

               .create(new URI("http://www.ocado.com"))

               .body(noBody())

               .GET().send();

int responseCode = response.responseCode();

String responseBody = response.body(asString());

System.out.println(responseBody);


// Async Call

HttpRequest request = HttpRequest

               .create(new URI("http://www.ocado.com"))

               .body(noBody())

               .GET();

CompletableFuture<HttpResponse> future = request.sendAsync();

Thread.sleep(10);

if (!future.isDone()) {

    future.cancel(true);

    System.err.println("timeout");

    return;

}


HttpResponse response = future.get();




222: jshell: The Java Shell (Read-Eval-Print Loop)


Java 언어 를 인터프리터 언어의 쉘 처럼 사용할수 있는 대화식 REPL(Read-Eval-Print-Loop) 도구를 제공한다.

별도로 java 프로젝트를 만들거나 public static void main(String[] args) 를 번거롭게 정의 할 필요없이 그냥 코드를 작성하고 바로 실행하면 된다. jshell을 사용하여 Java 기능을 쉽게 배우고 테스트 해 볼 수 있다.




224: HTML5 Javadoc


이전 버전의 JDK에서는 HTML 4.01 형식을 사용하였으나 javadoc 도구를 개선하여 HTML5 마크업으로 생성이 가능하게 되었




225: Javadoc Search


Javadoc문서에서 프로그램 요소, tag가 지정된 단어나 문구를 검색하는데 사용할 수 있는 검색상자를 사이트상에서 사용할 수 있다.

검색 상자를 추가하면 문서 내의 프로그램 요소와 태그가 지정된 단어 및 구문을 검색하는데 사용할수 있게 된다.

검색 기능은 로컬로 구현되며 서버 사이드의 연산에 의존하지 않는다.




226: UTF-8 Property Files


ResourceBundle 클래스의 properties file 에 대한 기본적인 파일 인코딩이 기존 ISO-8859-1 에서 UTF-8 로 변경되었다.

시스템 프로퍼티에서 설정도 가능하다.


java.util.PropertyResourceBundle.encoding=ISO-8859-1




238: Multi-Release JAR Files


JAR 파일 형식을 확장하여 여러 Java 버전의 클래스 파일을 하나의 JAR 안에 공존시킬수 있다.

특정한 버전에서 작동하는 특정 클래스를 jar 안에 넣을수 있다.


Before - 특정 java 버전에서만 작동하는 A.class

jar root

  - A.class

  - B.class

  - C.class

  - D.class


Multi-Release JAR Files 아래에서는 java9 와 10 일때 사용되는 A.class, B.class

jar root

  - A.class

  - B.class

  - C.class

  - D.class

  - META-INF

     - versions

        - 9

           - A.class

           - B.class

        - 10

           - A.class


만약 위 Multi-Release 가 java9 에서 실행된다면 java9 버전의 A,B 클래스와 일반 C,D 클래스가 실행될 것이고

java10 에서 실행 된다면 java10 버전의 A 클래스와 java9 버전의 B 클래스 그리고 일반 C,D 클래스가 실행된다.



266: More Concurrency Updates (reactive stream)


응용 프로그램의 동시성 및 병렬처리 지원을 위해 병행성 관련 라이브러리들 지원이 늘어난다.

개선된 CompletableFuture 과 reactive stream 을 도입하였다.


java.util.concurrent.Flow

java.util.concurrent.Flow.Publisher

java.util.concurrent.Flow.Subscriber

java.util.concurrent.Flow.Processor


Reactive Stream 은 Observer Pattern 과 유사하다.



CompletableFuture.


delay

future.completeAsync(supplier, CompletableFuture.delayedExecutor(3, TimeUnit.SECONDS))

.thenAccept(result -> System.out.println("accept: " + result));


Timeout

// TIMEOUT = 3;

// doWork() takes 5 seconds to finish

 

CompletableFuture<String> future = 

doWork("JavaSampleApproach")

.orTimeout(TIMEOUT, TimeUnit.SECONDS)

.whenComplete((result, error) -> {

if (error == null) {

System.out.println("The result is: " + result);

} else {

System.out.println("Sorry, timeout in " + TIMEOUT + " seconds");

}

});



Reactive Stream.


Subscriber


import java.util.concurrent.Flow.Subscriber;

import java.util.concurrent.Flow.Subscription;


import com.journaldev.reactive.beans.Employee;


public class MySubscriber implements Subscriber<Employee> {


private Subscription subscription;

private int counter = 0;

@Override

public void onSubscribe(Subscription subscription) {

System.out.println("Subscribed");

this.subscription = subscription;

this.subscription.request(1); //requesting data from publisher

System.out.println("onSubscribe requested 1 item");

}


@Override

public void onNext(Employee item) {

System.out.println("Processing Employee "+item);

counter++;

this.subscription.request(1);

}


@Override

public void onError(Throwable e) {

System.out.println("Some error happened");

e.printStackTrace();

}


@Override

public void onComplete() {

System.out.println("All Processing Done");

}


public int getCounter() {

return counter;

}


}




Test Stream Data


public class Employee {


private int id;

private String name;

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public Employee(int i, String s) {

this.id = i;

this.name = s;

}

public Employee() {

}

@Override

public String toString() {

return "[id="+id+",name="+name+"]";

}

}


import java.util.ArrayList;

import java.util.List;


import com.journaldev.reactive.beans.Employee;


public class EmpHelper {


public static List<Employee> getEmps() {


Employee e1 = new Employee(1, "Pankaj");

Employee e2 = new Employee(2, "David");

Employee e3 = new Employee(3, "Lisa");

Employee e4 = new Employee(4, "Ram");

Employee e5 = new Employee(5, "Anupam");

List<Employee> emps = new ArrayList<>();

emps.add(e1);

emps.add(e2);

emps.add(e3);

emps.add(e4);

emps.add(e5);

return emps;

}


}


Reactive Stream Test


import java.util.List;

import java.util.concurrent.SubmissionPublisher;


import com.journaldev.reactive.beans.Employee;


public class MyReactiveApp {


public static void main(String args[]) throws InterruptedException {


// Create Publisher

SubmissionPublisher<Employee> publisher = new SubmissionPublisher<>();


// Register Subscriber

MySubscriber subs = new MySubscriber();

publisher.subscribe(subs);


List<Employee> emps = EmpHelper.getEmps();


// Publish items

System.out.println("Publishing Items to Subscriber");

emps.stream().forEach(i -> publisher.submit(i));


// logic to wait till processing of all messages are over

while (emps.size() != subs.getCounter()) {

Thread.sleep(10);

}

// close the Publisher

publisher.close();


System.out.println("Exiting the app");


}


}




267: Unicode 8.0


Java 8 은 Unicode 6.1을 지원한다.

Java 9 는 10,555자,  29개의 스크립트 및 42개 블록의 유니코드 8.0 표준을 지원한다.




269: Convenience Factory Methods for Collections


불변 Collection 을 만들수있는 메소드가 생겼다.


Before 


Set<String> set = new HashSet<>();

set.add("a");

set.add("b");

set.add("c");

set = Collections.unmodifiableSet(set);


Set<String> set = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("a", "b", "c")));


Set<String> set = Collections.unmodifiableSet(new HashSet<String>() {{

    add("a"); add("b"); add("c");

}});


java 8 stream 사용

Set<String> set = Collections.unmodifiableSet(Stream.of("a", "b", "c").collect(toSet()));


After


Set<String> set = Set.of("a", "b", "c");

List.of(a, b, c);

Set.of(d, e, f, g);

Map.of()

Map.of(k1, v1)

Map.ofEntries(

    entry(k1, v1),

    entry(k2, v2),

    entry(k3, v3),

    // ...

    entry(kn, vn));




287: SHA-3 Hash Algorithms


NIST FIPS 202 에 명시된 SHA-3 암호화 해시 함수 (Byte only) 를 구현하여 제공한다.




288: Disable SHA-1 Certificates


보다 유연한 메커니즘을 제공하여 JDK 보안 구성을 향상시키기 위하여 SHA-1 을 기반으로한 X.509 인증서 체인을 사용하지 않도록 설정하였다.




289: Deprecate the Applet API


웹 브라우저 공급 업체들이 Java 브라우저 플러그인에 대한 지원을 제거함에 따라 Applet API 사용은 급속도로 무의미해지고 있다.

따라서 Applet API는 더이상 사용하지 않는것을 권장한다.

새로운 Java Web Start 또는 설치 가능한 응용 프로그램과 같은 대체기술을 제공한다.




292: Implement Selected ECMAScript 6 Features in Nashorn


java8 부터 JVM의 공식 javascript 엔진이였던 Nashorn (ECMAScript 5.1) 에 ECMAScript 6 (ES6) 버전의 ECMA-262에서 소개된 많은 새로운 기능중 일부를 구현하여 제공한다.


 


Java9 의 크게 달라진점 중 한가지인 아래와 관련된 모듈 시스템.


201: Modular Source Code

220: Modular Run-Time Images

260: Encapsulate Most Internal APIs

261: Module System; see also JSR 376

282: jlink: The Java Linker


java 모듈화 프로젝트인 Jigsaw 프로젝트는 링크에서 자세하게 알수 있다.


요러한 선언으로 프로젝트 최상위에 module-info.java 라는 이름으로 생성된다.


module com.foo.bar {


    requires org.baz.qux.one;

    requires org.baz.qux.two;

    requires ...;


    exports com.foo.bar.alpha;

    exports com.foo.bar.beta;

    exports ...;


    // not exports com.foo.bar.support; //hidden package

}





그외 추가적인 코어라이브러리 업데이트와 개선점들.



Private Interface Method


Java8 에서는 인터페이스에 default method static method 라는 두 가지 새로운 기능을 제공했었다.

단지 특정 기능을 처리하는 내부method 일뿐인데도 외부에 공개되는 public method 로 만들어야 하는 단점을 가지고 있었다.

그러한 요구 사항과 interface를 구현하는 다른 interface 또는 class가 해당 method에 액세스하거나 상속 할수 있는것을 원하지 않는 요구사항이 있다. 이에 Java9 Private Interface Method 에서는 interface 에 private method / private static method라는 새로운 기능을 제공하여 문제를 해결한다. 이제 중복 코드를 피하고 interface에 대한 캡슐화를 유지 할 수 있다.


public interface IMyInterface {

 

private void method1(String arg) {

// do something

}

 

private static void method2(Integer arg) {

// do something

}

}



try-with-resource 향상


기존의 java7 부터 제공된 try-with-resource 구문도 그냥저냥 사용했지만 사실 불편함이 많았다.


Before

void tryWithResourcesByJava7() throws IOException {

BufferedReader reader1 = new BufferedReader(new FileReader("test.txt"));

try (BufferedReader reader2 = reader1) {

// do something

}

}

final or effectively final이 적용되어 참조 변수를 구문에 바로 사용할 수 있게 되었다.


After

// final or effectively final이 적용되어 reader 참조를 사용할 수 있음

void tryWithResourcesByJava9() throws IOException {

    BufferedReader reader = new BufferedReader(new FileReader("test.txt"));

try (reader) {

        // do something

    }

}





Improve Diamond Operator


Java7 에는 코드를 보다 읽기 쉽게 만드는데 도움되는 "<>"(다이아몬드 연산자) Diamond Operator 라는 새로운 기능이 있었지만 익명 클래스(Anonymous Inner Class)에는 제한적이었다.


MyHandler<Integer> intHandler = new MyHandler<>(10) { // Anonymous Class };  //오류

MyHandler<?> handler = new MyHandler<>(""One hundred") { // Anonymous Class }; //오류



이제는 익명 클래스에서  Diamond Operator 를 사용할수 있다.


MyHandler<Integer> intHandler = new MyHandler<>(1) {


@Override

public void handle() {

// handling code...

}

};


MyHandler<? extends Integer> intHandler1 = new MyHandler<>(10) {


@Override

void handle() {

// handling code...

}

};

MyHandler<?> handler = new MyHandler<>("One hundred") {


@Override

void handle() {

// handling code...

}

};

}




Stream Improvements


Java 9 Stream 은 iterate(), takeWhile()/dropWhile(), ofNullable()  과 같은 새로운 추가 메소드를 사용하여 비동기 프로그래밍에 대한 몇 가지 유용한 개선 사항을 제공한다.


Iterate
IntStream
.iterate(1, i -> i < 20, i -> i * 2)
.forEach(System.out::println);


takeWile

//for ordered Stream

Stream.of(1, 2, 3, 4, 5, 6).takeWhile(i -> i <= 3).forEach(System.out::println);

 

// The result is:

// 1

// 2

// 3

 

// for unordered Stream

Stream.of(1, 6, 5, 2, 3, 4).takeWhile(i -> i <= 3).forEach(System.out::println);

 

// The result is:

// 1


dropWhile

//for ordered Stream

Stream.of(1, 2, 3, 4, 5, 6).dropWhile(i -> i <= 3).forEach(System.out::println);

 

// It drops (1,2,3), the result is:

// 4

// 5

// 6

 

//for unordered Stream

Stream.of(1, 6, 5, 2, 3, 4).dropWhile(i -> i <= 3).forEach(System.out::println);

 

// It drops (1), the result is:

// 6

// 5

// 2

// 3

// 4


ofNullable

// numbers [1,2,3,4]

// mapNumber [1 - one, 2 - two, 3 - three]

List<String> newstringNumbers = numbers.stream()

.flatMap(s -> Stream.ofNullable(mapNumber.get(s)))

.collect(Collectors.toList());


// null 값을 제외하고 스트림을 가져옴

// The result is:

// [one, two, three]




Optional class Stream


옵셔널 클래스 스트림이 개선되었다. orElse 구문 사용등에서 깔끔하지 못한부분이 해결되었다. 마음에 든다!!


옵셔널로 스트림 메소드가 제공됨에 따라

Stream<Integer> stream = Optional.of(1).stream();


Java 9 는 새로운 Optional::stream 으로 Optional 객체 지연작업을 제공하며 zero 또는 하나 이상의 요소 스트림을 반한한다. 또한 빈요소를 자동으로 확인하고 제거한다.


// streamOptional(): [(Optional.empty(), Optional.of("one"), Optional.of("two"), Optional.of("three")]

 

List<String> newStrings = streamOptional()

.flatMap(Optional::stream)

.collect(Collectors.toList());

// Result: newStrings[one, two, three]



isPresent() 및orElse() 를 사용하여 코드를 보다 명확하게 만들고 “else” 케이스를 처리하는 대신 Java9의 ifPresentOrElse() 메소드를 사용할 수 있다.


Optional<Integer> result3 = getOptionalEmpty();

result3.ifPresentOrElse(

x -> System.out.println("Result = " + x),

() -> System.out.println("return " + result2.orElse(-1) + ": Result not found."));

// return -1: Result not found.


or() 메소드는 값이 존재하는지 검사하고 값이 있는 경우 해당 Optional 을 리턴하고 그렇지 않은 경우 supplying function에서 생성한 다른 Optional 값을 리턴한다.


Optional<Integer> result = getOptionalEmpty() // Empty Optional object

.or(() -> getAnotherOptionalEmpty()) // Empty Optional object

.or(() -> getOptionalNormal())  // this return an Optional with real value 42

.or(() -> getAnotherOptionalNormal());  // this return an Optional with real value 99

// Result: Optional[42]














참고


http://openjdk.java.net/projects/jdk9/

http://javasampleapproach.com/java-9-tutorial

https://medium.com/@goinhacker/java-9%EC%9D%98-%EB%B3%80%ED%99%94%EC%99%80-%ED%8A%B9%EC%A7%95-%EB%8C%80%EC%B6%A9-%EC%A0%95%EB%A6%AC-fca77cee88f2

https://www.popit.kr/%EB%82%98%EB%A7%8C-%EB%AA%A8%EB%A5%B4%EA%B3%A0-%EC%9E%88%EB%8D%98-java9-%EB%B9%A0%EB%A5%B4%EA%B2%8C-%EB%B3%B4%EA%B8%B0/

'JAVA > 버전.' 카테고리의 다른 글

자바 버전별 신규기능, 특징 정리 - JDK10  (0) 2018.07.02
자바 버전별 특징 정리 - JDK1.4  (0) 2016.04.29

댓글