현재 버전

Java 11 로 전환해야 하는 이유


다시 자바를 하면서 느낀게  "자바는 꾸준히 발전하고 있는 재밌고 가치있는 중심 언어이다"  입니다.

이 글은 8버전의 람다,스트림, 9버전의 모듈이라는 커다란 변경 이후 11버전의 변경점에 대한 5분 정리이며 빨강색 핵심만 보시면 됩니다.

그리고 도커가 일반화  되고 있으며 자바 또한 도커 지원이 11버전들어 강력해 짐에 따라 자바 버전에 대한 사용도 더더욱 유연해 지리라 봅니다.





Java 11로 전환해야 하는 이유  /  OpenJDK 11 version  정리

(추가: Spring5 Webflux로 시작/전환하는 조직들도 많아 졌으면...정말 좋은데..)  

API에 대한 눈에 띄는 추가 및 수정 사항이 있으며,
시작, 성능 및 메모리 사용을 개선하는 향상된 기능이 있습니다.그리고 LTS 버전입니다.

1. 람다 파라미터를 위한 지역변수 표현 

java 10버전에서 편리한 var 구문이 생겨난 상황에서, 11버전에서는 람다 파라미터에서  좀 더 명시적으로 var 를 이용 할 수 있게 되었습니다. 따라서 아래와 같이 어노테이션을 명시할 수 있게 되었습니다.

list.stream()
    .map((@NotNull var s) -> s.toLowerCase())
    .collect(Collectors.toList());

2. HTTP Client (Standard) 

Non-Blocking request and response 지원 (with CompletableFuture)
Backpressure 지원(java.util.concurrent.Flow 패키지를 통해 Rx Flow를 구현체에 적용)
Factory method 형태로 지원
HTTP/2 지원
// 비동기 호출 예
public class HttpClientAsynchronous {
private static final HttpClient httpClient = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.connectTimeout(Duration.ofSeconds(10))
.build();
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.GET()
.uri(URI.create("https://httpbin.org/get"))
.setHeader("User-Agent", "Java 11 HttpClient Bot")
.build();
CompletableFuture<HttpResponse<String>> response =
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString());
String result = response.thenApply(HttpResponse::body).get(5, TimeUnit.SECONDS);
System.out.println(result);
}
} // 여러군데 비동기 호출
public class HttpClientCustomExecutor {
// custom executor
private static final ExecutorService executorService = Executors.newFixedThreadPool(5);
private static final HttpClient httpClient = HttpClient.newBuilder()
.executor(executorService)
.version(HttpClient.Version.HTTP_2)
.connectTimeout(Duration.ofSeconds(10))
.build(); public static void main(String[] args) throws Exception {
List<URI> targets = Arrays.asList(
new URI("https://httpbin.org/get?name=mkyong1"),
new URI("https://httpbin.org/get?name=mkyong2"),
new URI("https://httpbin.org/get?name=mkyong3"));

        List<CompletableFuture<String>> result = targets.stream()
.map(url -> httpClient.sendAsync(
HttpRequest.newBuilder(url)
.GET()
.setHeader("User-Agent", "Java 11 HttpClient Bot")
.build(),
HttpResponse.BodyHandlers.ofString())
.thenApply(response -> response.body()))
.collect(Collectors.toList()); for (CompletableFuture<String> future : result) {
System.out.println(future.get());
}
}
}
참고로 Spring5에서는 Rest Client에 RestTemplate 대신해 WebClient를 사용하여 비동기구현을 할 수 있게 되었습니다. 기존 멀티쓰레드 방식을 버리고 Reactor(WebFlux) 와 함께 스프링 기반 웹서비스를 구현할 경우 그에 따른  성능과 효율 향상은 어마어마 합니다.

3. 모듈 

모듈을 통해 애플리케이션에 필요한 구성 요소만 포함하는 런타임 구성을 사용자 지정할 수 있습니다. 이 사용자 지정은 메모리 공간을 더 적게 사용하며 애플리케이션이 jlink를 사용하여 배포용 사용자 지정 런타임에 정적으로 연결될 수 있게 해줍니다. 메모리 공간을 적게 사용하면 특히 마이크로서비스 아키텍처에서 유용할 수 있습니다.

내부적으로 JVM은 모듈을 활용하여 클래스 로딩을 보다 효율적으로 만들 수 있습니다. 그 결과 런타임이 더 작아지고, 더 가벼워져서 더 빠르게 시작할 수 있습니다. 모듈은 클래스에 필요한 구성 요소를 인코딩하기 때문에 JVM에서 애플리케이션 성능을 개선하기 위해 사용하는 최적화 기법의 효과가 더 좋아질 수 있습니다.

프로그래머의 경우 모듈은 모듈이 내보내는 패키지와 필요한 구성 요소를 명시적으로 선언하고 반사적 액세스를 제한하여 강력한 캡슐화를 적용하는 데 도움이 됩니다. 이 캡슐화 수준을 사용하면 애플리케이션을 더 안전하고 쉽게 유지 관리할 수 있습니다.


4. 프로파일링 및 진단

Java Flight Recorder 

JFR(Java Flight Recorder)은 실행 중인 Java 애플리케이션에서 진단 및 프로파일링 데이터를 수집합니다.  JFR 및 JMC는 Java 8에서 상용 기능이지만 Java 11에서는 둘 다 오픈 소스입니다.

Java Mission Control 

JMC(Java Mission Control)는 JFR(Java Flight Recorder)에서 수집한 데이터를 그래픽으로 표시하고 Java에서는 오픈 소스로 제공됩니다. JFR 및 JMC를 사용하면 메모리 누수, GC 오버헤드, 핫 메서드, 스레드 병목 상태 및 I/O 블로킹과 같은 런타임 문제를 진단할 수 있습니다.

통합 로깅 

Java 11에는 JVM의 모든 구성 요소에 대한 일반적인 로깅 시스템이 있습니다.이 세분화된 로깅은 JVM 충돌에 대한 근본 원인 분석을 수행하고 프로덕션 환경에서 성능 문제를 진단하는 데 유용합니다.

오버헤드가 낮은 힙 프로파일링 

Java 힙 할당을 샘플링하는 데 사용할 수 있는 새 API가 JVMTI(Java Virtual Machine Tool Interface)에 추가되었습니다.JFR 구현에서는 할당이 누락될 수도 있습니다. 반면 Java 11의 힙 샘플링은 라이브 개체와 데드 개체 모두에 대한 정보를 제공할 수 있습니다. APM(애플리케이션 성능 모니터링) 공급업체가 이 새로운 기능을 활용하기 시작 했습니다.

StackWalker 

현재 스레드의 스택에 대한 스냅샷 가져오기는 로깅할 때 주로 사용됩니다.

5. 가비지 수집 

Java 11에서 사용할 수 있는 가비지 수집기는 직렬, 병렬, 가비지 우선 및 엡실론입니다. Java 11의 기본 가비지 수집기는 G1GC(가비지 우선 가비지 수집기)입니다.

ZGC일시 중지 시간을 10ms 미만으로 유지하려고 하는 대기 시간이 짧은 동시 수집기입니다. ZGC는 Java 11에서 실험적 기능으로 사용할 수 있습니다.CMS(Concurrent Mark and Sweep) 수집기는 사용할 수 있지만 Java 9 이후에는 사용되지 않습니다.

엡실론 

엡실론 가비지 수집기는 할당을 처리하지만 메모리를 회수하지는 않습니다. 힙이 소진되면 JVM이 종료됩니다. 엡실론은 수명이 짧은 서비스와 가비지를 사용하지 않는 것으로 알려진 애플리케이션에 유용합니다.

Docker 컨테이너의 향상된 기능 

Java 10 이전에 컨테이너에 설정된 메모리 및 CPU 제약 조건은 JVM에서 인식되지 않았습니다. 예를 들어 Java 8에서 JVM은 최대 힙 크기의 기본값을 기본 호스트의 실제 메모리의 ¼로 설정합니다. Java 10부터 JVM은 컨테이너 제어 그룹(cgroup)에 의해 설정된 제약 조건을 사용하여 메모리 및 CPU 제한을 설정합니다(아래 참고 사항 참조). 예를 들어 기본 최대 힙 크기는 컨테이너의 메모리 제한의 ¼입니다(예: -m2G의 경우 500MB).

다중 릴리스 jar 파일 

Java 11에서 클래스 파일의 여러 Java 릴리스별 버전을 포함하는 jar 파일을 만들 수 있습니다.

6. 성능 향상

JVM 성능향상) 

  • JEP 197: Segmented Code Cache[14] - 코드 캐시를 고유 세그먼트로 나눕니다. 이러한 구분은 JVM 메모리 공간을 보다 효율적으로 제어하고, 컴파일된 메서드의 검색 시간을 단축하고, 코드 캐시의 조각화를 크게 줄이고, 성능을 향상시킵니다.

  • JEP 254: Compact Strings[15] - 문자 인코딩에 따라 문자열의 내부 표현을 문자당 2바이트에서 문자당 1~2바이트로 변경합니다. 대부분의 문자열은 ISO-8859-1/라틴어-1 문자를 포함하므로 이 변경 내용으로 인해 문자열을 저장하는 데 필요한 공간이 효율적으로 변경됩니다.

  • JEP 310: Application Class-Data Sharing[16] - 클래스-데이터 공유는 보관된 클래스가 런타임 시 메모리에 매핑될 수 있게 하여 시작 시간을 줄여줍니다. 애플리케이션 클래스-데이터 공유는 애플리케이션 클래스를 CDS 보관함에 배치할 수 있도록 하여 클래스-데이터 공유를 확장합니다. 여러 JVM이 동일한 보관 파일을 공유하는 경우 메모리가 저장되고 전체 시스템 응답 시간이 단축됩니다.

  • JEP 312: Thread-Local Handshakes[17] - 글로벌 VM 세이프포인트를 수행하지 않고 스레드에 대한 콜백을 실행하여 VM이 글로벌 세이프포인트의 수를 줄여 대기 시간을 단축할 수 있게 해줍니다.

  • Lazy Allocation of Compiler Threads[18] - VM은 단계별 컴파일 모드에서 다량의 컴파일러 스레드를 시작합니다. 이 모드는 CPU가 여러 개 있는 시스템에서 기본값입니다. 이러한 스레드는 사용 가능한 메모리 또는 컴파일 요청 수에 관계없이 생성됩니다. 스레드는 유휴 상태일 때(거의 모든 시간) 메모리를 사용하므로 리소스를 비효율적으로 사용합니다. 이 문제를 해결하기 위해 시작 시 각 유형의 컴파일러 스레드를 하나씩만 시작하도록 구현이 변경되었습니다. 추가 스레드를 시작하고 사용하지 않는 스레드를 종료하는 것은 동적으로 처리됩니다.

핵심 라이브러리 성능 향상) 

  • JEP 193: Variable Handles[19] - 표준을 정의한다는 것은 개체 필드 및 배열 요소, 메모리 정렬의 세부적인 제어를 위한 표준 펜스 작업 세트, 참조된 개체의 강력한 연결성을 유지하기 위한 표준 연결성 펜스 작업에 대한 다양한 java.util.concurrent.atomic 및 sun.misc.Unsafe 작업의 동급 요소를 호출하는 것을 의미합니다.

  • JEP 269: Convenience Factory Methods for Collections[20] - 소량의 요소를 사용하여 컬렉션 및 맵 인스턴스를 편리하게 만들 수 있게 해주는 라이브러리 API를 정의합니다. 컬렉션 인터페이스에서 간결하고 수정할 수 없는 컬렉션 인스턴스를 만드는 고정 팩터리 메서드입니다. 이러한 인스턴스는 본질적으로 더 효율적입니다. API는 조밀하게 표시되고 래퍼 클래스가 없는 컬렉션을 만듭니다.

  • JEP 285: Spin-Wait Hints[21] - Java에서 스핀 루프에 있음을 런타임 시스템에 암시할 수 있게 해주는 API를 제공합니다. 특정 하드웨어 플랫폼은 스레드가 바쁜 대기(busy-wait) 상태라고 소프트웨어가 알려주면 이점을 얻을 수 있습니다.

  • JEP 321: HTTP Client(Standard) [22]- HTTP/2 및 WebSocket을 구현하고 레거시 HttpURLConnection API를 대체할 수 있는 새로운 HTTP 클라이언트 API를 제공합니다.




    P.S


    수정 이력

    2020-11-18 09:47:15 에 아래 내용에서 변경 됨 #22

    다시 자바를 하면서 느낀게  "자바는 꾸준히 발전하고 있는 재밌고 가치있는 중심 언어이다"  입니다.

    이 글은 8버전의 람다,스트림, 9버전의 모듈이라는 커다란 변경 이후 11버전의 변경점에 대한 5분 정리이며 빨강색 핵심만 보시면 됩니다.

    그리고 도커가 일반화 됨에 따라 자바 버전에 대한 자유로운 사용도 더더욱 유연해 지리라 봅니다.





    Java 11로 전환해야 하는 이유  /  OpenJDK 11 version  정리

    (추가: Spring5 Webflux로 시작/전환하는 조직들도 많아 졌으면...정말 좋은데..)  

    API에 대한 눈에 띄는 추가 및 수정 사항이 있으며,
    시작, 성능 및 메모리 사용을 개선하는 향상된 기능이 있습니다.그리고 LTS 버전입니다.

    1. 람다 파라미터를 위한 지역변수 표현 

    java 10버전에서 편리한 var 구문이 생겨난 상황에서, 11버전에서는 람다 파라미터에서  좀 더 명시적으로 var 를 이용 할 수 있게 되었습니다. 따라서 아래와 같이 어노테이션을 명시할 수 있게 되었습니다.

    list.stream()
        .map((@NotNull var s) -> s.toLowerCase())
        .collect(Collectors.toList());

    2. HTTP Client (Standard) 

    Non-Blocking request and response 지원 (with CompletableFuture)
    Backpressure 지원(java.util.concurrent.Flow 패키지를 통해 Rx Flow를 구현체에 적용)
    Factory method 형태로 지원
    HTTP/2 지원
    // 비동기 호출 예
    public class HttpClientAsynchronous {
    private static final HttpClient httpClient = HttpClient.newBuilder()
    .version(HttpClient.Version.HTTP_2)
    .connectTimeout(Duration.ofSeconds(10))
    .build();
    public static void main(String[] args) throws Exception {
    HttpRequest request = HttpRequest.newBuilder()
    .GET()
    .uri(URI.create("https://httpbin.org/get"))
    .setHeader("User-Agent", "Java 11 HttpClient Bot")
    .build();
    CompletableFuture<HttpResponse<String>> response =
    httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString());
    String result = response.thenApply(HttpResponse::body).get(5, TimeUnit.SECONDS);
    System.out.println(result);
    }
    } // 여러군데 비동기 호출
    public class HttpClientCustomExecutor {
    // custom executor
    private static final ExecutorService executorService = Executors.newFixedThreadPool(5);
    private static final HttpClient httpClient = HttpClient.newBuilder()
    .executor(executorService)
    .version(HttpClient.Version.HTTP_2)
    .connectTimeout(Duration.ofSeconds(10))
    .build(); public static void main(String[] args) throws Exception {
    List<URI> targets = Arrays.asList(
    new URI("https://httpbin.org/get?name=mkyong1"),
    new URI("https://httpbin.org/get?name=mkyong2"),
    new URI("https://httpbin.org/get?name=mkyong3"));

            List<CompletableFuture<String>> result = targets.stream()
    .map(url -> httpClient.sendAsync(
    HttpRequest.newBuilder(url)
    .GET()
    .setHeader("User-Agent", "Java 11 HttpClient Bot")
    .build(),
    HttpResponse.BodyHandlers.ofString())
    .thenApply(response -> response.body()))
    .collect(Collectors.toList()); for (CompletableFuture<String> future : result) {
    System.out.println(future.get());
    }
    }
    }
    참고로 Spring5에서는 Rest Client에 RestTemplate 대신해 WebClient를 사용하여 비동기구현을 할 수 있게 되었습니다. 기존 멀티쓰레드 방식을 버리고 Reactor(WebFlux) 와 함께 스프링 기반 웹서비스를 구현할 경우 그에 따른  성능과 효율 향상은 어마어마 합니다.

    3. 모듈 

    모듈을 통해 애플리케이션에 필요한 구성 요소만 포함하는 런타임 구성을 사용자 지정할 수 있습니다. 이 사용자 지정은 메모리 공간을 더 적게 사용하며 애플리케이션이 jlink를 사용하여 배포용 사용자 지정 런타임에 정적으로 연결될 수 있게 해줍니다. 메모리 공간을 적게 사용하면 특히 마이크로서비스 아키텍처에서 유용할 수 있습니다.

    내부적으로 JVM은 모듈을 활용하여 클래스 로딩을 보다 효율적으로 만들 수 있습니다. 그 결과 런타임이 더 작아지고, 더 가벼워져서 더 빠르게 시작할 수 있습니다. 모듈은 클래스에 필요한 구성 요소를 인코딩하기 때문에 JVM에서 애플리케이션 성능을 개선하기 위해 사용하는 최적화 기법의 효과가 더 좋아질 수 있습니다.

    프로그래머의 경우 모듈은 모듈이 내보내는 패키지와 필요한 구성 요소를 명시적으로 선언하고 반사적 액세스를 제한하여 강력한 캡슐화를 적용하는 데 도움이 됩니다. 이 캡슐화 수준을 사용하면 애플리케이션을 더 안전하고 쉽게 유지 관리할 수 있습니다.


    4. 프로파일링 및 진단

    Java Flight Recorder 

    JFR(Java Flight Recorder)은 실행 중인 Java 애플리케이션에서 진단 및 프로파일링 데이터를 수집합니다.  JFR 및 JMC는 Java 8에서 상용 기능이지만 Java 11에서는 둘 다 오픈 소스입니다.

    Java Mission Control 

    JMC(Java Mission Control)는 JFR(Java Flight Recorder)에서 수집한 데이터를 그래픽으로 표시하고 Java에서는 오픈 소스로 제공됩니다. JFR 및 JMC를 사용하면 메모리 누수, GC 오버헤드, 핫 메서드, 스레드 병목 상태 및 I/O 블로킹과 같은 런타임 문제를 진단할 수 있습니다.

    통합 로깅 

    Java 11에는 JVM의 모든 구성 요소에 대한 일반적인 로깅 시스템이 있습니다.이 세분화된 로깅은 JVM 충돌에 대한 근본 원인 분석을 수행하고 프로덕션 환경에서 성능 문제를 진단하는 데 유용합니다.

    오버헤드가 낮은 힙 프로파일링 

    Java 힙 할당을 샘플링하는 데 사용할 수 있는 새 API가 JVMTI(Java Virtual Machine Tool Interface)에 추가되었습니다.JFR 구현에서는 할당이 누락될 수도 있습니다. 반면 Java 11의 힙 샘플링은 라이브 개체와 데드 개체 모두에 대한 정보를 제공할 수 있습니다. APM(애플리케이션 성능 모니터링) 공급업체가 이 새로운 기능을 활용하기 시작 했습니다.

    StackWalker 

    현재 스레드의 스택에 대한 스냅샷 가져오기는 로깅할 때 주로 사용됩니다.

    5. 가비지 수집 

    Java 11에서 사용할 수 있는 가비지 수집기는 직렬, 병렬, 가비지 우선 및 엡실론입니다. Java 11의 기본 가비지 수집기는 G1GC(가비지 우선 가비지 수집기)입니다.

    ZGC일시 중지 시간을 10ms 미만으로 유지하려고 하는 대기 시간이 짧은 동시 수집기입니다. ZGC는 Java 11에서 실험적 기능으로 사용할 수 있습니다.CMS(Concurrent Mark and Sweep) 수집기는 사용할 수 있지만 Java 9 이후에는 사용되지 않습니다.

    엡실론 

    엡실론 가비지 수집기는 할당을 처리하지만 메모리를 회수하지는 않습니다. 힙이 소진되면 JVM이 종료됩니다. 엡실론은 수명이 짧은 서비스와 가비지를 사용하지 않는 것으로 알려진 애플리케이션에 유용합니다.

    Docker 컨테이너의 향상된 기능 

    Java 10 이전에 컨테이너에 설정된 메모리 및 CPU 제약 조건은 JVM에서 인식되지 않았습니다. 예를 들어 Java 8에서 JVM은 최대 힙 크기의 기본값을 기본 호스트의 실제 메모리의 ¼로 설정합니다. Java 10부터 JVM은 컨테이너 제어 그룹(cgroup)에 의해 설정된 제약 조건을 사용하여 메모리 및 CPU 제한을 설정합니다(아래 참고 사항 참조). 예를 들어 기본 최대 힙 크기는 컨테이너의 메모리 제한의 ¼입니다(예: -m2G의 경우 500MB).

    다중 릴리스 jar 파일 

    Java 11에서 클래스 파일의 여러 Java 릴리스별 버전을 포함하는 jar 파일을 만들 수 있습니다.

    6. 성능 향상

    JVM 성능향상) 

    • JEP 197: Segmented Code Cache[14] - 코드 캐시를 고유 세그먼트로 나눕니다. 이러한 구분은 JVM 메모리 공간을 보다 효율적으로 제어하고, 컴파일된 메서드의 검색 시간을 단축하고, 코드 캐시의 조각화를 크게 줄이고, 성능을 향상시킵니다.

    • JEP 254: Compact Strings[15] - 문자 인코딩에 따라 문자열의 내부 표현을 문자당 2바이트에서 문자당 1~2바이트로 변경합니다. 대부분의 문자열은 ISO-8859-1/라틴어-1 문자를 포함하므로 이 변경 내용으로 인해 문자열을 저장하는 데 필요한 공간이 효율적으로 변경됩니다.

    • JEP 310: Application Class-Data Sharing[16] - 클래스-데이터 공유는 보관된 클래스가 런타임 시 메모리에 매핑될 수 있게 하여 시작 시간을 줄여줍니다. 애플리케이션 클래스-데이터 공유는 애플리케이션 클래스를 CDS 보관함에 배치할 수 있도록 하여 클래스-데이터 공유를 확장합니다. 여러 JVM이 동일한 보관 파일을 공유하는 경우 메모리가 저장되고 전체 시스템 응답 시간이 단축됩니다.

    • JEP 312: Thread-Local Handshakes[17] - 글로벌 VM 세이프포인트를 수행하지 않고 스레드에 대한 콜백을 실행하여 VM이 글로벌 세이프포인트의 수를 줄여 대기 시간을 단축할 수 있게 해줍니다.

    • Lazy Allocation of Compiler Threads[18] - VM은 단계별 컴파일 모드에서 다량의 컴파일러 스레드를 시작합니다. 이 모드는 CPU가 여러 개 있는 시스템에서 기본값입니다. 이러한 스레드는 사용 가능한 메모리 또는 컴파일 요청 수에 관계없이 생성됩니다. 스레드는 유휴 상태일 때(거의 모든 시간) 메모리를 사용하므로 리소스를 비효율적으로 사용합니다. 이 문제를 해결하기 위해 시작 시 각 유형의 컴파일러 스레드를 하나씩만 시작하도록 구현이 변경되었습니다. 추가 스레드를 시작하고 사용하지 않는 스레드를 종료하는 것은 동적으로 처리됩니다.

    핵심 라이브러리 성능 향상) 

    • JEP 193: Variable Handles[19] - 표준을 정의한다는 것은 개체 필드 및 배열 요소, 메모리 정렬의 세부적인 제어를 위한 표준 펜스 작업 세트, 참조된 개체의 강력한 연결성을 유지하기 위한 표준 연결성 펜스 작업에 대한 다양한 java.util.concurrent.atomic 및 sun.misc.Unsafe 작업의 동급 요소를 호출하는 것을 의미합니다.

    • JEP 269: Convenience Factory Methods for Collections[20] - 소량의 요소를 사용하여 컬렉션 및 맵 인스턴스를 편리하게 만들 수 있게 해주는 라이브러리 API를 정의합니다. 컬렉션 인터페이스에서 간결하고 수정할 수 없는 컬렉션 인스턴스를 만드는 고정 팩터리 메서드입니다. 이러한 인스턴스는 본질적으로 더 효율적입니다. API는 조밀하게 표시되고 래퍼 클래스가 없는 컬렉션을 만듭니다.

    • JEP 285: Spin-Wait Hints[21] - Java에서 스핀 루프에 있음을 런타임 시스템에 암시할 수 있게 해주는 API를 제공합니다. 특정 하드웨어 플랫폼은 스레드가 바쁜 대기(busy-wait) 상태라고 소프트웨어가 알려주면 이점을 얻을 수 있습니다.

    • JEP 321: HTTP Client(Standard) [22]- HTTP/2 및 WebSocket을 구현하고 레거시 HttpURLConnection API를 대체할 수 있는 새로운 HTTP 클라이언트 API를 제공합니다.




      P.S

      2020-11-18 09:45:45 에 아래 내용에서 변경 됨 #21

      8버전의 람다,스트림, 9버전의 모듈이라는 커다란 변경 이후 11버전의 변경점에 대한 5분 정리.

      빨강색 핵심만 보시면 됩니다.

      그리고 도커가 일반화 됨에 따라 자바 버전에 대한 자유로운 사용도 더더욱 유연해 지리라 봅니다.





      Java 11로 전환해야 하는 이유  /  OpenJDK 11 version  정리

      (추가: Spring5 Webflux로 시작/전환하는 조직들도 많아 졌으면...정말 좋은데..)  

      API에 대한 눈에 띄는 추가 및 수정 사항이 있으며,
      시작, 성능 및 메모리 사용을 개선하는 향상된 기능이 있습니다.그리고 LTS 버전입니다.

      1. 람다 파라미터를 위한 지역변수 표현 

      java 10버전에서 편리한 var 구문이 생겨난 상황에서, 11버전에서는 람다 파라미터에서  좀 더 명시적으로 var 를 이용 할 수 있게 되었습니다. 따라서 아래와 같이 어노테이션을 명시할 수 있게 되었습니다.

      list.stream()
          .map((@NotNull var s) -> s.toLowerCase())
          .collect(Collectors.toList());

      2. HTTP Client (Standard) 

      Non-Blocking request and response 지원 (with CompletableFuture)
      Backpressure 지원(java.util.concurrent.Flow 패키지를 통해 Rx Flow를 구현체에 적용)
      Factory method 형태로 지원
      HTTP/2 지원
      // 비동기 호출 예
      public class HttpClientAsynchronous {
      private static final HttpClient httpClient = HttpClient.newBuilder()
      .version(HttpClient.Version.HTTP_2)
      .connectTimeout(Duration.ofSeconds(10))
      .build();
      public static void main(String[] args) throws Exception {
      HttpRequest request = HttpRequest.newBuilder()
      .GET()
      .uri(URI.create("https://httpbin.org/get"))
      .setHeader("User-Agent", "Java 11 HttpClient Bot")
      .build();
      CompletableFuture<HttpResponse<String>> response =
      httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString());
      String result = response.thenApply(HttpResponse::body).get(5, TimeUnit.SECONDS);
      System.out.println(result);
      }
      } // 여러군데 비동기 호출
      public class HttpClientCustomExecutor {
      // custom executor
      private static final ExecutorService executorService = Executors.newFixedThreadPool(5);
      private static final HttpClient httpClient = HttpClient.newBuilder()
      .executor(executorService)
      .version(HttpClient.Version.HTTP_2)
      .connectTimeout(Duration.ofSeconds(10))
      .build(); public static void main(String[] args) throws Exception {
      List<URI> targets = Arrays.asList(
      new URI("https://httpbin.org/get?name=mkyong1"),
      new URI("https://httpbin.org/get?name=mkyong2"),
      new URI("https://httpbin.org/get?name=mkyong3"));

              List<CompletableFuture<String>> result = targets.stream()
      .map(url -> httpClient.sendAsync(
      HttpRequest.newBuilder(url)
      .GET()
      .setHeader("User-Agent", "Java 11 HttpClient Bot")
      .build(),
      HttpResponse.BodyHandlers.ofString())
      .thenApply(response -> response.body()))
      .collect(Collectors.toList()); for (CompletableFuture<String> future : result) {
      System.out.println(future.get());
      }
      }
      }
      참고로 Spring5에서는 Rest Client에 RestTemplate 대신해 WebClient를 사용하여 비동기구현을 할 수 있게 되었습니다. 기존 멀티쓰레드 방식을 버리고 Reactor(WebFlux) 와 함께 스프링 기반 웹서비스를 구현할 경우 그에 따른  성능과 효율 향상은 어마어마 합니다.

      3. 모듈 

      모듈을 통해 애플리케이션에 필요한 구성 요소만 포함하는 런타임 구성을 사용자 지정할 수 있습니다. 이 사용자 지정은 메모리 공간을 더 적게 사용하며 애플리케이션이 jlink를 사용하여 배포용 사용자 지정 런타임에 정적으로 연결될 수 있게 해줍니다. 메모리 공간을 적게 사용하면 특히 마이크로서비스 아키텍처에서 유용할 수 있습니다.

      내부적으로 JVM은 모듈을 활용하여 클래스 로딩을 보다 효율적으로 만들 수 있습니다. 그 결과 런타임이 더 작아지고, 더 가벼워져서 더 빠르게 시작할 수 있습니다. 모듈은 클래스에 필요한 구성 요소를 인코딩하기 때문에 JVM에서 애플리케이션 성능을 개선하기 위해 사용하는 최적화 기법의 효과가 더 좋아질 수 있습니다.

      프로그래머의 경우 모듈은 모듈이 내보내는 패키지와 필요한 구성 요소를 명시적으로 선언하고 반사적 액세스를 제한하여 강력한 캡슐화를 적용하는 데 도움이 됩니다. 이 캡슐화 수준을 사용하면 애플리케이션을 더 안전하고 쉽게 유지 관리할 수 있습니다.


      4. 프로파일링 및 진단

      Java Flight Recorder 

      JFR(Java Flight Recorder)은 실행 중인 Java 애플리케이션에서 진단 및 프로파일링 데이터를 수집합니다.  JFR 및 JMC는 Java 8에서 상용 기능이지만 Java 11에서는 둘 다 오픈 소스입니다.

      Java Mission Control 

      JMC(Java Mission Control)는 JFR(Java Flight Recorder)에서 수집한 데이터를 그래픽으로 표시하고 Java에서는 오픈 소스로 제공됩니다. JFR 및 JMC를 사용하면 메모리 누수, GC 오버헤드, 핫 메서드, 스레드 병목 상태 및 I/O 블로킹과 같은 런타임 문제를 진단할 수 있습니다.

      통합 로깅 

      Java 11에는 JVM의 모든 구성 요소에 대한 일반적인 로깅 시스템이 있습니다.이 세분화된 로깅은 JVM 충돌에 대한 근본 원인 분석을 수행하고 프로덕션 환경에서 성능 문제를 진단하는 데 유용합니다.

      오버헤드가 낮은 힙 프로파일링 

      Java 힙 할당을 샘플링하는 데 사용할 수 있는 새 API가 JVMTI(Java Virtual Machine Tool Interface)에 추가되었습니다.JFR 구현에서는 할당이 누락될 수도 있습니다. 반면 Java 11의 힙 샘플링은 라이브 개체와 데드 개체 모두에 대한 정보를 제공할 수 있습니다. APM(애플리케이션 성능 모니터링) 공급업체가 이 새로운 기능을 활용하기 시작 했습니다.

      StackWalker 

      현재 스레드의 스택에 대한 스냅샷 가져오기는 로깅할 때 주로 사용됩니다.

      5. 가비지 수집 

      Java 11에서 사용할 수 있는 가비지 수집기는 직렬, 병렬, 가비지 우선 및 엡실론입니다. Java 11의 기본 가비지 수집기는 G1GC(가비지 우선 가비지 수집기)입니다.

      ZGC일시 중지 시간을 10ms 미만으로 유지하려고 하는 대기 시간이 짧은 동시 수집기입니다. ZGC는 Java 11에서 실험적 기능으로 사용할 수 있습니다.CMS(Concurrent Mark and Sweep) 수집기는 사용할 수 있지만 Java 9 이후에는 사용되지 않습니다.

      엡실론 

      엡실론 가비지 수집기는 할당을 처리하지만 메모리를 회수하지는 않습니다. 힙이 소진되면 JVM이 종료됩니다. 엡실론은 수명이 짧은 서비스와 가비지를 사용하지 않는 것으로 알려진 애플리케이션에 유용합니다.

      Docker 컨테이너의 향상된 기능 

      Java 10 이전에 컨테이너에 설정된 메모리 및 CPU 제약 조건은 JVM에서 인식되지 않았습니다. 예를 들어 Java 8에서 JVM은 최대 힙 크기의 기본값을 기본 호스트의 실제 메모리의 ¼로 설정합니다. Java 10부터 JVM은 컨테이너 제어 그룹(cgroup)에 의해 설정된 제약 조건을 사용하여 메모리 및 CPU 제한을 설정합니다(아래 참고 사항 참조). 예를 들어 기본 최대 힙 크기는 컨테이너의 메모리 제한의 ¼입니다(예: -m2G의 경우 500MB).

      다중 릴리스 jar 파일 

      Java 11에서 클래스 파일의 여러 Java 릴리스별 버전을 포함하는 jar 파일을 만들 수 있습니다.

      6. 성능 향상

      JVM 성능향상) 

      • JEP 197: Segmented Code Cache[14] - 코드 캐시를 고유 세그먼트로 나눕니다. 이러한 구분은 JVM 메모리 공간을 보다 효율적으로 제어하고, 컴파일된 메서드의 검색 시간을 단축하고, 코드 캐시의 조각화를 크게 줄이고, 성능을 향상시킵니다.

      • JEP 254: Compact Strings[15] - 문자 인코딩에 따라 문자열의 내부 표현을 문자당 2바이트에서 문자당 1~2바이트로 변경합니다. 대부분의 문자열은 ISO-8859-1/라틴어-1 문자를 포함하므로 이 변경 내용으로 인해 문자열을 저장하는 데 필요한 공간이 효율적으로 변경됩니다.

      • JEP 310: Application Class-Data Sharing[16] - 클래스-데이터 공유는 보관된 클래스가 런타임 시 메모리에 매핑될 수 있게 하여 시작 시간을 줄여줍니다. 애플리케이션 클래스-데이터 공유는 애플리케이션 클래스를 CDS 보관함에 배치할 수 있도록 하여 클래스-데이터 공유를 확장합니다. 여러 JVM이 동일한 보관 파일을 공유하는 경우 메모리가 저장되고 전체 시스템 응답 시간이 단축됩니다.

      • JEP 312: Thread-Local Handshakes[17] - 글로벌 VM 세이프포인트를 수행하지 않고 스레드에 대한 콜백을 실행하여 VM이 글로벌 세이프포인트의 수를 줄여 대기 시간을 단축할 수 있게 해줍니다.

      • Lazy Allocation of Compiler Threads[18] - VM은 단계별 컴파일 모드에서 다량의 컴파일러 스레드를 시작합니다. 이 모드는 CPU가 여러 개 있는 시스템에서 기본값입니다. 이러한 스레드는 사용 가능한 메모리 또는 컴파일 요청 수에 관계없이 생성됩니다. 스레드는 유휴 상태일 때(거의 모든 시간) 메모리를 사용하므로 리소스를 비효율적으로 사용합니다. 이 문제를 해결하기 위해 시작 시 각 유형의 컴파일러 스레드를 하나씩만 시작하도록 구현이 변경되었습니다. 추가 스레드를 시작하고 사용하지 않는 스레드를 종료하는 것은 동적으로 처리됩니다.

      핵심 라이브러리 성능 향상) 

      • JEP 193: Variable Handles[19] - 표준을 정의한다는 것은 개체 필드 및 배열 요소, 메모리 정렬의 세부적인 제어를 위한 표준 펜스 작업 세트, 참조된 개체의 강력한 연결성을 유지하기 위한 표준 연결성 펜스 작업에 대한 다양한 java.util.concurrent.atomic 및 sun.misc.Unsafe 작업의 동급 요소를 호출하는 것을 의미합니다.

      • JEP 269: Convenience Factory Methods for Collections[20] - 소량의 요소를 사용하여 컬렉션 및 맵 인스턴스를 편리하게 만들 수 있게 해주는 라이브러리 API를 정의합니다. 컬렉션 인터페이스에서 간결하고 수정할 수 없는 컬렉션 인스턴스를 만드는 고정 팩터리 메서드입니다. 이러한 인스턴스는 본질적으로 더 효율적입니다. API는 조밀하게 표시되고 래퍼 클래스가 없는 컬렉션을 만듭니다.

      • JEP 285: Spin-Wait Hints[21] - Java에서 스핀 루프에 있음을 런타임 시스템에 암시할 수 있게 해주는 API를 제공합니다. 특정 하드웨어 플랫폼은 스레드가 바쁜 대기(busy-wait) 상태라고 소프트웨어가 알려주면 이점을 얻을 수 있습니다.

      • JEP 321: HTTP Client(Standard) [22]- HTTP/2 및 WebSocket을 구현하고 레거시 HttpURLConnection API를 대체할 수 있는 새로운 HTTP 클라이언트 API를 제공합니다.




        P.S

        다시 자바를 하면서 느낀게  "자바는 꾸준히 발전하고 있는 재밌고 가치있는 중심 언어이다"  입니다.

        2020-11-18 09:44:17 에 아래 내용에서 변경 됨 #20

        8버전의 람다,스트림, 9버전의 모듈이라는 커다란 변경 이후 11버전의 변경점에 대한 5분 정리.

        빨강색 핵심만 보시면 됩니다.

        그리고 도커가 일반화 됨에 따라 자바 버전에 대한 자유로운 사용도 더더욱 유연해 지리라 봅니다.





        Java 11로 전환해야 하는 이유  /  OpenJDK 11 version  정리

        (추가: Spring5 Webflux로 시작/전환하는 조직들도 많아 졌으면...정말 좋은데..)  

        API에 대한 눈에 띄는 추가 및 수정 사항이 있으며,
        시작, 성능 및 메모리 사용을 개선하는 향상된 기능이 있습니다.그리고 LTS 버전입니다.

        1. 람다 파라미터를 위한 지역변수 표현 

        java 10버전에 편리한 var 구문이 생겨난 상황에서, 11버전에서는 람다 파라미터에서  좀 더 명시적으로 var 를 이용 할 수 있게 되었습니다. 따라서 아래와 같이 어노테이션을 명시할 수 있게 되었습니다.

        list.stream()
            .map((@NotNull var s) -> s.toLowerCase())
            .collect(Collectors.toList());

        2. HTTP Client (Standard) 

        Non-Blocking request and response 지원 (with CompletableFuture)
        Backpressure 지원(java.util.concurrent.Flow 패키지를 통해 Rx Flow를 구현체에 적용)
        Factory method 형태로 지원
        HTTP/2 지원
        // 비동기 호출 예
        public class HttpClientAsynchronous {
        private static final HttpClient httpClient = HttpClient.newBuilder()
        .version(HttpClient.Version.HTTP_2)
        .connectTimeout(Duration.ofSeconds(10))
        .build();
        public static void main(String[] args) throws Exception {
        HttpRequest request = HttpRequest.newBuilder()
        .GET()
        .uri(URI.create("https://httpbin.org/get"))
        .setHeader("User-Agent", "Java 11 HttpClient Bot")
        .build();
        CompletableFuture<HttpResponse<String>> response =
        httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString());
        String result = response.thenApply(HttpResponse::body).get(5, TimeUnit.SECONDS);
        System.out.println(result);
        }
        } // 여러군데 비동기 호출
        public class HttpClientCustomExecutor {
        // custom executor
        private static final ExecutorService executorService = Executors.newFixedThreadPool(5);
        private static final HttpClient httpClient = HttpClient.newBuilder()
        .executor(executorService)
        .version(HttpClient.Version.HTTP_2)
        .connectTimeout(Duration.ofSeconds(10))
        .build(); public static void main(String[] args) throws Exception {
        List<URI> targets = Arrays.asList(
        new URI("https://httpbin.org/get?name=mkyong1"),
        new URI("https://httpbin.org/get?name=mkyong2"),
        new URI("https://httpbin.org/get?name=mkyong3"));

                List<CompletableFuture<String>> result = targets.stream()
        .map(url -> httpClient.sendAsync(
        HttpRequest.newBuilder(url)
        .GET()
        .setHeader("User-Agent", "Java 11 HttpClient Bot")
        .build(),
        HttpResponse.BodyHandlers.ofString())
        .thenApply(response -> response.body()))
        .collect(Collectors.toList()); for (CompletableFuture<String> future : result) {
        System.out.println(future.get());
        }
        }
        }
        참고로 Spring5에서는 Rest Client에 RestTemplate 대신해 WebClient를 사용하여 비동기구현을 할 수 있게 되었습니다. 기존 멀티쓰레드 방식을 버리고 Reactor(WebFlux) 와 함께 스프링 기반 웹서비스를 구현할 경우 그에 따른  성능과 효율 향상은 어마어마 합니다.

        3. 모듈 

        모듈을 통해 애플리케이션에 필요한 구성 요소만 포함하는 런타임 구성을 사용자 지정할 수 있습니다. 이 사용자 지정은 메모리 공간을 더 적게 사용하며 애플리케이션이 jlink를 사용하여 배포용 사용자 지정 런타임에 정적으로 연결될 수 있게 해줍니다. 메모리 공간을 적게 사용하면 특히 마이크로서비스 아키텍처에서 유용할 수 있습니다.

        내부적으로 JVM은 모듈을 활용하여 클래스 로딩을 보다 효율적으로 만들 수 있습니다. 그 결과 런타임이 더 작아지고, 더 가벼워져서 더 빠르게 시작할 수 있습니다. 모듈은 클래스에 필요한 구성 요소를 인코딩하기 때문에 JVM에서 애플리케이션 성능을 개선하기 위해 사용하는 최적화 기법의 효과가 더 좋아질 수 있습니다.

        프로그래머의 경우 모듈은 모듈이 내보내는 패키지와 필요한 구성 요소를 명시적으로 선언하고 반사적 액세스를 제한하여 강력한 캡슐화를 적용하는 데 도움이 됩니다. 이 캡슐화 수준을 사용하면 애플리케이션을 더 안전하고 쉽게 유지 관리할 수 있습니다.


        4. 프로파일링 및 진단

        Java Flight Recorder 

        JFR(Java Flight Recorder)은 실행 중인 Java 애플리케이션에서 진단 및 프로파일링 데이터를 수집합니다.  JFR 및 JMC는 Java 8에서 상용 기능이지만 Java 11에서는 둘 다 오픈 소스입니다.

        Java Mission Control 

        JMC(Java Mission Control)는 JFR(Java Flight Recorder)에서 수집한 데이터를 그래픽으로 표시하고 Java에서는 오픈 소스로 제공됩니다. JFR 및 JMC를 사용하면 메모리 누수, GC 오버헤드, 핫 메서드, 스레드 병목 상태 및 I/O 블로킹과 같은 런타임 문제를 진단할 수 있습니다.

        통합 로깅 

        Java 11에는 JVM의 모든 구성 요소에 대한 일반적인 로깅 시스템이 있습니다.이 세분화된 로깅은 JVM 충돌에 대한 근본 원인 분석을 수행하고 프로덕션 환경에서 성능 문제를 진단하는 데 유용합니다.

        오버헤드가 낮은 힙 프로파일링 

        Java 힙 할당을 샘플링하는 데 사용할 수 있는 새 API가 JVMTI(Java Virtual Machine Tool Interface)에 추가되었습니다.JFR 구현에서는 할당이 누락될 수도 있습니다. 반면 Java 11의 힙 샘플링은 라이브 개체와 데드 개체 모두에 대한 정보를 제공할 수 있습니다. APM(애플리케이션 성능 모니터링) 공급업체가 이 새로운 기능을 활용하기 시작 했습니다.

        StackWalker 

        현재 스레드의 스택에 대한 스냅샷 가져오기는 로깅할 때 주로 사용됩니다.

        5. 가비지 수집 

        Java 11에서 사용할 수 있는 가비지 수집기는 직렬, 병렬, 가비지 우선 및 엡실론입니다. Java 11의 기본 가비지 수집기는 G1GC(가비지 우선 가비지 수집기)입니다.

        ZGC일시 중지 시간을 10ms 미만으로 유지하려고 하는 대기 시간이 짧은 동시 수집기입니다. ZGC는 Java 11에서 실험적 기능으로 사용할 수 있습니다.CMS(Concurrent Mark and Sweep) 수집기는 사용할 수 있지만 Java 9 이후에는 사용되지 않습니다.

        엡실론 

        엡실론 가비지 수집기는 할당을 처리하지만 메모리를 회수하지는 않습니다. 힙이 소진되면 JVM이 종료됩니다. 엡실론은 수명이 짧은 서비스와 가비지를 사용하지 않는 것으로 알려진 애플리케이션에 유용합니다.

        Docker 컨테이너의 향상된 기능 

        Java 10 이전에 컨테이너에 설정된 메모리 및 CPU 제약 조건은 JVM에서 인식되지 않았습니다. 예를 들어 Java 8에서 JVM은 최대 힙 크기의 기본값을 기본 호스트의 실제 메모리의 ¼로 설정합니다. Java 10부터 JVM은 컨테이너 제어 그룹(cgroup)에 의해 설정된 제약 조건을 사용하여 메모리 및 CPU 제한을 설정합니다(아래 참고 사항 참조). 예를 들어 기본 최대 힙 크기는 컨테이너의 메모리 제한의 ¼입니다(예: -m2G의 경우 500MB).

        다중 릴리스 jar 파일 

        Java 11에서 클래스 파일의 여러 Java 릴리스별 버전을 포함하는 jar 파일을 만들 수 있습니다.

        6. 성능 향상

        JVM 성능향상) 

        • JEP 197: Segmented Code Cache[14] - 코드 캐시를 고유 세그먼트로 나눕니다. 이러한 구분은 JVM 메모리 공간을 보다 효율적으로 제어하고, 컴파일된 메서드의 검색 시간을 단축하고, 코드 캐시의 조각화를 크게 줄이고, 성능을 향상시킵니다.

        • JEP 254: Compact Strings[15] - 문자 인코딩에 따라 문자열의 내부 표현을 문자당 2바이트에서 문자당 1~2바이트로 변경합니다. 대부분의 문자열은 ISO-8859-1/라틴어-1 문자를 포함하므로 이 변경 내용으로 인해 문자열을 저장하는 데 필요한 공간이 효율적으로 변경됩니다.

        • JEP 310: Application Class-Data Sharing[16] - 클래스-데이터 공유는 보관된 클래스가 런타임 시 메모리에 매핑될 수 있게 하여 시작 시간을 줄여줍니다. 애플리케이션 클래스-데이터 공유는 애플리케이션 클래스를 CDS 보관함에 배치할 수 있도록 하여 클래스-데이터 공유를 확장합니다. 여러 JVM이 동일한 보관 파일을 공유하는 경우 메모리가 저장되고 전체 시스템 응답 시간이 단축됩니다.

        • JEP 312: Thread-Local Handshakes[17] - 글로벌 VM 세이프포인트를 수행하지 않고 스레드에 대한 콜백을 실행하여 VM이 글로벌 세이프포인트의 수를 줄여 대기 시간을 단축할 수 있게 해줍니다.

        • Lazy Allocation of Compiler Threads[18] - VM은 단계별 컴파일 모드에서 다량의 컴파일러 스레드를 시작합니다. 이 모드는 CPU가 여러 개 있는 시스템에서 기본값입니다. 이러한 스레드는 사용 가능한 메모리 또는 컴파일 요청 수에 관계없이 생성됩니다. 스레드는 유휴 상태일 때(거의 모든 시간) 메모리를 사용하므로 리소스를 비효율적으로 사용합니다. 이 문제를 해결하기 위해 시작 시 각 유형의 컴파일러 스레드를 하나씩만 시작하도록 구현이 변경되었습니다. 추가 스레드를 시작하고 사용하지 않는 스레드를 종료하는 것은 동적으로 처리됩니다.

        핵심 라이브러리 성능 향상) 

        • JEP 193: Variable Handles[19] - 표준을 정의한다는 것은 개체 필드 및 배열 요소, 메모리 정렬의 세부적인 제어를 위한 표준 펜스 작업 세트, 참조된 개체의 강력한 연결성을 유지하기 위한 표준 연결성 펜스 작업에 대한 다양한 java.util.concurrent.atomic 및 sun.misc.Unsafe 작업의 동급 요소를 호출하는 것을 의미합니다.

        • JEP 269: Convenience Factory Methods for Collections[20] - 소량의 요소를 사용하여 컬렉션 및 맵 인스턴스를 편리하게 만들 수 있게 해주는 라이브러리 API를 정의합니다. 컬렉션 인터페이스에서 간결하고 수정할 수 없는 컬렉션 인스턴스를 만드는 고정 팩터리 메서드입니다. 이러한 인스턴스는 본질적으로 더 효율적입니다. API는 조밀하게 표시되고 래퍼 클래스가 없는 컬렉션을 만듭니다.

        • JEP 285: Spin-Wait Hints[21] - Java에서 스핀 루프에 있음을 런타임 시스템에 암시할 수 있게 해주는 API를 제공합니다. 특정 하드웨어 플랫폼은 스레드가 바쁜 대기(busy-wait) 상태라고 소프트웨어가 알려주면 이점을 얻을 수 있습니다.

        • JEP 321: HTTP Client(Standard) [22]- HTTP/2 및 WebSocket을 구현하고 레거시 HttpURLConnection API를 대체할 수 있는 새로운 HTTP 클라이언트 API를 제공합니다.




          P.S

          다시 자바를 하면서 느낀게  "자바는 꾸준히 발전하고 있는 재밌고 가치있는 중심 언어이다"  입니다.

          2020-11-18 09:43:20 에 아래 내용에서 변경 됨 #19

          8버전의 람다,스트림, 9버전의 모듈이라는 커다란 변경 이후 11버전의 변경점에 대한 5분 정리.

          빨강색 핵심만 보시면 됩니다.

          그리고 도커가 일반화 됨에 따라 자바 버전에 대한 자유로운 사용도 더더욱 유연해 지리라 봅니다.





          Java 11로 전환해야 하는 이유  /  OpenJDK 11 version  정리

          (추가: Spring5 Webflux로 시작/전환하는 조직들도 많아 졌으면...정말 좋은데..)  

          API에 대한 눈에 띄는 추가 및 수정 사항이 있으며,
          시작, 성능 및 메모리 사용을 개선하는 향상된 기능이 있습니다.그리고 LTS 버전입니다.

          1. 람다 파라미터를 위한 지역변수 표현 

          java 10버전에 편리한 var 구문이 생겨난 상황에서, 11버전에서는 람다 파라미터에서  좀 더 명시적으로 var 를 이용 할 수 있게 되었습니다. 따라서 아래와 같이 어노테이션을 명시할 수 있게 되었습니다.

          list.stream()
              .map((@NotNull var s) -> s.toLowerCase())
              .collect(Collectors.toList());

          2. HTTP Client (Standard) 

          Non-Blocking request and response 지원 (with CompletableFuture)
          Backpressure 지원(java.util.concurrent.Flow 패키지를 통해 Rx Flow를 구현체에 적용)
          Factory method 형태로 지원
          HTTP/2 지원
          // 비동기 호출 예
          public class HttpClientAsynchronous {
          private static final HttpClient httpClient = HttpClient.newBuilder()
          .version(HttpClient.Version.HTTP_2)
          .connectTimeout(Duration.ofSeconds(10))
          .build();
          public static void main(String[] args) throws Exception {
          HttpRequest request = HttpRequest.newBuilder()
          .GET()
          .uri(URI.create("https://httpbin.org/get"))
          .setHeader("User-Agent", "Java 11 HttpClient Bot")
          .build();
          CompletableFuture<HttpResponse<String>> response =
          httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString());
          String result = response.thenApply(HttpResponse::body).get(5, TimeUnit.SECONDS);
          System.out.println(result);
          }
          } // 여러군데 비동기 호출
          public class HttpClientCustomExecutor {
          // custom executor
          private static final ExecutorService executorService = Executors.newFixedThreadPool(5);
          private static final HttpClient httpClient = HttpClient.newBuilder()
          .executor(executorService)
          .version(HttpClient.Version.HTTP_2)
          .connectTimeout(Duration.ofSeconds(10))
          .build(); public static void main(String[] args) throws Exception {
          List<URI> targets = Arrays.asList(
          new URI("https://httpbin.org/get?name=mkyong1"),
          new URI("https://httpbin.org/get?name=mkyong2"),
          new URI("https://httpbin.org/get?name=mkyong3"));

                  List<CompletableFuture<String>> result = targets.stream()
          .map(url -> httpClient.sendAsync(
          HttpRequest.newBuilder(url)
          .GET()
          .setHeader("User-Agent", "Java 11 HttpClient Bot")
          .build(),
          HttpResponse.BodyHandlers.ofString())
          .thenApply(response -> response.body()))
          .collect(Collectors.toList()); for (CompletableFuture<String> future : result) {
          System.out.println(future.get());
          }
          }
          }
          참고로 Spring5에서는 Rest Client에 RestTemplate 대신해 WebClient를 사용하여 비동기구현을 할 수 있게 되었습니다. 기존 멀티쓰레드 방식을 버리고 Reactor(WebFlux) 와 함께 스프링 기반 웹서비스를 구현할 경우 그에 따른  성능과 효율 향상은 어마어마 합니다.

          3. 모듈 

          모듈을 통해 애플리케이션에 필요한 구성 요소만 포함하는 런타임 구성을 사용자 지정할 수 있습니다. 이 사용자 지정은 메모리 공간을 더 적게 사용하며 애플리케이션이 jlink를 사용하여 배포용 사용자 지정 런타임에 정적으로 연결될 수 있게 해줍니다. 메모리 공간을 적게 사용하면 특히 마이크로서비스 아키텍처에서 유용할 수 있습니다.

          내부적으로 JVM은 모듈을 활용하여 클래스 로딩을 보다 효율적으로 만들 수 있습니다. 그 결과 런타임이 더 작아지고, 더 가벼워져서 더 빠르게 시작할 수 있습니다. 모듈은 클래스에 필요한 구성 요소를 인코딩하기 때문에 JVM에서 애플리케이션 성능을 개선하기 위해 사용하는 최적화 기법의 효과가 더 좋아질 수 있습니다.

          프로그래머의 경우 모듈은 모듈이 내보내는 패키지와 필요한 구성 요소를 명시적으로 선언하고 반사적 액세스를 제한하여 강력한 캡슐화를 적용하는 데 도움이 됩니다. 이 캡슐화 수준을 사용하면 애플리케이션을 더 안전하고 쉽게 유지 관리할 수 있습니다.


          4. 프로파일링 및 진단

          Java Flight Recorder 

          JFR(Java Flight Recorder)은 실행 중인 Java 애플리케이션에서 진단 및 프로파일링 데이터를 수집합니다.  JFR 및 JMC는 Java 8에서 상용 기능이지만 Java 11에서는 둘 다 오픈 소스입니다.

          Java Mission Control 

          JMC(Java Mission Control)는 JFR(Java Flight Recorder)에서 수집한 데이터를 그래픽으로 표시하고 Java에서는 오픈 소스로 제공됩니다. JFR 및 JMC를 사용하면 메모리 누수, GC 오버헤드, 핫 메서드, 스레드 병목 상태 및 I/O 블로킹과 같은 런타임 문제를 진단할 수 있습니다.

          통합 로깅 

          Java 11에는 JVM의 모든 구성 요소에 대한 일반적인 로깅 시스템이 있습니다.이 세분화된 로깅은 JVM 충돌에 대한 근본 원인 분석을 수행하고 프로덕션 환경에서 성능 문제를 진단하는 데 유용합니다.

          오버헤드가 낮은 힙 프로파일링 

          Java 힙 할당을 샘플링하는 데 사용할 수 있는 새 API가 JVMTI(Java Virtual Machine Tool Interface)에 추가되었습니다.JFR 구현에서는 할당이 누락될 수도 있습니다. 반면 Java 11의 힙 샘플링은 라이브 개체와 데드 개체 모두에 대한 정보를 제공할 수 있습니다. APM(애플리케이션 성능 모니터링) 공급업체가 이 새로운 기능을 활용하기 시작 했습니다.

          StackWalker 

          현재 스레드의 스택에 대한 스냅샷 가져오기는 로깅할 때 주로 사용됩니다.

          5. 가비지 수집 

          Java 11에서 사용할 수 있는 가비지 수집기는 직렬, 병렬, 가비지 우선 및 엡실론입니다. Java 11의 기본 가비지 수집기는 G1GC(가비지 우선 가비지 수집기)입니다.

          ZGC일시 중지 시간을 10ms 미만으로 유지하려고 하는 대기 시간이 짧은 동시 수집기입니다. ZGC는 Java 11에서 실험적 기능으로 사용할 수 있습니다.CMS(Concurrent Mark and Sweep) 수집기는 사용할 수 있지만 Java 9 이후에는 사용되지 않습니다.

          엡실론 

          엡실론 가비지 수집기는 할당을 처리하지만 메모리를 회수하지는 않습니다. 힙이 소진되면 JVM이 종료됩니다. 엡실론은 수명이 짧은 서비스와 가비지를 사용하지 않는 것으로 알려진 애플리케이션에 유용합니다.

          Docker 컨테이너의 향상된 기능 

          Java 10 이전에 컨테이너에 설정된 메모리 및 CPU 제약 조건은 JVM에서 인식되지 않았습니다. 예를 들어 Java 8에서 JVM은 최대 힙 크기의 기본값을 기본 호스트의 실제 메모리의 ¼로 설정합니다. Java 10부터 JVM은 컨테이너 제어 그룹(cgroup)에 의해 설정된 제약 조건을 사용하여 메모리 및 CPU 제한을 설정합니다(아래 참고 사항 참조). 예를 들어 기본 최대 힙 크기는 컨테이너의 메모리 제한의 ¼입니다(예: -m2G의 경우 500MB).

          다중 릴리스 jar 파일 

          Java 11에서 클래스 파일의 여러 Java 릴리스별 버전을 포함하는 jar 파일을 만들 수 있습니다.

          6. 성능 향상

          JVM 성능향상) 

          • JEP 197: Segmented Code Cache[14] - 코드 캐시를 고유 세그먼트로 나눕니다. 이러한 구분은 JVM 메모리 공간을 보다 효율적으로 제어하고, 컴파일된 메서드의 검색 시간을 단축하고, 코드 캐시의 조각화를 크게 줄이고, 성능을 향상시킵니다.

          • JEP 254: Compact Strings[15] - 문자 인코딩에 따라 문자열의 내부 표현을 문자당 2바이트에서 문자당 1~2바이트로 변경합니다. 대부분의 문자열은 ISO-8859-1/라틴어-1 문자를 포함하므로 이 변경 내용으로 인해 문자열을 저장하는 데 필요한 공간이 효율적으로 변경됩니다.

          • JEP 310: Application Class-Data Sharing[16] - 클래스-데이터 공유는 보관된 클래스가 런타임 시 메모리에 매핑될 수 있게 하여 시작 시간을 줄여줍니다. 애플리케이션 클래스-데이터 공유는 애플리케이션 클래스를 CDS 보관함에 배치할 수 있도록 하여 클래스-데이터 공유를 확장합니다. 여러 JVM이 동일한 보관 파일을 공유하는 경우 메모리가 저장되고 전체 시스템 응답 시간이 단축됩니다.

          • JEP 312: Thread-Local Handshakes[17] - 글로벌 VM 세이프포인트를 수행하지 않고 스레드에 대한 콜백을 실행하여 VM이 글로벌 세이프포인트의 수를 줄여 대기 시간을 단축할 수 있게 해줍니다.

          • Lazy Allocation of Compiler Threads[18] - VM은 단계별 컴파일 모드에서 다량의 컴파일러 스레드를 시작합니다. 이 모드는 CPU가 여러 개 있는 시스템에서 기본값입니다. 이러한 스레드는 사용 가능한 메모리 또는 컴파일 요청 수에 관계없이 생성됩니다. 스레드는 유휴 상태일 때(거의 모든 시간) 메모리를 사용하므로 리소스를 비효율적으로 사용합니다. 이 문제를 해결하기 위해 시작 시 각 유형의 컴파일러 스레드를 하나씩만 시작하도록 구현이 변경되었습니다. 추가 스레드를 시작하고 사용하지 않는 스레드를 종료하는 것은 동적으로 처리됩니다.

          핵심 라이브러리 성능 향상) 

          • JEP 193: Variable Handles[19] - 표준을 정의한다는 것은 개체 필드 및 배열 요소, 메모리 정렬의 세부적인 제어를 위한 표준 펜스 작업 세트, 참조된 개체의 강력한 연결성을 유지하기 위한 표준 연결성 펜스 작업에 대한 다양한 java.util.concurrent.atomic 및 sun.misc.Unsafe 작업의 동급 요소를 호출하는 것을 의미합니다.

          • JEP 269: Convenience Factory Methods for Collections[20] - 소량의 요소를 사용하여 컬렉션 및 맵 인스턴스를 편리하게 만들 수 있게 해주는 라이브러리 API를 정의합니다. 컬렉션 인터페이스에서 간결하고 수정할 수 없는 컬렉션 인스턴스를 만드는 고정 팩터리 메서드입니다. 이러한 인스턴스는 본질적으로 더 효율적입니다. API는 조밀하게 표시되고 래퍼 클래스가 없는 컬렉션을 만듭니다.

          • JEP 285: Spin-Wait Hints[21] - Java에서 스핀 루프에 있음을 런타임 시스템에 암시할 수 있게 해주는 API를 제공합니다. 특정 하드웨어 플랫폼은 스레드가 바쁜 대기(busy-wait) 상태라고 소프트웨어가 알려주면 이점을 얻을 수 있습니다.

          • JEP 321: HTTP Client(Standard) [22]- HTTP/2 및 WebSocket을 구현하고 레거시 HttpURLConnection API를 대체할 수 있는 새로운 HTTP 클라이언트 API를 제공합니다.




            P.S

            다시 자바를 하면서 느낀게  "자바는 꾸준히 발전하고 있는 재밌고 가치있는 중심 언어이다"  입니다.

            2020-11-18 09:40:46 에 아래 내용에서 변경 됨 #18

            8버전의 람다,스트림, 9버전의 모듈이라는 커다란 변경 이후 11버전의 변경점에 대한 5분 정리.

            빨강색 핵심만 보시면 됩니다.





            Java 11로 전환해야 하는 이유  /  OpenJDK 11 version  정리

            (추가: Spring5 Webflux로 시작/전환하는 조직들도 많아 졌으면...정말 좋은데..)  

            API에 대한 눈에 띄는 추가 및 수정 사항이 있으며,
            시작, 성능 및 메모리 사용을 개선하는 향상된 기능이 있습니다.그리고 LTS 버전입니다.

            1. 람다 파라미터를 위한 지역변수 표현 

            java 10버전에 편리한 var 구문이 생겨난 상황에서, 11버전에서는 람다 파라미터에서  좀 더 명시적으로 var 를 이용 할 수 있게 되었습니다. 따라서 아래와 같이 어노테이션을 명시할 수 있게 되었습니다.

            list.stream()
                .map((@NotNull var s) -> s.toLowerCase())
                .collect(Collectors.toList());

            2. HTTP Client (Standard) 

            Non-Blocking request and response 지원 (with CompletableFuture)
            Backpressure 지원(java.util.concurrent.Flow 패키지를 통해 Rx Flow를 구현체에 적용)
            Factory method 형태로 지원
            HTTP/2 지원
            // 비동기 호출 예
            public class HttpClientAsynchronous {
            private static final HttpClient httpClient = HttpClient.newBuilder()
            .version(HttpClient.Version.HTTP_2)
            .connectTimeout(Duration.ofSeconds(10))
            .build();
            public static void main(String[] args) throws Exception {
            HttpRequest request = HttpRequest.newBuilder()
            .GET()
            .uri(URI.create("https://httpbin.org/get"))
            .setHeader("User-Agent", "Java 11 HttpClient Bot")
            .build();
            CompletableFuture<HttpResponse<String>> response =
            httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString());
            String result = response.thenApply(HttpResponse::body).get(5, TimeUnit.SECONDS);
            System.out.println(result);
            }
            } // 여러군데 비동기 호출
            public class HttpClientCustomExecutor {
            // custom executor
            private static final ExecutorService executorService = Executors.newFixedThreadPool(5);
            private static final HttpClient httpClient = HttpClient.newBuilder()
            .executor(executorService)
            .version(HttpClient.Version.HTTP_2)
            .connectTimeout(Duration.ofSeconds(10))
            .build(); public static void main(String[] args) throws Exception {
            List<URI> targets = Arrays.asList(
            new URI("https://httpbin.org/get?name=mkyong1"),
            new URI("https://httpbin.org/get?name=mkyong2"),
            new URI("https://httpbin.org/get?name=mkyong3"));

                    List<CompletableFuture<String>> result = targets.stream()
            .map(url -> httpClient.sendAsync(
            HttpRequest.newBuilder(url)
            .GET()
            .setHeader("User-Agent", "Java 11 HttpClient Bot")
            .build(),
            HttpResponse.BodyHandlers.ofString())
            .thenApply(response -> response.body()))
            .collect(Collectors.toList()); for (CompletableFuture<String> future : result) {
            System.out.println(future.get());
            }
            }
            }
            참고로 Spring5에서는 Rest Client에 RestTemplate 대신해 WebClient를 사용하여 비동기구현을 할 수 있게 되었습니다. 기존 멀티쓰레드 방식을 버리고 Reactor(WebFlux) 와 함께 스프링 기반 웹서비스를 구현할 경우 그에 따른  성능과 효율 향상은 어마어마 합니다.

            3. 모듈 

            모듈을 통해 애플리케이션에 필요한 구성 요소만 포함하는 런타임 구성을 사용자 지정할 수 있습니다. 이 사용자 지정은 메모리 공간을 더 적게 사용하며 애플리케이션이 jlink를 사용하여 배포용 사용자 지정 런타임에 정적으로 연결될 수 있게 해줍니다. 메모리 공간을 적게 사용하면 특히 마이크로서비스 아키텍처에서 유용할 수 있습니다.

            내부적으로 JVM은 모듈을 활용하여 클래스 로딩을 보다 효율적으로 만들 수 있습니다. 그 결과 런타임이 더 작아지고, 더 가벼워져서 더 빠르게 시작할 수 있습니다. 모듈은 클래스에 필요한 구성 요소를 인코딩하기 때문에 JVM에서 애플리케이션 성능을 개선하기 위해 사용하는 최적화 기법의 효과가 더 좋아질 수 있습니다.

            프로그래머의 경우 모듈은 모듈이 내보내는 패키지와 필요한 구성 요소를 명시적으로 선언하고 반사적 액세스를 제한하여 강력한 캡슐화를 적용하는 데 도움이 됩니다. 이 캡슐화 수준을 사용하면 애플리케이션을 더 안전하고 쉽게 유지 관리할 수 있습니다.


            4. 프로파일링 및 진단

            Java Flight Recorder 

            JFR(Java Flight Recorder)은 실행 중인 Java 애플리케이션에서 진단 및 프로파일링 데이터를 수집합니다.  JFR 및 JMC는 Java 8에서 상용 기능이지만 Java 11에서는 둘 다 오픈 소스입니다.

            Java Mission Control 

            JMC(Java Mission Control)는 JFR(Java Flight Recorder)에서 수집한 데이터를 그래픽으로 표시하고 Java에서는 오픈 소스로 제공됩니다. JFR 및 JMC를 사용하면 메모리 누수, GC 오버헤드, 핫 메서드, 스레드 병목 상태 및 I/O 블로킹과 같은 런타임 문제를 진단할 수 있습니다.

            통합 로깅 

            Java 11에는 JVM의 모든 구성 요소에 대한 일반적인 로깅 시스템이 있습니다.이 세분화된 로깅은 JVM 충돌에 대한 근본 원인 분석을 수행하고 프로덕션 환경에서 성능 문제를 진단하는 데 유용합니다.

            오버헤드가 낮은 힙 프로파일링 

            Java 힙 할당을 샘플링하는 데 사용할 수 있는 새 API가 JVMTI(Java Virtual Machine Tool Interface)에 추가되었습니다.JFR 구현에서는 할당이 누락될 수도 있습니다. 반면 Java 11의 힙 샘플링은 라이브 개체와 데드 개체 모두에 대한 정보를 제공할 수 있습니다. APM(애플리케이션 성능 모니터링) 공급업체가 이 새로운 기능을 활용하기 시작 했습니다.

            StackWalker 

            현재 스레드의 스택에 대한 스냅샷 가져오기는 로깅할 때 주로 사용됩니다.

            5. 가비지 수집 

            Java 11에서 사용할 수 있는 가비지 수집기는 직렬, 병렬, 가비지 우선 및 엡실론입니다. Java 11의 기본 가비지 수집기는 G1GC(가비지 우선 가비지 수집기)입니다.

            ZGC일시 중지 시간을 10ms 미만으로 유지하려고 하는 대기 시간이 짧은 동시 수집기입니다. ZGC는 Java 11에서 실험적 기능으로 사용할 수 있습니다.CMS(Concurrent Mark and Sweep) 수집기는 사용할 수 있지만 Java 9 이후에는 사용되지 않습니다.

            엡실론 

            엡실론 가비지 수집기는 할당을 처리하지만 메모리를 회수하지는 않습니다. 힙이 소진되면 JVM이 종료됩니다. 엡실론은 수명이 짧은 서비스와 가비지를 사용하지 않는 것으로 알려진 애플리케이션에 유용합니다.

            Docker 컨테이너의 향상된 기능 

            Java 10 이전에 컨테이너에 설정된 메모리 및 CPU 제약 조건은 JVM에서 인식되지 않았습니다. 예를 들어 Java 8에서 JVM은 최대 힙 크기의 기본값을 기본 호스트의 실제 메모리의 ¼로 설정합니다. Java 10부터 JVM은 컨테이너 제어 그룹(cgroup)에 의해 설정된 제약 조건을 사용하여 메모리 및 CPU 제한을 설정합니다(아래 참고 사항 참조). 예를 들어 기본 최대 힙 크기는 컨테이너의 메모리 제한의 ¼입니다(예: -m2G의 경우 500MB).

            다중 릴리스 jar 파일 

            Java 11에서 클래스 파일의 여러 Java 릴리스별 버전을 포함하는 jar 파일을 만들 수 있습니다.

            6. 성능 향상

            JVM 성능향상) 

            • JEP 197: Segmented Code Cache[14] - 코드 캐시를 고유 세그먼트로 나눕니다. 이러한 구분은 JVM 메모리 공간을 보다 효율적으로 제어하고, 컴파일된 메서드의 검색 시간을 단축하고, 코드 캐시의 조각화를 크게 줄이고, 성능을 향상시킵니다.

            • JEP 254: Compact Strings[15] - 문자 인코딩에 따라 문자열의 내부 표현을 문자당 2바이트에서 문자당 1~2바이트로 변경합니다. 대부분의 문자열은 ISO-8859-1/라틴어-1 문자를 포함하므로 이 변경 내용으로 인해 문자열을 저장하는 데 필요한 공간이 효율적으로 변경됩니다.

            • JEP 310: Application Class-Data Sharing[16] - 클래스-데이터 공유는 보관된 클래스가 런타임 시 메모리에 매핑될 수 있게 하여 시작 시간을 줄여줍니다. 애플리케이션 클래스-데이터 공유는 애플리케이션 클래스를 CDS 보관함에 배치할 수 있도록 하여 클래스-데이터 공유를 확장합니다. 여러 JVM이 동일한 보관 파일을 공유하는 경우 메모리가 저장되고 전체 시스템 응답 시간이 단축됩니다.

            • JEP 312: Thread-Local Handshakes[17] - 글로벌 VM 세이프포인트를 수행하지 않고 스레드에 대한 콜백을 실행하여 VM이 글로벌 세이프포인트의 수를 줄여 대기 시간을 단축할 수 있게 해줍니다.

            • Lazy Allocation of Compiler Threads[18] - VM은 단계별 컴파일 모드에서 다량의 컴파일러 스레드를 시작합니다. 이 모드는 CPU가 여러 개 있는 시스템에서 기본값입니다. 이러한 스레드는 사용 가능한 메모리 또는 컴파일 요청 수에 관계없이 생성됩니다. 스레드는 유휴 상태일 때(거의 모든 시간) 메모리를 사용하므로 리소스를 비효율적으로 사용합니다. 이 문제를 해결하기 위해 시작 시 각 유형의 컴파일러 스레드를 하나씩만 시작하도록 구현이 변경되었습니다. 추가 스레드를 시작하고 사용하지 않는 스레드를 종료하는 것은 동적으로 처리됩니다.

            핵심 라이브러리 성능 향상) 

            • JEP 193: Variable Handles[19] - 표준을 정의한다는 것은 개체 필드 및 배열 요소, 메모리 정렬의 세부적인 제어를 위한 표준 펜스 작업 세트, 참조된 개체의 강력한 연결성을 유지하기 위한 표준 연결성 펜스 작업에 대한 다양한 java.util.concurrent.atomic 및 sun.misc.Unsafe 작업의 동급 요소를 호출하는 것을 의미합니다.

            • JEP 269: Convenience Factory Methods for Collections[20] - 소량의 요소를 사용하여 컬렉션 및 맵 인스턴스를 편리하게 만들 수 있게 해주는 라이브러리 API를 정의합니다. 컬렉션 인터페이스에서 간결하고 수정할 수 없는 컬렉션 인스턴스를 만드는 고정 팩터리 메서드입니다. 이러한 인스턴스는 본질적으로 더 효율적입니다. API는 조밀하게 표시되고 래퍼 클래스가 없는 컬렉션을 만듭니다.

            • JEP 285: Spin-Wait Hints[21] - Java에서 스핀 루프에 있음을 런타임 시스템에 암시할 수 있게 해주는 API를 제공합니다. 특정 하드웨어 플랫폼은 스레드가 바쁜 대기(busy-wait) 상태라고 소프트웨어가 알려주면 이점을 얻을 수 있습니다.

            • JEP 321: HTTP Client(Standard) [22]- HTTP/2 및 WebSocket을 구현하고 레거시 HttpURLConnection API를 대체할 수 있는 새로운 HTTP 클라이언트 API를 제공합니다.




              P.S

              다시 자바를 하면서 느낀게  "자바는 꾸준히 발전하고 있는 재밌고 가치있는 중심 언어이다"  입니다.

              2020-09-28 10:11:14 에 아래 내용에서 변경 됨 #17

              바쁜분들은 빨강색 핵심만 보시면 됩니다.

              8버전의 람다,스트림, 9버전의 모듈이라는 커다란 변경 이후 11버전의 변경점에 대한 5분 정리.





              Java 11로 전환해야 하는 이유  /  OpenJDK 11 version  정리

              (추가: Spring5 Webflux로 시작/전환하는 조직들도 많아 졌으면...정말 좋은데..)  

              API에 대한 눈에 띄는 추가 및 수정 사항이 있으며,
              시작, 성능 및 메모리 사용을 개선하는 향상된 기능이 있습니다.그리고 LTS 버전입니다.

              1. 람다 파라미터를 위한 지역변수 표현 

              java 10버전에 편리한 var 구문이 생겨난 상황에서, 11버전에서는 람다 파라미터에서  좀 더 명시적으로 var 를 이용 할 수 있게 되었습니다. 따라서 아래와 같이 어노테이션을 명시할 수 있게 되었습니다.

              list.stream()
                  .map((@NotNull var s) -> s.toLowerCase())
                  .collect(Collectors.toList());

              2. HTTP Client (Standard) 

              Non-Blocking request and response 지원 (with CompletableFuture)
              Backpressure 지원(java.util.concurrent.Flow 패키지를 통해 Rx Flow를 구현체에 적용)
              Factory method 형태로 지원
              HTTP/2 지원
              // 비동기 호출 예
              public class HttpClientAsynchronous {
              private static final HttpClient httpClient = HttpClient.newBuilder()
              .version(HttpClient.Version.HTTP_2)
              .connectTimeout(Duration.ofSeconds(10))
              .build();
              public static void main(String[] args) throws Exception {
              HttpRequest request = HttpRequest.newBuilder()
              .GET()
              .uri(URI.create("https://httpbin.org/get"))
              .setHeader("User-Agent", "Java 11 HttpClient Bot")
              .build();
              CompletableFuture<HttpResponse<String>> response =
              httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString());
              String result = response.thenApply(HttpResponse::body).get(5, TimeUnit.SECONDS);
              System.out.println(result);
              }
              } // 여러군데 비동기 호출
              public class HttpClientCustomExecutor {
              // custom executor
              private static final ExecutorService executorService = Executors.newFixedThreadPool(5);
              private static final HttpClient httpClient = HttpClient.newBuilder()
              .executor(executorService)
              .version(HttpClient.Version.HTTP_2)
              .connectTimeout(Duration.ofSeconds(10))
              .build(); public static void main(String[] args) throws Exception {
              List<URI> targets = Arrays.asList(
              new URI("https://httpbin.org/get?name=mkyong1"),
              new URI("https://httpbin.org/get?name=mkyong2"),
              new URI("https://httpbin.org/get?name=mkyong3"));

                      List<CompletableFuture<String>> result = targets.stream()
              .map(url -> httpClient.sendAsync(
              HttpRequest.newBuilder(url)
              .GET()
              .setHeader("User-Agent", "Java 11 HttpClient Bot")
              .build(),
              HttpResponse.BodyHandlers.ofString())
              .thenApply(response -> response.body()))
              .collect(Collectors.toList()); for (CompletableFuture<String> future : result) {
              System.out.println(future.get());
              }
              }
              }
              참고로 Spring5에서는 Rest Client에 RestTemplate 대신해 WebClient를 사용하여 비동기구현을 할 수 있게 되었습니다. 기존 멀티쓰레드 방식을 버리고 Reactor(WebFlux) 와 함께 스프링 기반 웹서비스를 구현할 경우 그에 따른  성능과 효율 향상은 어마어마 합니다.

              3. 모듈 

              모듈을 통해 애플리케이션에 필요한 구성 요소만 포함하는 런타임 구성을 사용자 지정할 수 있습니다. 이 사용자 지정은 메모리 공간을 더 적게 사용하며 애플리케이션이 jlink를 사용하여 배포용 사용자 지정 런타임에 정적으로 연결될 수 있게 해줍니다. 메모리 공간을 적게 사용하면 특히 마이크로서비스 아키텍처에서 유용할 수 있습니다.

              내부적으로 JVM은 모듈을 활용하여 클래스 로딩을 보다 효율적으로 만들 수 있습니다. 그 결과 런타임이 더 작아지고, 더 가벼워져서 더 빠르게 시작할 수 있습니다. 모듈은 클래스에 필요한 구성 요소를 인코딩하기 때문에 JVM에서 애플리케이션 성능을 개선하기 위해 사용하는 최적화 기법의 효과가 더 좋아질 수 있습니다.

              프로그래머의 경우 모듈은 모듈이 내보내는 패키지와 필요한 구성 요소를 명시적으로 선언하고 반사적 액세스를 제한하여 강력한 캡슐화를 적용하는 데 도움이 됩니다. 이 캡슐화 수준을 사용하면 애플리케이션을 더 안전하고 쉽게 유지 관리할 수 있습니다.


              4. 프로파일링 및 진단

              Java Flight Recorder 

              JFR(Java Flight Recorder)은 실행 중인 Java 애플리케이션에서 진단 및 프로파일링 데이터를 수집합니다.  JFR 및 JMC는 Java 8에서 상용 기능이지만 Java 11에서는 둘 다 오픈 소스입니다.

              Java Mission Control 

              JMC(Java Mission Control)는 JFR(Java Flight Recorder)에서 수집한 데이터를 그래픽으로 표시하고 Java에서는 오픈 소스로 제공됩니다. JFR 및 JMC를 사용하면 메모리 누수, GC 오버헤드, 핫 메서드, 스레드 병목 상태 및 I/O 블로킹과 같은 런타임 문제를 진단할 수 있습니다.

              통합 로깅 

              Java 11에는 JVM의 모든 구성 요소에 대한 일반적인 로깅 시스템이 있습니다.이 세분화된 로깅은 JVM 충돌에 대한 근본 원인 분석을 수행하고 프로덕션 환경에서 성능 문제를 진단하는 데 유용합니다.

              오버헤드가 낮은 힙 프로파일링 

              Java 힙 할당을 샘플링하는 데 사용할 수 있는 새 API가 JVMTI(Java Virtual Machine Tool Interface)에 추가되었습니다.JFR 구현에서는 할당이 누락될 수도 있습니다. 반면 Java 11의 힙 샘플링은 라이브 개체와 데드 개체 모두에 대한 정보를 제공할 수 있습니다. APM(애플리케이션 성능 모니터링) 공급업체가 이 새로운 기능을 활용하기 시작 했습니다.

              StackWalker 

              현재 스레드의 스택에 대한 스냅샷 가져오기는 로깅할 때 주로 사용됩니다.

              5. 가비지 수집 

              Java 11에서 사용할 수 있는 가비지 수집기는 직렬, 병렬, 가비지 우선 및 엡실론입니다. Java 11의 기본 가비지 수집기는 G1GC(가비지 우선 가비지 수집기)입니다.

              ZGC일시 중지 시간을 10ms 미만으로 유지하려고 하는 대기 시간이 짧은 동시 수집기입니다. ZGC는 Java 11에서 실험적 기능으로 사용할 수 있습니다.CMS(Concurrent Mark and Sweep) 수집기는 사용할 수 있지만 Java 9 이후에는 사용되지 않습니다.

              엡실론 

              엡실론 가비지 수집기는 할당을 처리하지만 메모리를 회수하지는 않습니다. 힙이 소진되면 JVM이 종료됩니다. 엡실론은 수명이 짧은 서비스와 가비지를 사용하지 않는 것으로 알려진 애플리케이션에 유용합니다.

              Docker 컨테이너의 향상된 기능 

              Java 10 이전에 컨테이너에 설정된 메모리 및 CPU 제약 조건은 JVM에서 인식되지 않았습니다. 예를 들어 Java 8에서 JVM은 최대 힙 크기의 기본값을 기본 호스트의 실제 메모리의 ¼로 설정합니다. Java 10부터 JVM은 컨테이너 제어 그룹(cgroup)에 의해 설정된 제약 조건을 사용하여 메모리 및 CPU 제한을 설정합니다(아래 참고 사항 참조). 예를 들어 기본 최대 힙 크기는 컨테이너의 메모리 제한의 ¼입니다(예: -m2G의 경우 500MB).

              다중 릴리스 jar 파일 

              Java 11에서 클래스 파일의 여러 Java 릴리스별 버전을 포함하는 jar 파일을 만들 수 있습니다.

              6. 성능 향상

              JVM 성능향상) 

              • JEP 197: Segmented Code Cache[14] - 코드 캐시를 고유 세그먼트로 나눕니다. 이러한 구분은 JVM 메모리 공간을 보다 효율적으로 제어하고, 컴파일된 메서드의 검색 시간을 단축하고, 코드 캐시의 조각화를 크게 줄이고, 성능을 향상시킵니다.

              • JEP 254: Compact Strings[15] - 문자 인코딩에 따라 문자열의 내부 표현을 문자당 2바이트에서 문자당 1~2바이트로 변경합니다. 대부분의 문자열은 ISO-8859-1/라틴어-1 문자를 포함하므로 이 변경 내용으로 인해 문자열을 저장하는 데 필요한 공간이 효율적으로 변경됩니다.

              • JEP 310: Application Class-Data Sharing[16] - 클래스-데이터 공유는 보관된 클래스가 런타임 시 메모리에 매핑될 수 있게 하여 시작 시간을 줄여줍니다. 애플리케이션 클래스-데이터 공유는 애플리케이션 클래스를 CDS 보관함에 배치할 수 있도록 하여 클래스-데이터 공유를 확장합니다. 여러 JVM이 동일한 보관 파일을 공유하는 경우 메모리가 저장되고 전체 시스템 응답 시간이 단축됩니다.

              • JEP 312: Thread-Local Handshakes[17] - 글로벌 VM 세이프포인트를 수행하지 않고 스레드에 대한 콜백을 실행하여 VM이 글로벌 세이프포인트의 수를 줄여 대기 시간을 단축할 수 있게 해줍니다.

              • Lazy Allocation of Compiler Threads[18] - VM은 단계별 컴파일 모드에서 다량의 컴파일러 스레드를 시작합니다. 이 모드는 CPU가 여러 개 있는 시스템에서 기본값입니다. 이러한 스레드는 사용 가능한 메모리 또는 컴파일 요청 수에 관계없이 생성됩니다. 스레드는 유휴 상태일 때(거의 모든 시간) 메모리를 사용하므로 리소스를 비효율적으로 사용합니다. 이 문제를 해결하기 위해 시작 시 각 유형의 컴파일러 스레드를 하나씩만 시작하도록 구현이 변경되었습니다. 추가 스레드를 시작하고 사용하지 않는 스레드를 종료하는 것은 동적으로 처리됩니다.

              핵심 라이브러리 성능 향상) 

              • JEP 193: Variable Handles[19] - 표준을 정의한다는 것은 개체 필드 및 배열 요소, 메모리 정렬의 세부적인 제어를 위한 표준 펜스 작업 세트, 참조된 개체의 강력한 연결성을 유지하기 위한 표준 연결성 펜스 작업에 대한 다양한 java.util.concurrent.atomic 및 sun.misc.Unsafe 작업의 동급 요소를 호출하는 것을 의미합니다.

              • JEP 269: Convenience Factory Methods for Collections[20] - 소량의 요소를 사용하여 컬렉션 및 맵 인스턴스를 편리하게 만들 수 있게 해주는 라이브러리 API를 정의합니다. 컬렉션 인터페이스에서 간결하고 수정할 수 없는 컬렉션 인스턴스를 만드는 고정 팩터리 메서드입니다. 이러한 인스턴스는 본질적으로 더 효율적입니다. API는 조밀하게 표시되고 래퍼 클래스가 없는 컬렉션을 만듭니다.

              • JEP 285: Spin-Wait Hints[21] - Java에서 스핀 루프에 있음을 런타임 시스템에 암시할 수 있게 해주는 API를 제공합니다. 특정 하드웨어 플랫폼은 스레드가 바쁜 대기(busy-wait) 상태라고 소프트웨어가 알려주면 이점을 얻을 수 있습니다.

              • JEP 321: HTTP Client(Standard) [22]- HTTP/2 및 WebSocket을 구현하고 레거시 HttpURLConnection API를 대체할 수 있는 새로운 HTTP 클라이언트 API를 제공합니다.




                P.S

                다시 자바를 하면서 느낀게  "자바는 꾸준히 발전하고 있는 재밌고 가치있는 중심 언어이다"  입니다.

                2020-09-28 10:10:16 에 아래 내용에서 변경 됨 #16

                바쁜분들은 빨강색 핵심만 보시면 됩니다.

                8버전의 람다, 9버전의 모듈이라는 커다란 변경 이후 11버전의 변경점에 대한 5분 정리.





                Java 11로 전환해야 하는 이유  /  OpenJDK 11 version  정리

                (추가: Spring5 Webflux로 시작/전환하는 조직들도 많아 졌으면...정말 좋은데..)  

                API에 대한 눈에 띄는 추가 및 수정 사항이 있으며,
                시작, 성능 및 메모리 사용을 개선하는 향상된 기능이 있습니다.그리고 LTS 버전입니다.

                1. 람다 파라미터를 위한 지역변수 표현 

                java 10버전에 편리한 var 구문이 생겨난 상황에서, 11버전에서는 람다 파라미터에서  좀 더 명시적으로 var 를 이용 할 수 있게 되었습니다. 따라서 아래와 같이 어노테이션을 명시할 수 있게 되었습니다.

                list.stream()
                    .map((@NotNull var s) -> s.toLowerCase())
                    .collect(Collectors.toList());

                2. HTTP Client (Standard) 

                Non-Blocking request and response 지원 (with CompletableFuture)
                Backpressure 지원(java.util.concurrent.Flow 패키지를 통해 Rx Flow를 구현체에 적용)
                Factory method 형태로 지원
                HTTP/2 지원
                // 비동기 호출 예
                public class HttpClientAsynchronous {
                private static final HttpClient httpClient = HttpClient.newBuilder()
                .version(HttpClient.Version.HTTP_2)
                .connectTimeout(Duration.ofSeconds(10))
                .build();
                public static void main(String[] args) throws Exception {
                HttpRequest request = HttpRequest.newBuilder()
                .GET()
                .uri(URI.create("https://httpbin.org/get"))
                .setHeader("User-Agent", "Java 11 HttpClient Bot")
                .build();
                CompletableFuture<HttpResponse<String>> response =
                httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString());
                String result = response.thenApply(HttpResponse::body).get(5, TimeUnit.SECONDS);
                System.out.println(result);
                }
                } // 여러군데 비동기 호출
                public class HttpClientCustomExecutor {
                // custom executor
                private static final ExecutorService executorService = Executors.newFixedThreadPool(5);
                private static final HttpClient httpClient = HttpClient.newBuilder()
                .executor(executorService)
                .version(HttpClient.Version.HTTP_2)
                .connectTimeout(Duration.ofSeconds(10))
                .build(); public static void main(String[] args) throws Exception {
                List<URI> targets = Arrays.asList(
                new URI("https://httpbin.org/get?name=mkyong1"),
                new URI("https://httpbin.org/get?name=mkyong2"),
                new URI("https://httpbin.org/get?name=mkyong3"));

                        List<CompletableFuture<String>> result = targets.stream()
                .map(url -> httpClient.sendAsync(
                HttpRequest.newBuilder(url)
                .GET()
                .setHeader("User-Agent", "Java 11 HttpClient Bot")
                .build(),
                HttpResponse.BodyHandlers.ofString())
                .thenApply(response -> response.body()))
                .collect(Collectors.toList()); for (CompletableFuture<String> future : result) {
                System.out.println(future.get());
                }
                }
                }
                참고로 Spring5에서는 Rest Client에 RestTemplate 대신해 WebClient를 사용하여 비동기구현을 할 수 있게 되었습니다. 기존 멀티쓰레드 방식을 버리고 Reactor(WebFlux) 와 함께 스프링 기반 웹서비스를 구현할 경우 그에 따른  성능과 효율 향상은 어마어마 합니다.

                3. 모듈 

                모듈을 통해 애플리케이션에 필요한 구성 요소만 포함하는 런타임 구성을 사용자 지정할 수 있습니다. 이 사용자 지정은 메모리 공간을 더 적게 사용하며 애플리케이션이 jlink를 사용하여 배포용 사용자 지정 런타임에 정적으로 연결될 수 있게 해줍니다. 메모리 공간을 적게 사용하면 특히 마이크로서비스 아키텍처에서 유용할 수 있습니다.

                내부적으로 JVM은 모듈을 활용하여 클래스 로딩을 보다 효율적으로 만들 수 있습니다. 그 결과 런타임이 더 작아지고, 더 가벼워져서 더 빠르게 시작할 수 있습니다. 모듈은 클래스에 필요한 구성 요소를 인코딩하기 때문에 JVM에서 애플리케이션 성능을 개선하기 위해 사용하는 최적화 기법의 효과가 더 좋아질 수 있습니다.

                프로그래머의 경우 모듈은 모듈이 내보내는 패키지와 필요한 구성 요소를 명시적으로 선언하고 반사적 액세스를 제한하여 강력한 캡슐화를 적용하는 데 도움이 됩니다. 이 캡슐화 수준을 사용하면 애플리케이션을 더 안전하고 쉽게 유지 관리할 수 있습니다.


                4. 프로파일링 및 진단

                Java Flight Recorder 

                JFR(Java Flight Recorder)은 실행 중인 Java 애플리케이션에서 진단 및 프로파일링 데이터를 수집합니다.  JFR 및 JMC는 Java 8에서 상용 기능이지만 Java 11에서는 둘 다 오픈 소스입니다.

                Java Mission Control 

                JMC(Java Mission Control)는 JFR(Java Flight Recorder)에서 수집한 데이터를 그래픽으로 표시하고 Java에서는 오픈 소스로 제공됩니다. JFR 및 JMC를 사용하면 메모리 누수, GC 오버헤드, 핫 메서드, 스레드 병목 상태 및 I/O 블로킹과 같은 런타임 문제를 진단할 수 있습니다.

                통합 로깅 

                Java 11에는 JVM의 모든 구성 요소에 대한 일반적인 로깅 시스템이 있습니다.이 세분화된 로깅은 JVM 충돌에 대한 근본 원인 분석을 수행하고 프로덕션 환경에서 성능 문제를 진단하는 데 유용합니다.

                오버헤드가 낮은 힙 프로파일링 

                Java 힙 할당을 샘플링하는 데 사용할 수 있는 새 API가 JVMTI(Java Virtual Machine Tool Interface)에 추가되었습니다.JFR 구현에서는 할당이 누락될 수도 있습니다. 반면 Java 11의 힙 샘플링은 라이브 개체와 데드 개체 모두에 대한 정보를 제공할 수 있습니다. APM(애플리케이션 성능 모니터링) 공급업체가 이 새로운 기능을 활용하기 시작 했습니다.

                StackWalker 

                현재 스레드의 스택에 대한 스냅샷 가져오기는 로깅할 때 주로 사용됩니다.

                5. 가비지 수집 

                Java 11에서 사용할 수 있는 가비지 수집기는 직렬, 병렬, 가비지 우선 및 엡실론입니다. Java 11의 기본 가비지 수집기는 G1GC(가비지 우선 가비지 수집기)입니다.

                ZGC일시 중지 시간을 10ms 미만으로 유지하려고 하는 대기 시간이 짧은 동시 수집기입니다. ZGC는 Java 11에서 실험적 기능으로 사용할 수 있습니다.CMS(Concurrent Mark and Sweep) 수집기는 사용할 수 있지만 Java 9 이후에는 사용되지 않습니다.

                엡실론 

                엡실론 가비지 수집기는 할당을 처리하지만 메모리를 회수하지는 않습니다. 힙이 소진되면 JVM이 종료됩니다. 엡실론은 수명이 짧은 서비스와 가비지를 사용하지 않는 것으로 알려진 애플리케이션에 유용합니다.

                Docker 컨테이너의 향상된 기능 

                Java 10 이전에 컨테이너에 설정된 메모리 및 CPU 제약 조건은 JVM에서 인식되지 않았습니다. 예를 들어 Java 8에서 JVM은 최대 힙 크기의 기본값을 기본 호스트의 실제 메모리의 ¼로 설정합니다. Java 10부터 JVM은 컨테이너 제어 그룹(cgroup)에 의해 설정된 제약 조건을 사용하여 메모리 및 CPU 제한을 설정합니다(아래 참고 사항 참조). 예를 들어 기본 최대 힙 크기는 컨테이너의 메모리 제한의 ¼입니다(예: -m2G의 경우 500MB).

                다중 릴리스 jar 파일 

                Java 11에서 클래스 파일의 여러 Java 릴리스별 버전을 포함하는 jar 파일을 만들 수 있습니다.

                6. 성능 향상

                JVM 성능향상) 

                • JEP 197: Segmented Code Cache[14] - 코드 캐시를 고유 세그먼트로 나눕니다. 이러한 구분은 JVM 메모리 공간을 보다 효율적으로 제어하고, 컴파일된 메서드의 검색 시간을 단축하고, 코드 캐시의 조각화를 크게 줄이고, 성능을 향상시킵니다.

                • JEP 254: Compact Strings[15] - 문자 인코딩에 따라 문자열의 내부 표현을 문자당 2바이트에서 문자당 1~2바이트로 변경합니다. 대부분의 문자열은 ISO-8859-1/라틴어-1 문자를 포함하므로 이 변경 내용으로 인해 문자열을 저장하는 데 필요한 공간이 효율적으로 변경됩니다.

                • JEP 310: Application Class-Data Sharing[16] - 클래스-데이터 공유는 보관된 클래스가 런타임 시 메모리에 매핑될 수 있게 하여 시작 시간을 줄여줍니다. 애플리케이션 클래스-데이터 공유는 애플리케이션 클래스를 CDS 보관함에 배치할 수 있도록 하여 클래스-데이터 공유를 확장합니다. 여러 JVM이 동일한 보관 파일을 공유하는 경우 메모리가 저장되고 전체 시스템 응답 시간이 단축됩니다.

                • JEP 312: Thread-Local Handshakes[17] - 글로벌 VM 세이프포인트를 수행하지 않고 스레드에 대한 콜백을 실행하여 VM이 글로벌 세이프포인트의 수를 줄여 대기 시간을 단축할 수 있게 해줍니다.

                • Lazy Allocation of Compiler Threads[18] - VM은 단계별 컴파일 모드에서 다량의 컴파일러 스레드를 시작합니다. 이 모드는 CPU가 여러 개 있는 시스템에서 기본값입니다. 이러한 스레드는 사용 가능한 메모리 또는 컴파일 요청 수에 관계없이 생성됩니다. 스레드는 유휴 상태일 때(거의 모든 시간) 메모리를 사용하므로 리소스를 비효율적으로 사용합니다. 이 문제를 해결하기 위해 시작 시 각 유형의 컴파일러 스레드를 하나씩만 시작하도록 구현이 변경되었습니다. 추가 스레드를 시작하고 사용하지 않는 스레드를 종료하는 것은 동적으로 처리됩니다.

                핵심 라이브러리 성능 향상) 

                • JEP 193: Variable Handles[19] - 표준을 정의한다는 것은 개체 필드 및 배열 요소, 메모리 정렬의 세부적인 제어를 위한 표준 펜스 작업 세트, 참조된 개체의 강력한 연결성을 유지하기 위한 표준 연결성 펜스 작업에 대한 다양한 java.util.concurrent.atomic 및 sun.misc.Unsafe 작업의 동급 요소를 호출하는 것을 의미합니다.

                • JEP 269: Convenience Factory Methods for Collections[20] - 소량의 요소를 사용하여 컬렉션 및 맵 인스턴스를 편리하게 만들 수 있게 해주는 라이브러리 API를 정의합니다. 컬렉션 인터페이스에서 간결하고 수정할 수 없는 컬렉션 인스턴스를 만드는 고정 팩터리 메서드입니다. 이러한 인스턴스는 본질적으로 더 효율적입니다. API는 조밀하게 표시되고 래퍼 클래스가 없는 컬렉션을 만듭니다.

                • JEP 285: Spin-Wait Hints[21] - Java에서 스핀 루프에 있음을 런타임 시스템에 암시할 수 있게 해주는 API를 제공합니다. 특정 하드웨어 플랫폼은 스레드가 바쁜 대기(busy-wait) 상태라고 소프트웨어가 알려주면 이점을 얻을 수 있습니다.

                • JEP 321: HTTP Client(Standard) [22]- HTTP/2 및 WebSocket을 구현하고 레거시 HttpURLConnection API를 대체할 수 있는 새로운 HTTP 클라이언트 API를 제공합니다.




                  P.S

                  다시 자바를 하면서 느낀게  "자바는 꾸준히 발전하고 있는 재밌고 가치있는 중심 언어이다"  입니다.

                  2020-09-28 10:09:35 에 아래 내용에서 변경 됨 #15

                  바쁜분들은 빨강색 핵심만 보시면 됩니다.





                  Java 11로 전환해야 하는 이유  /  OpenJDK 11 version  정리

                  (추가: Spring5 Webflux로 시작/전환하는 조직들도 많아 졌으면...정말 좋은데..)  

                  API에 대한 눈에 띄는 추가 및 수정 사항이 있으며,
                  시작, 성능 및 메모리 사용을 개선하는 향상된 기능이 있습니다.그리고 LTS 버전입니다.

                  1. 람다 파라미터를 위한 지역변수 표현 

                  java 10버전에 편리한 var 구문이 생겨난 상황에서, 11버전에서는 람다 파라미터에서  좀 더 명시적으로 var 를 이용 할 수 있게 되었습니다. 따라서 아래와 같이 어노테이션을 명시할 수 있게 되었습니다.

                  list.stream()
                      .map((@NotNull var s) -> s.toLowerCase())
                      .collect(Collectors.toList());

                  2. HTTP Client (Standard) 

                  Non-Blocking request and response 지원 (with CompletableFuture)
                  Backpressure 지원(java.util.concurrent.Flow 패키지를 통해 Rx Flow를 구현체에 적용)
                  Factory method 형태로 지원
                  HTTP/2 지원
                  // 비동기 호출 예
                  public class HttpClientAsynchronous {
                  private static final HttpClient httpClient = HttpClient.newBuilder()
                  .version(HttpClient.Version.HTTP_2)
                  .connectTimeout(Duration.ofSeconds(10))
                  .build();
                  public static void main(String[] args) throws Exception {
                  HttpRequest request = HttpRequest.newBuilder()
                  .GET()
                  .uri(URI.create("https://httpbin.org/get"))
                  .setHeader("User-Agent", "Java 11 HttpClient Bot")
                  .build();
                  CompletableFuture<HttpResponse<String>> response =
                  httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString());
                  String result = response.thenApply(HttpResponse::body).get(5, TimeUnit.SECONDS);
                  System.out.println(result);
                  }
                  } // 여러군데 비동기 호출
                  public class HttpClientCustomExecutor {
                  // custom executor
                  private static final ExecutorService executorService = Executors.newFixedThreadPool(5);
                  private static final HttpClient httpClient = HttpClient.newBuilder()
                  .executor(executorService)
                  .version(HttpClient.Version.HTTP_2)
                  .connectTimeout(Duration.ofSeconds(10))
                  .build(); public static void main(String[] args) throws Exception {
                  List<URI> targets = Arrays.asList(
                  new URI("https://httpbin.org/get?name=mkyong1"),
                  new URI("https://httpbin.org/get?name=mkyong2"),
                  new URI("https://httpbin.org/get?name=mkyong3"));

                          List<CompletableFuture<String>> result = targets.stream()
                  .map(url -> httpClient.sendAsync(
                  HttpRequest.newBuilder(url)
                  .GET()
                  .setHeader("User-Agent", "Java 11 HttpClient Bot")
                  .build(),
                  HttpResponse.BodyHandlers.ofString())
                  .thenApply(response -> response.body()))
                  .collect(Collectors.toList()); for (CompletableFuture<String> future : result) {
                  System.out.println(future.get());
                  }
                  }
                  }
                  참고로 Spring5에서는 Rest Client에 RestTemplate 대신해 WebClient를 사용하여 비동기구현을 할 수 있게 되었습니다. 기존 멀티쓰레드 방식을 버리고 Reactor(WebFlux) 와 함께 스프링 기반 웹서비스를 구현할 경우 그에 따른  성능과 효율 향상은 어마어마 합니다.

                  3. 모듈 

                  모듈을 통해 애플리케이션에 필요한 구성 요소만 포함하는 런타임 구성을 사용자 지정할 수 있습니다. 이 사용자 지정은 메모리 공간을 더 적게 사용하며 애플리케이션이 jlink를 사용하여 배포용 사용자 지정 런타임에 정적으로 연결될 수 있게 해줍니다. 메모리 공간을 적게 사용하면 특히 마이크로서비스 아키텍처에서 유용할 수 있습니다.

                  내부적으로 JVM은 모듈을 활용하여 클래스 로딩을 보다 효율적으로 만들 수 있습니다. 그 결과 런타임이 더 작아지고, 더 가벼워져서 더 빠르게 시작할 수 있습니다. 모듈은 클래스에 필요한 구성 요소를 인코딩하기 때문에 JVM에서 애플리케이션 성능을 개선하기 위해 사용하는 최적화 기법의 효과가 더 좋아질 수 있습니다.

                  프로그래머의 경우 모듈은 모듈이 내보내는 패키지와 필요한 구성 요소를 명시적으로 선언하고 반사적 액세스를 제한하여 강력한 캡슐화를 적용하는 데 도움이 됩니다. 이 캡슐화 수준을 사용하면 애플리케이션을 더 안전하고 쉽게 유지 관리할 수 있습니다.


                  4. 프로파일링 및 진단

                  Java Flight Recorder 

                  JFR(Java Flight Recorder)은 실행 중인 Java 애플리케이션에서 진단 및 프로파일링 데이터를 수집합니다.  JFR 및 JMC는 Java 8에서 상용 기능이지만 Java 11에서는 둘 다 오픈 소스입니다.

                  Java Mission Control 

                  JMC(Java Mission Control)는 JFR(Java Flight Recorder)에서 수집한 데이터를 그래픽으로 표시하고 Java에서는 오픈 소스로 제공됩니다. JFR 및 JMC를 사용하면 메모리 누수, GC 오버헤드, 핫 메서드, 스레드 병목 상태 및 I/O 블로킹과 같은 런타임 문제를 진단할 수 있습니다.

                  통합 로깅 

                  Java 11에는 JVM의 모든 구성 요소에 대한 일반적인 로깅 시스템이 있습니다.이 세분화된 로깅은 JVM 충돌에 대한 근본 원인 분석을 수행하고 프로덕션 환경에서 성능 문제를 진단하는 데 유용합니다.

                  오버헤드가 낮은 힙 프로파일링 

                  Java 힙 할당을 샘플링하는 데 사용할 수 있는 새 API가 JVMTI(Java Virtual Machine Tool Interface)에 추가되었습니다.JFR 구현에서는 할당이 누락될 수도 있습니다. 반면 Java 11의 힙 샘플링은 라이브 개체와 데드 개체 모두에 대한 정보를 제공할 수 있습니다. APM(애플리케이션 성능 모니터링) 공급업체가 이 새로운 기능을 활용하기 시작 했습니다.

                  StackWalker 

                  현재 스레드의 스택에 대한 스냅샷 가져오기는 로깅할 때 주로 사용됩니다.

                  5. 가비지 수집 

                  Java 11에서 사용할 수 있는 가비지 수집기는 직렬, 병렬, 가비지 우선 및 엡실론입니다. Java 11의 기본 가비지 수집기는 G1GC(가비지 우선 가비지 수집기)입니다.

                  ZGC일시 중지 시간을 10ms 미만으로 유지하려고 하는 대기 시간이 짧은 동시 수집기입니다. ZGC는 Java 11에서 실험적 기능으로 사용할 수 있습니다.CMS(Concurrent Mark and Sweep) 수집기는 사용할 수 있지만 Java 9 이후에는 사용되지 않습니다.

                  엡실론 

                  엡실론 가비지 수집기는 할당을 처리하지만 메모리를 회수하지는 않습니다. 힙이 소진되면 JVM이 종료됩니다. 엡실론은 수명이 짧은 서비스와 가비지를 사용하지 않는 것으로 알려진 애플리케이션에 유용합니다.

                  Docker 컨테이너의 향상된 기능 

                  Java 10 이전에 컨테이너에 설정된 메모리 및 CPU 제약 조건은 JVM에서 인식되지 않았습니다. 예를 들어 Java 8에서 JVM은 최대 힙 크기의 기본값을 기본 호스트의 실제 메모리의 ¼로 설정합니다. Java 10부터 JVM은 컨테이너 제어 그룹(cgroup)에 의해 설정된 제약 조건을 사용하여 메모리 및 CPU 제한을 설정합니다(아래 참고 사항 참조). 예를 들어 기본 최대 힙 크기는 컨테이너의 메모리 제한의 ¼입니다(예: -m2G의 경우 500MB).

                  다중 릴리스 jar 파일 

                  Java 11에서 클래스 파일의 여러 Java 릴리스별 버전을 포함하는 jar 파일을 만들 수 있습니다.

                  6. 성능 향상

                  JVM 성능향상) 

                  • JEP 197: Segmented Code Cache[14] - 코드 캐시를 고유 세그먼트로 나눕니다. 이러한 구분은 JVM 메모리 공간을 보다 효율적으로 제어하고, 컴파일된 메서드의 검색 시간을 단축하고, 코드 캐시의 조각화를 크게 줄이고, 성능을 향상시킵니다.

                  • JEP 254: Compact Strings[15] - 문자 인코딩에 따라 문자열의 내부 표현을 문자당 2바이트에서 문자당 1~2바이트로 변경합니다. 대부분의 문자열은 ISO-8859-1/라틴어-1 문자를 포함하므로 이 변경 내용으로 인해 문자열을 저장하는 데 필요한 공간이 효율적으로 변경됩니다.

                  • JEP 310: Application Class-Data Sharing[16] - 클래스-데이터 공유는 보관된 클래스가 런타임 시 메모리에 매핑될 수 있게 하여 시작 시간을 줄여줍니다. 애플리케이션 클래스-데이터 공유는 애플리케이션 클래스를 CDS 보관함에 배치할 수 있도록 하여 클래스-데이터 공유를 확장합니다. 여러 JVM이 동일한 보관 파일을 공유하는 경우 메모리가 저장되고 전체 시스템 응답 시간이 단축됩니다.

                  • JEP 312: Thread-Local Handshakes[17] - 글로벌 VM 세이프포인트를 수행하지 않고 스레드에 대한 콜백을 실행하여 VM이 글로벌 세이프포인트의 수를 줄여 대기 시간을 단축할 수 있게 해줍니다.

                  • Lazy Allocation of Compiler Threads[18] - VM은 단계별 컴파일 모드에서 다량의 컴파일러 스레드를 시작합니다. 이 모드는 CPU가 여러 개 있는 시스템에서 기본값입니다. 이러한 스레드는 사용 가능한 메모리 또는 컴파일 요청 수에 관계없이 생성됩니다. 스레드는 유휴 상태일 때(거의 모든 시간) 메모리를 사용하므로 리소스를 비효율적으로 사용합니다. 이 문제를 해결하기 위해 시작 시 각 유형의 컴파일러 스레드를 하나씩만 시작하도록 구현이 변경되었습니다. 추가 스레드를 시작하고 사용하지 않는 스레드를 종료하는 것은 동적으로 처리됩니다.

                  핵심 라이브러리 성능 향상) 

                  • JEP 193: Variable Handles[19] - 표준을 정의한다는 것은 개체 필드 및 배열 요소, 메모리 정렬의 세부적인 제어를 위한 표준 펜스 작업 세트, 참조된 개체의 강력한 연결성을 유지하기 위한 표준 연결성 펜스 작업에 대한 다양한 java.util.concurrent.atomic 및 sun.misc.Unsafe 작업의 동급 요소를 호출하는 것을 의미합니다.

                  • JEP 269: Convenience Factory Methods for Collections[20] - 소량의 요소를 사용하여 컬렉션 및 맵 인스턴스를 편리하게 만들 수 있게 해주는 라이브러리 API를 정의합니다. 컬렉션 인터페이스에서 간결하고 수정할 수 없는 컬렉션 인스턴스를 만드는 고정 팩터리 메서드입니다. 이러한 인스턴스는 본질적으로 더 효율적입니다. API는 조밀하게 표시되고 래퍼 클래스가 없는 컬렉션을 만듭니다.

                  • JEP 285: Spin-Wait Hints[21] - Java에서 스핀 루프에 있음을 런타임 시스템에 암시할 수 있게 해주는 API를 제공합니다. 특정 하드웨어 플랫폼은 스레드가 바쁜 대기(busy-wait) 상태라고 소프트웨어가 알려주면 이점을 얻을 수 있습니다.

                  • JEP 321: HTTP Client(Standard) [22]- HTTP/2 및 WebSocket을 구현하고 레거시 HttpURLConnection API를 대체할 수 있는 새로운 HTTP 클라이언트 API를 제공합니다.




                    P.S

                    다시 자바를 하면서 느낀게  "자바는 꾸준히 발전하고 있는 재밌고 가치있는 중심 언어이다"  입니다.

                    2020-09-25 09:29:52 에 아래 내용에서 변경 됨 #14


                    Java 11로 전환해야 하는 이유  /  OpenJDK 11 version  정리

                    (추가: Spring5 Webflux로 시작/전환하는 조직들도 많아 졌으면...정말 좋은데..)  

                    API에 대한 눈에 띄는 추가 및 수정 사항이 있으며,
                    시작, 성능 및 메모리 사용을 개선하는 향상된 기능이 있습니다.그리고 LTS 버전입니다.

                    1. 람다 파라미터를 위한 지역변수 표현 

                    java 10버전에 편리한 var 구문이 생겨난 상황에서, 11버전에서는 람다 파라미터에서  좀 더 명시적으로 var 를 이용 할 수 있게 되었습니다. 따라서 아래와 같이 어노테이션을 명시할 수 있게 되었습니다.

                    list.stream()
                        .map((@NotNull var s) -> s.toLowerCase())
                        .collect(Collectors.toList());

                    2. HTTP Client (Standard) 

                    Non-Blocking request and response 지원 (with CompletableFuture)
                    Backpressure 지원(java.util.concurrent.Flow 패키지를 통해 Rx Flow를 구현체에 적용)
                    Factory method 형태로 지원
                    HTTP/2 지원
                    // 비동기 호출 예
                    public class HttpClientAsynchronous {
                    private static final HttpClient httpClient = HttpClient.newBuilder()
                    .version(HttpClient.Version.HTTP_2)
                    .connectTimeout(Duration.ofSeconds(10))
                    .build();
                    public static void main(String[] args) throws Exception {
                    HttpRequest request = HttpRequest.newBuilder()
                    .GET()
                    .uri(URI.create("https://httpbin.org/get"))
                    .setHeader("User-Agent", "Java 11 HttpClient Bot")
                    .build();
                    CompletableFuture<HttpResponse<String>> response =
                    httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString());
                    String result = response.thenApply(HttpResponse::body).get(5, TimeUnit.SECONDS);
                    System.out.println(result);
                    }
                    } // 여러군데 비동기 호출
                    public class HttpClientCustomExecutor {
                    // custom executor
                    private static final ExecutorService executorService = Executors.newFixedThreadPool(5);
                    private static final HttpClient httpClient = HttpClient.newBuilder()
                    .executor(executorService)
                    .version(HttpClient.Version.HTTP_2)
                    .connectTimeout(Duration.ofSeconds(10))
                    .build(); public static void main(String[] args) throws Exception {
                    List<URI> targets = Arrays.asList(
                    new URI("https://httpbin.org/get?name=mkyong1"),
                    new URI("https://httpbin.org/get?name=mkyong2"),
                    new URI("https://httpbin.org/get?name=mkyong3"));

                            List<CompletableFuture<String>> result = targets.stream()
                    .map(url -> httpClient.sendAsync(
                    HttpRequest.newBuilder(url)
                    .GET()
                    .setHeader("User-Agent", "Java 11 HttpClient Bot")
                    .build(),
                    HttpResponse.BodyHandlers.ofString())
                    .thenApply(response -> response.body()))
                    .collect(Collectors.toList()); for (CompletableFuture<String> future : result) {
                    System.out.println(future.get());
                    }
                    }
                    }
                    참고로 Spring5에서는 Rest Client에 RestTemplate 대신해 WebClient를 사용하여 비동기구현을 할 수 있게 되었습니다. 기존 멀티쓰레드 방식을 버리고 Reactor(WebFlux) 와 함께 스프링 기반 웹서비스를 구현할 경우 그에 따른  성능과 효율 향상은 어마어마 합니다.

                    3. 모듈 

                    모듈을 통해 애플리케이션에 필요한 구성 요소만 포함하는 런타임 구성을 사용자 지정할 수 있습니다. 이 사용자 지정은 메모리 공간을 더 적게 사용하며 애플리케이션이 jlink를 사용하여 배포용 사용자 지정 런타임에 정적으로 연결될 수 있게 해줍니다. 메모리 공간을 적게 사용하면 특히 마이크로서비스 아키텍처에서 유용할 수 있습니다.

                    내부적으로 JVM은 모듈을 활용하여 클래스 로딩을 보다 효율적으로 만들 수 있습니다. 그 결과 런타임이 더 작아지고, 더 가벼워져서 더 빠르게 시작할 수 있습니다. 모듈은 클래스에 필요한 구성 요소를 인코딩하기 때문에 JVM에서 애플리케이션 성능을 개선하기 위해 사용하는 최적화 기법의 효과가 더 좋아질 수 있습니다.

                    프로그래머의 경우 모듈은 모듈이 내보내는 패키지와 필요한 구성 요소를 명시적으로 선언하고 반사적 액세스를 제한하여 강력한 캡슐화를 적용하는 데 도움이 됩니다. 이 캡슐화 수준을 사용하면 애플리케이션을 더 안전하고 쉽게 유지 관리할 수 있습니다.


                    4. 프로파일링 및 진단

                    Java Flight Recorder 

                    JFR(Java Flight Recorder)은 실행 중인 Java 애플리케이션에서 진단 및 프로파일링 데이터를 수집합니다.  JFR 및 JMC는 Java 8에서 상용 기능이지만 Java 11에서는 둘 다 오픈 소스입니다.

                    Java Mission Control 

                    JMC(Java Mission Control)는 JFR(Java Flight Recorder)에서 수집한 데이터를 그래픽으로 표시하고 Java에서는 오픈 소스로 제공됩니다. JFR 및 JMC를 사용하면 메모리 누수, GC 오버헤드, 핫 메서드, 스레드 병목 상태 및 I/O 블로킹과 같은 런타임 문제를 진단할 수 있습니다.

                    통합 로깅 

                    Java 11에는 JVM의 모든 구성 요소에 대한 일반적인 로깅 시스템이 있습니다.이 세분화된 로깅은 JVM 충돌에 대한 근본 원인 분석을 수행하고 프로덕션 환경에서 성능 문제를 진단하는 데 유용합니다.

                    오버헤드가 낮은 힙 프로파일링 

                    Java 힙 할당을 샘플링하는 데 사용할 수 있는 새 API가 JVMTI(Java Virtual Machine Tool Interface)에 추가되었습니다.JFR 구현에서는 할당이 누락될 수도 있습니다. 반면 Java 11의 힙 샘플링은 라이브 개체와 데드 개체 모두에 대한 정보를 제공할 수 있습니다. APM(애플리케이션 성능 모니터링) 공급업체가 이 새로운 기능을 활용하기 시작 했습니다.

                    StackWalker 

                    현재 스레드의 스택에 대한 스냅샷 가져오기는 로깅할 때 주로 사용됩니다.

                    5. 가비지 수집 

                    Java 11에서 사용할 수 있는 가비지 수집기는 직렬, 병렬, 가비지 우선 및 엡실론입니다. Java 11의 기본 가비지 수집기는 G1GC(가비지 우선 가비지 수집기)입니다.

                    ZGC일시 중지 시간을 10ms 미만으로 유지하려고 하는 대기 시간이 짧은 동시 수집기입니다. ZGC는 Java 11에서 실험적 기능으로 사용할 수 있습니다.CMS(Concurrent Mark and Sweep) 수집기는 사용할 수 있지만 Java 9 이후에는 사용되지 않습니다.

                    엡실론 

                    엡실론 가비지 수집기는 할당을 처리하지만 메모리를 회수하지는 않습니다. 힙이 소진되면 JVM이 종료됩니다. 엡실론은 수명이 짧은 서비스와 가비지를 사용하지 않는 것으로 알려진 애플리케이션에 유용합니다.

                    Docker 컨테이너의 향상된 기능 

                    Java 10 이전에 컨테이너에 설정된 메모리 및 CPU 제약 조건은 JVM에서 인식되지 않았습니다. 예를 들어 Java 8에서 JVM은 최대 힙 크기의 기본값을 기본 호스트의 실제 메모리의 ¼로 설정합니다. Java 10부터 JVM은 컨테이너 제어 그룹(cgroup)에 의해 설정된 제약 조건을 사용하여 메모리 및 CPU 제한을 설정합니다(아래 참고 사항 참조). 예를 들어 기본 최대 힙 크기는 컨테이너의 메모리 제한의 ¼입니다(예: -m2G의 경우 500MB).

                    다중 릴리스 jar 파일 

                    Java 11에서 클래스 파일의 여러 Java 릴리스별 버전을 포함하는 jar 파일을 만들 수 있습니다.

                    6. 성능 향상

                    JVM 성능향상) 

                    • JEP 197: Segmented Code Cache[14] - 코드 캐시를 고유 세그먼트로 나눕니다. 이러한 구분은 JVM 메모리 공간을 보다 효율적으로 제어하고, 컴파일된 메서드의 검색 시간을 단축하고, 코드 캐시의 조각화를 크게 줄이고, 성능을 향상시킵니다.

                    • JEP 254: Compact Strings[15] - 문자 인코딩에 따라 문자열의 내부 표현을 문자당 2바이트에서 문자당 1~2바이트로 변경합니다. 대부분의 문자열은 ISO-8859-1/라틴어-1 문자를 포함하므로 이 변경 내용으로 인해 문자열을 저장하는 데 필요한 공간이 효율적으로 변경됩니다.

                    • JEP 310: Application Class-Data Sharing[16] - 클래스-데이터 공유는 보관된 클래스가 런타임 시 메모리에 매핑될 수 있게 하여 시작 시간을 줄여줍니다. 애플리케이션 클래스-데이터 공유는 애플리케이션 클래스를 CDS 보관함에 배치할 수 있도록 하여 클래스-데이터 공유를 확장합니다. 여러 JVM이 동일한 보관 파일을 공유하는 경우 메모리가 저장되고 전체 시스템 응답 시간이 단축됩니다.

                    • JEP 312: Thread-Local Handshakes[17] - 글로벌 VM 세이프포인트를 수행하지 않고 스레드에 대한 콜백을 실행하여 VM이 글로벌 세이프포인트의 수를 줄여 대기 시간을 단축할 수 있게 해줍니다.

                    • Lazy Allocation of Compiler Threads[18] - VM은 단계별 컴파일 모드에서 다량의 컴파일러 스레드를 시작합니다. 이 모드는 CPU가 여러 개 있는 시스템에서 기본값입니다. 이러한 스레드는 사용 가능한 메모리 또는 컴파일 요청 수에 관계없이 생성됩니다. 스레드는 유휴 상태일 때(거의 모든 시간) 메모리를 사용하므로 리소스를 비효율적으로 사용합니다. 이 문제를 해결하기 위해 시작 시 각 유형의 컴파일러 스레드를 하나씩만 시작하도록 구현이 변경되었습니다. 추가 스레드를 시작하고 사용하지 않는 스레드를 종료하는 것은 동적으로 처리됩니다.

                    핵심 라이브러리 성능 향상) 

                    • JEP 193: Variable Handles[19] - 표준을 정의한다는 것은 개체 필드 및 배열 요소, 메모리 정렬의 세부적인 제어를 위한 표준 펜스 작업 세트, 참조된 개체의 강력한 연결성을 유지하기 위한 표준 연결성 펜스 작업에 대한 다양한 java.util.concurrent.atomic 및 sun.misc.Unsafe 작업의 동급 요소를 호출하는 것을 의미합니다.

                    • JEP 269: Convenience Factory Methods for Collections[20] - 소량의 요소를 사용하여 컬렉션 및 맵 인스턴스를 편리하게 만들 수 있게 해주는 라이브러리 API를 정의합니다. 컬렉션 인터페이스에서 간결하고 수정할 수 없는 컬렉션 인스턴스를 만드는 고정 팩터리 메서드입니다. 이러한 인스턴스는 본질적으로 더 효율적입니다. API는 조밀하게 표시되고 래퍼 클래스가 없는 컬렉션을 만듭니다.

                    • JEP 285: Spin-Wait Hints[21] - Java에서 스핀 루프에 있음을 런타임 시스템에 암시할 수 있게 해주는 API를 제공합니다. 특정 하드웨어 플랫폼은 스레드가 바쁜 대기(busy-wait) 상태라고 소프트웨어가 알려주면 이점을 얻을 수 있습니다.

                    • JEP 321: HTTP Client(Standard) [22]- HTTP/2 및 WebSocket을 구현하고 레거시 HttpURLConnection API를 대체할 수 있는 새로운 HTTP 클라이언트 API를 제공합니다.




                      P.S

                      다시 자바를 하면서 느낀게  "자바는 꾸준히 발전하고 있는 재밌고 가치있는 중심 언어이다"  입니다.

                      2020-09-24 19:01:49 에 아래 내용에서 변경 됨 #13


                      Java 11로 전환해야 하는 이유  /  OpenJDK 11 version  정리

                      (추가: Spring5 Webflux로 시작/전환하는 조직들도 많아 졌으면...정말 좋은데..)  

                      API에 대한 눈에 띄는 추가 및 수정 사항이 있으며,
                      시작, 성능 및 메모리 사용을 개선하는 향상된 기능이 있습니다.그리고 LTS 버전입니다.

                      1. 람다 파라미터를 위한 지역변수 표현 

                      java 10버전에 편리한 var 구문이 생겨난 상황에서, 11버전에서는 람다 파라미터에서  좀 더 명시적으로 var 를 이용 할 수 있게 되었습니다. 따라서 아래와 같이 어노테이션을 명시할 수 있게 되었습니다.

                      list.stream()
                          .map((@NotNull var s) -> s.toLowerCase())
                          .collect(Collectors.toList());

                      2. HTTP Client (Standard) 

                      Non-Blocking request and response 지원 (with CompletableFuture)
                      Backpressure 지원(java.util.concurrent.Flow 패키지를 통해 Rx Flow를 구현체에 적용)
                      Factory method 형태로 지원
                      HTTP/2 지원
                      // 비동기 호출 예
                      public class HttpClientAsynchronous {
                      private static final HttpClient httpClient = HttpClient.newBuilder()
                      .version(HttpClient.Version.HTTP_2)
                      .connectTimeout(Duration.ofSeconds(10))
                      .build();
                      public static void main(String[] args) throws Exception {
                      HttpRequest request = HttpRequest.newBuilder()
                      .GET()
                      .uri(URI.create("https://httpbin.org/get"))
                      .setHeader("User-Agent", "Java 11 HttpClient Bot")
                      .build();
                      CompletableFuture<HttpResponse<String>> response =
                      httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString());
                      String result = response.thenApply(HttpResponse::body).get(5, TimeUnit.SECONDS);
                      System.out.println(result);
                      }
                      }
                      // 여러군데 비동기 호출
                      public class HttpClientCustomExecutor {
                      // custom executor
                      private static final ExecutorService executorService = Executors.newFixedThreadPool(5);
                      private static final HttpClient httpClient = HttpClient.newBuilder()
                      .executor(executorService)
                      .version(HttpClient.Version.HTTP_2)
                      .connectTimeout(Duration.ofSeconds(10))
                      .build(); public static void main(String[] args) throws Exception {
                      List<URI> targets = Arrays.asList(
                      new URI("https://httpbin.org/get?name=mkyong1"),
                      new URI("https://httpbin.org/get?name=mkyong2"),
                      new URI("https://httpbin.org/get?name=mkyong3"));

                              List<CompletableFuture<String>> result = targets.stream()
                      .map(url -> httpClient.sendAsync(
                      HttpRequest.newBuilder(url)
                      .GET()
                      .setHeader("User-Agent", "Java 11 HttpClient Bot")
                      .build(),
                      HttpResponse.BodyHandlers.ofString())
                      .thenApply(response -> response.body()))
                      .collect(Collectors.toList()); for (CompletableFuture<String> future : result) {
                      System.out.println(future.get());
                      }
                      }
                      }
                      참고로 Spring5에서는 Rest Client에 RestTemplate 대신해 WebClient를 사용하여 비동기구현을 할 수 있게 되었습니다. 기존 멀티쓰레드 방식을 버리고 Reactor(WebFlux) 와 함께 스프링 기반 웹서비스를 구현할 경우 그에 따른  성능과 효율 향상은 어마어마 합니다.

                      3. 모듈 

                      모듈을 통해 애플리케이션에 필요한 구성 요소만 포함하는 런타임 구성을 사용자 지정할 수 있습니다. 이 사용자 지정은 메모리 공간을 더 적게 사용하며 애플리케이션이 jlink를 사용하여 배포용 사용자 지정 런타임에 정적으로 연결될 수 있게 해줍니다. 메모리 공간을 적게 사용하면 특히 마이크로서비스 아키텍처에서 유용할 수 있습니다.

                      내부적으로 JVM은 모듈을 활용하여 클래스 로딩을 보다 효율적으로 만들 수 있습니다. 그 결과 런타임이 더 작아지고, 더 가벼워져서 더 빠르게 시작할 수 있습니다. 모듈은 클래스에 필요한 구성 요소를 인코딩하기 때문에 JVM에서 애플리케이션 성능을 개선하기 위해 사용하는 최적화 기법의 효과가 더 좋아질 수 있습니다.

                      프로그래머의 경우 모듈은 모듈이 내보내는 패키지와 필요한 구성 요소를 명시적으로 선언하고 반사적 액세스를 제한하여 강력한 캡슐화를 적용하는 데 도움이 됩니다. 이 캡슐화 수준을 사용하면 애플리케이션을 더 안전하고 쉽게 유지 관리할 수 있습니다.


                      4. 프로파일링 및 진단

                      Java Flight Recorder 

                      JFR(Java Flight Recorder)은 실행 중인 Java 애플리케이션에서 진단 및 프로파일링 데이터를 수집합니다.  JFR 및 JMC는 Java 8에서 상용 기능이지만 Java 11에서는 둘 다 오픈 소스입니다.

                      Java Mission Control 

                      JMC(Java Mission Control)는 JFR(Java Flight Recorder)에서 수집한 데이터를 그래픽으로 표시하고 Java에서는 오픈 소스로 제공됩니다. JFR 및 JMC를 사용하면 메모리 누수, GC 오버헤드, 핫 메서드, 스레드 병목 상태 및 I/O 블로킹과 같은 런타임 문제를 진단할 수 있습니다.

                      통합 로깅 

                      Java 11에는 JVM의 모든 구성 요소에 대한 일반적인 로깅 시스템이 있습니다.이 세분화된 로깅은 JVM 충돌에 대한 근본 원인 분석을 수행하고 프로덕션 환경에서 성능 문제를 진단하는 데 유용합니다.

                      오버헤드가 낮은 힙 프로파일링 

                      Java 힙 할당을 샘플링하는 데 사용할 수 있는 새 API가 JVMTI(Java Virtual Machine Tool Interface)에 추가되었습니다.JFR 구현에서는 할당이 누락될 수도 있습니다. 반면 Java 11의 힙 샘플링은 라이브 개체와 데드 개체 모두에 대한 정보를 제공할 수 있습니다. APM(애플리케이션 성능 모니터링) 공급업체가 이 새로운 기능을 활용하기 시작 했습니다.

                      StackWalker 

                      현재 스레드의 스택에 대한 스냅샷 가져오기는 로깅할 때 주로 사용됩니다.

                      5. 가비지 수집 

                      Java 11에서 사용할 수 있는 가비지 수집기는 직렬, 병렬, 가비지 우선 및 엡실론입니다. Java 11의 기본 가비지 수집기는 G1GC(가비지 우선 가비지 수집기)입니다.

                      ZGC일시 중지 시간을 10ms 미만으로 유지하려고 하는 대기 시간이 짧은 동시 수집기입니다. ZGC는 Java 11에서 실험적 기능으로 사용할 수 있습니다.CMS(Concurrent Mark and Sweep) 수집기는 사용할 수 있지만 Java 9 이후에는 사용되지 않습니다.

                      엡실론 

                      엡실론 가비지 수집기는 할당을 처리하지만 메모리를 회수하지는 않습니다. 힙이 소진되면 JVM이 종료됩니다. 엡실론은 수명이 짧은 서비스와 가비지를 사용하지 않는 것으로 알려진 애플리케이션에 유용합니다.

                      Docker 컨테이너의 향상된 기능 

                      Java 10 이전에 컨테이너에 설정된 메모리 및 CPU 제약 조건은 JVM에서 인식되지 않았습니다. 예를 들어 Java 8에서 JVM은 최대 힙 크기의 기본값을 기본 호스트의 실제 메모리의 ¼로 설정합니다. Java 10부터 JVM은 컨테이너 제어 그룹(cgroup)에 의해 설정된 제약 조건을 사용하여 메모리 및 CPU 제한을 설정합니다(아래 참고 사항 참조). 예를 들어 기본 최대 힙 크기는 컨테이너의 메모리 제한의 ¼입니다(예: -m2G의 경우 500MB).

                      다중 릴리스 jar 파일 

                      Java 11에서 클래스 파일의 여러 Java 릴리스별 버전을 포함하는 jar 파일을 만들 수 있습니다.

                      6. 성능 향상

                      JVM 성능향상) 

                      • JEP 197: Segmented Code Cache[14] - 코드 캐시를 고유 세그먼트로 나눕니다. 이러한 구분은 JVM 메모리 공간을 보다 효율적으로 제어하고, 컴파일된 메서드의 검색 시간을 단축하고, 코드 캐시의 조각화를 크게 줄이고, 성능을 향상시킵니다.

                      • JEP 254: Compact Strings[15] - 문자 인코딩에 따라 문자열의 내부 표현을 문자당 2바이트에서 문자당 1~2바이트로 변경합니다. 대부분의 문자열은 ISO-8859-1/라틴어-1 문자를 포함하므로 이 변경 내용으로 인해 문자열을 저장하는 데 필요한 공간이 효율적으로 변경됩니다.

                      • JEP 310: Application Class-Data Sharing[16] - 클래스-데이터 공유는 보관된 클래스가 런타임 시 메모리에 매핑될 수 있게 하여 시작 시간을 줄여줍니다. 애플리케이션 클래스-데이터 공유는 애플리케이션 클래스를 CDS 보관함에 배치할 수 있도록 하여 클래스-데이터 공유를 확장합니다. 여러 JVM이 동일한 보관 파일을 공유하는 경우 메모리가 저장되고 전체 시스템 응답 시간이 단축됩니다.

                      • JEP 312: Thread-Local Handshakes[17] - 글로벌 VM 세이프포인트를 수행하지 않고 스레드에 대한 콜백을 실행하여 VM이 글로벌 세이프포인트의 수를 줄여 대기 시간을 단축할 수 있게 해줍니다.

                      • Lazy Allocation of Compiler Threads[18] - VM은 단계별 컴파일 모드에서 다량의 컴파일러 스레드를 시작합니다. 이 모드는 CPU가 여러 개 있는 시스템에서 기본값입니다. 이러한 스레드는 사용 가능한 메모리 또는 컴파일 요청 수에 관계없이 생성됩니다. 스레드는 유휴 상태일 때(거의 모든 시간) 메모리를 사용하므로 리소스를 비효율적으로 사용합니다. 이 문제를 해결하기 위해 시작 시 각 유형의 컴파일러 스레드를 하나씩만 시작하도록 구현이 변경되었습니다. 추가 스레드를 시작하고 사용하지 않는 스레드를 종료하는 것은 동적으로 처리됩니다.

                      핵심 라이브러리 성능 향상) 

                      • JEP 193: Variable Handles[19] - 표준을 정의한다는 것은 개체 필드 및 배열 요소, 메모리 정렬의 세부적인 제어를 위한 표준 펜스 작업 세트, 참조된 개체의 강력한 연결성을 유지하기 위한 표준 연결성 펜스 작업에 대한 다양한 java.util.concurrent.atomic 및 sun.misc.Unsafe 작업의 동급 요소를 호출하는 것을 의미합니다.

                      • JEP 269: Convenience Factory Methods for Collections[20] - 소량의 요소를 사용하여 컬렉션 및 맵 인스턴스를 편리하게 만들 수 있게 해주는 라이브러리 API를 정의합니다. 컬렉션 인터페이스에서 간결하고 수정할 수 없는 컬렉션 인스턴스를 만드는 고정 팩터리 메서드입니다. 이러한 인스턴스는 본질적으로 더 효율적입니다. API는 조밀하게 표시되고 래퍼 클래스가 없는 컬렉션을 만듭니다.

                      • JEP 285: Spin-Wait Hints[21] - Java에서 스핀 루프에 있음을 런타임 시스템에 암시할 수 있게 해주는 API를 제공합니다. 특정 하드웨어 플랫폼은 스레드가 바쁜 대기(busy-wait) 상태라고 소프트웨어가 알려주면 이점을 얻을 수 있습니다.

                      • JEP 321: HTTP Client(Standard) [22]- HTTP/2 및 WebSocket을 구현하고 레거시 HttpURLConnection API를 대체할 수 있는 새로운 HTTP 클라이언트 API를 제공합니다.




                        P.S

                        다시 자바를 하면서 느낀게  "자바는 꾸준히 발전하고 있는 재밌고 가치있는 중심 언어이다"  입니다.

                        2020-09-24 19:00:45 에 아래 내용에서 변경 됨 #12


                        Java 11로 전환해야 하는 이유  /  OpenJDK 11 version  정리

                        (추가: Spring5 Webflux로 시작/전환하는 조직들도 많아 졌으면...정말 좋은데..)  

                        API에 대한 눈에 띄는 추가 및 수정 사항이 있으며,
                        시작, 성능 및 메모리 사용을 개선하는 향상된 기능이 있습니다.그리고 LTS 버전입니다.

                        1. 람다 파라미터를 위한 지역변수 표현 

                        java 10버전에 편리한 var 구문이 생겨난 상황에서, 11버전에서는 람다 파라미터에서  좀 더 명시적으로 var 를 이용 할 수 있게 되었습니다. 따라서 아래와 같이 어노테이션을 명시할 수 있게 되었습니다.

                        list.stream()
                            .map((@NotNull var s) -> s.toLowerCase())
                            .collect(Collectors.toList());

                        2. HTTP Client (Standard) 

                        Non-Blocking request and response 지원 (with CompletableFuture)
                        Backpressure 지원(java.util.concurrent.Flow 패키지를 통해 Rx Flow를 구현체에 적용)
                        Factory method 형태로 지원
                        HTTP/2 지원
                        public class HttpClientAsynchronous { private static final HttpClient httpClient = HttpClient.newBuilder()
                        .version(HttpClient.Version.HTTP_2)
                        .connectTimeout(Duration.ofSeconds(10))
                        .build(); public static void main(String[] args) throws Exception { HttpRequest request = HttpRequest.newBuilder()
                        .GET()
                        .uri(URI.create("https://httpbin.org/get"))
                        .setHeader("User-Agent", "Java 11 HttpClient Bot")
                        .build(); CompletableFuture<HttpResponse<String>> response =
                        httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString()); String result = response.thenApply(HttpResponse::body).get(5, TimeUnit.SECONDS); System.out.println(result); } }
                        public class HttpClientCustomExecutor { // custom executor
                        private static final ExecutorService executorService = Executors.newFixedThreadPool(5); private static final HttpClient httpClient = HttpClient.newBuilder()
                        .executor(executorService)
                        .version(HttpClient.Version.HTTP_2)
                        .connectTimeout(Duration.ofSeconds(10))
                        .build(); public static void main(String[] args) throws Exception { List<URI> targets = Arrays.asList(
                        new URI("https://httpbin.org/get?name=mkyong1"),
                        new URI("https://httpbin.org/get?name=mkyong2"),
                        new URI("https://httpbin.org/get?name=mkyong3"));         List<CompletableFuture<String>> result = targets.stream()
                        .map(url -> httpClient.sendAsync(
                        HttpRequest.newBuilder(url)
                        .GET()
                        .setHeader("User-Agent", "Java 11 HttpClient Bot")
                        .build(),
                        HttpResponse.BodyHandlers.ofString())
                        .thenApply(response -> response.body()))
                        .collect(Collectors.toList()); for (CompletableFuture<String> future : result) {
                        System.out.println(future.get());
                        } } }
                        참고로 Spring5에서는 Rest Client에 RestTemplate 대신해 WebClient를 사용하여 비동기구현을 할 수 있게 되었습니다. 기존 멀티쓰레드 방식을 버리고 Reactor(WebFlux) 와 함께 스프링 기반 웹서비스를 구현할 경우 그에 따른  성능과 효율 향상은 어마어마 합니다.

                        3. 모듈 

                        모듈을 통해 애플리케이션에 필요한 구성 요소만 포함하는 런타임 구성을 사용자 지정할 수 있습니다. 이 사용자 지정은 메모리 공간을 더 적게 사용하며 애플리케이션이 jlink를 사용하여 배포용 사용자 지정 런타임에 정적으로 연결될 수 있게 해줍니다. 메모리 공간을 적게 사용하면 특히 마이크로서비스 아키텍처에서 유용할 수 있습니다.

                        내부적으로 JVM은 모듈을 활용하여 클래스 로딩을 보다 효율적으로 만들 수 있습니다. 그 결과 런타임이 더 작아지고, 더 가벼워져서 더 빠르게 시작할 수 있습니다. 모듈은 클래스에 필요한 구성 요소를 인코딩하기 때문에 JVM에서 애플리케이션 성능을 개선하기 위해 사용하는 최적화 기법의 효과가 더 좋아질 수 있습니다.

                        프로그래머의 경우 모듈은 모듈이 내보내는 패키지와 필요한 구성 요소를 명시적으로 선언하고 반사적 액세스를 제한하여 강력한 캡슐화를 적용하는 데 도움이 됩니다. 이 캡슐화 수준을 사용하면 애플리케이션을 더 안전하고 쉽게 유지 관리할 수 있습니다.


                        4. 프로파일링 및 진단

                        Java Flight Recorder 

                        JFR(Java Flight Recorder)은 실행 중인 Java 애플리케이션에서 진단 및 프로파일링 데이터를 수집합니다.  JFR 및 JMC는 Java 8에서 상용 기능이지만 Java 11에서는 둘 다 오픈 소스입니다.

                        Java Mission Control 

                        JMC(Java Mission Control)는 JFR(Java Flight Recorder)에서 수집한 데이터를 그래픽으로 표시하고 Java에서는 오픈 소스로 제공됩니다. JFR 및 JMC를 사용하면 메모리 누수, GC 오버헤드, 핫 메서드, 스레드 병목 상태 및 I/O 블로킹과 같은 런타임 문제를 진단할 수 있습니다.

                        통합 로깅 

                        Java 11에는 JVM의 모든 구성 요소에 대한 일반적인 로깅 시스템이 있습니다.이 세분화된 로깅은 JVM 충돌에 대한 근본 원인 분석을 수행하고 프로덕션 환경에서 성능 문제를 진단하는 데 유용합니다.

                        오버헤드가 낮은 힙 프로파일링 

                        Java 힙 할당을 샘플링하는 데 사용할 수 있는 새 API가 JVMTI(Java Virtual Machine Tool Interface)에 추가되었습니다.JFR 구현에서는 할당이 누락될 수도 있습니다. 반면 Java 11의 힙 샘플링은 라이브 개체와 데드 개체 모두에 대한 정보를 제공할 수 있습니다. APM(애플리케이션 성능 모니터링) 공급업체가 이 새로운 기능을 활용하기 시작 했습니다.

                        StackWalker 

                        현재 스레드의 스택에 대한 스냅샷 가져오기는 로깅할 때 주로 사용됩니다.

                        5. 가비지 수집 

                        Java 11에서 사용할 수 있는 가비지 수집기는 직렬, 병렬, 가비지 우선 및 엡실론입니다. Java 11의 기본 가비지 수집기는 G1GC(가비지 우선 가비지 수집기)입니다.

                        ZGC일시 중지 시간을 10ms 미만으로 유지하려고 하는 대기 시간이 짧은 동시 수집기입니다. ZGC는 Java 11에서 실험적 기능으로 사용할 수 있습니다.CMS(Concurrent Mark and Sweep) 수집기는 사용할 수 있지만 Java 9 이후에는 사용되지 않습니다.

                        엡실론 

                        엡실론 가비지 수집기는 할당을 처리하지만 메모리를 회수하지는 않습니다. 힙이 소진되면 JVM이 종료됩니다. 엡실론은 수명이 짧은 서비스와 가비지를 사용하지 않는 것으로 알려진 애플리케이션에 유용합니다.

                        Docker 컨테이너의 향상된 기능 

                        Java 10 이전에 컨테이너에 설정된 메모리 및 CPU 제약 조건은 JVM에서 인식되지 않았습니다. 예를 들어 Java 8에서 JVM은 최대 힙 크기의 기본값을 기본 호스트의 실제 메모리의 ¼로 설정합니다. Java 10부터 JVM은 컨테이너 제어 그룹(cgroup)에 의해 설정된 제약 조건을 사용하여 메모리 및 CPU 제한을 설정합니다(아래 참고 사항 참조). 예를 들어 기본 최대 힙 크기는 컨테이너의 메모리 제한의 ¼입니다(예: -m2G의 경우 500MB).

                        다중 릴리스 jar 파일 

                        Java 11에서 클래스 파일의 여러 Java 릴리스별 버전을 포함하는 jar 파일을 만들 수 있습니다.

                        6. 성능 향상

                        JVM 성능향상) 

                        • JEP 197: Segmented Code Cache[14] - 코드 캐시를 고유 세그먼트로 나눕니다. 이러한 구분은 JVM 메모리 공간을 보다 효율적으로 제어하고, 컴파일된 메서드의 검색 시간을 단축하고, 코드 캐시의 조각화를 크게 줄이고, 성능을 향상시킵니다.

                        • JEP 254: Compact Strings[15] - 문자 인코딩에 따라 문자열의 내부 표현을 문자당 2바이트에서 문자당 1~2바이트로 변경합니다. 대부분의 문자열은 ISO-8859-1/라틴어-1 문자를 포함하므로 이 변경 내용으로 인해 문자열을 저장하는 데 필요한 공간이 효율적으로 변경됩니다.

                        • JEP 310: Application Class-Data Sharing[16] - 클래스-데이터 공유는 보관된 클래스가 런타임 시 메모리에 매핑될 수 있게 하여 시작 시간을 줄여줍니다. 애플리케이션 클래스-데이터 공유는 애플리케이션 클래스를 CDS 보관함에 배치할 수 있도록 하여 클래스-데이터 공유를 확장합니다. 여러 JVM이 동일한 보관 파일을 공유하는 경우 메모리가 저장되고 전체 시스템 응답 시간이 단축됩니다.

                        • JEP 312: Thread-Local Handshakes[17] - 글로벌 VM 세이프포인트를 수행하지 않고 스레드에 대한 콜백을 실행하여 VM이 글로벌 세이프포인트의 수를 줄여 대기 시간을 단축할 수 있게 해줍니다.

                        • Lazy Allocation of Compiler Threads[18] - VM은 단계별 컴파일 모드에서 다량의 컴파일러 스레드를 시작합니다. 이 모드는 CPU가 여러 개 있는 시스템에서 기본값입니다. 이러한 스레드는 사용 가능한 메모리 또는 컴파일 요청 수에 관계없이 생성됩니다. 스레드는 유휴 상태일 때(거의 모든 시간) 메모리를 사용하므로 리소스를 비효율적으로 사용합니다. 이 문제를 해결하기 위해 시작 시 각 유형의 컴파일러 스레드를 하나씩만 시작하도록 구현이 변경되었습니다. 추가 스레드를 시작하고 사용하지 않는 스레드를 종료하는 것은 동적으로 처리됩니다.

                        핵심 라이브러리 성능 향상) 

                        • JEP 193: Variable Handles[19] - 표준을 정의한다는 것은 개체 필드 및 배열 요소, 메모리 정렬의 세부적인 제어를 위한 표준 펜스 작업 세트, 참조된 개체의 강력한 연결성을 유지하기 위한 표준 연결성 펜스 작업에 대한 다양한 java.util.concurrent.atomic 및 sun.misc.Unsafe 작업의 동급 요소를 호출하는 것을 의미합니다.

                        • JEP 269: Convenience Factory Methods for Collections[20] - 소량의 요소를 사용하여 컬렉션 및 맵 인스턴스를 편리하게 만들 수 있게 해주는 라이브러리 API를 정의합니다. 컬렉션 인터페이스에서 간결하고 수정할 수 없는 컬렉션 인스턴스를 만드는 고정 팩터리 메서드입니다. 이러한 인스턴스는 본질적으로 더 효율적입니다. API는 조밀하게 표시되고 래퍼 클래스가 없는 컬렉션을 만듭니다.

                        • JEP 285: Spin-Wait Hints[21] - Java에서 스핀 루프에 있음을 런타임 시스템에 암시할 수 있게 해주는 API를 제공합니다. 특정 하드웨어 플랫폼은 스레드가 바쁜 대기(busy-wait) 상태라고 소프트웨어가 알려주면 이점을 얻을 수 있습니다.

                        • JEP 321: HTTP Client(Standard) [22]- HTTP/2 및 WebSocket을 구현하고 레거시 HttpURLConnection API를 대체할 수 있는 새로운 HTTP 클라이언트 API를 제공합니다.




                          P.S

                          다시 자바를 하면서 느낀게  "자바는 꾸준히 발전하고 있는 재밌고 가치있는 중심 언어이다"  입니다.

                          2020-09-24 18:58:42 에 아래 내용에서 변경 됨 #11


                          Java 11로 전환해야 하는 이유  /  OpenJDK 11 version  정리

                          (추가: Spring5 Webflux로 시작/전환하는 조직들도 많아 졌으면...정말 좋은데..)  

                          API에 대한 눈에 띄는 추가 및 수정 사항이 있으며,
                          시작, 성능 및 메모리 사용을 개선하는 향상된 기능이 있습니다.그리고 LTS 버전입니다.

                          1. 람다 파라미터를 위한 지역변수 표현 

                          java 10버전에 편리한 var 구문이 생겨난 상황에서, 11버전에서는 람다 파라미터에서  좀 더 명시적으로 var 를 이용 할 수 있게 되었습니다. 따라서 아래와 같이 어노테이션을 명시할 수 있게 되었습니다.

                          list.stream()
                              .map((@NotNull var s) -> s.toLowerCase())
                              .collect(Collectors.toList());

                          2. HTTP Client (Standard) 

                          Non-Blocking request and response 지원 (with CompletableFuture)
                          Backpressure 지원(java.util.concurrent.Flow 패키지를 통해 Rx Flow를 구현체에 적용)
                          Factory method 형태로 지원
                          HTTP/2 지원
                          CompletableFuture<HttpResponse<String>> response = HttpClient.newBuilder()
                            .build()
                            .sendAsync(request, HttpResponse.BodyHandler.asString());
                          List<URI> targets = Arrays.asList(
                            new URI("https://postman-echo.com/get?foo1=bar1"),
                            new URI("https://postman-echo.com/get?foo2=bar2"));
                          
                          HttpClient client = HttpClient.newHttpClient();
                          
                          List<CompletableFuture<String>> futures = targets.stream()
                            .map(target -> client
                              .sendAsync(
                                HttpRequest.newBuilder(target).GET().build(),
                                HttpResponse.BodyHandler.asString())
                              .thenApply(response -> response.body()))
                            .collect(Collectors.toList());
                          참고로 Spring5에서는 Rest Client에 RestTemplate 대신해 WebClient를 사용하여 비동기구현을 할 수 있게 되었습니다. 기존 멀티쓰레드 방식을 버리고 Reactor(WebFlux) 와 함께 스프링 기반 웹서비스를 구현할 경우 그에 따른  성능과 효율 향상은 어마어마 합니다.

                          3. 모듈 

                          모듈을 통해 애플리케이션에 필요한 구성 요소만 포함하는 런타임 구성을 사용자 지정할 수 있습니다. 이 사용자 지정은 메모리 공간을 더 적게 사용하며 애플리케이션이 jlink를 사용하여 배포용 사용자 지정 런타임에 정적으로 연결될 수 있게 해줍니다. 메모리 공간을 적게 사용하면 특히 마이크로서비스 아키텍처에서 유용할 수 있습니다.

                          내부적으로 JVM은 모듈을 활용하여 클래스 로딩을 보다 효율적으로 만들 수 있습니다. 그 결과 런타임이 더 작아지고, 더 가벼워져서 더 빠르게 시작할 수 있습니다. 모듈은 클래스에 필요한 구성 요소를 인코딩하기 때문에 JVM에서 애플리케이션 성능을 개선하기 위해 사용하는 최적화 기법의 효과가 더 좋아질 수 있습니다.

                          프로그래머의 경우 모듈은 모듈이 내보내는 패키지와 필요한 구성 요소를 명시적으로 선언하고 반사적 액세스를 제한하여 강력한 캡슐화를 적용하는 데 도움이 됩니다. 이 캡슐화 수준을 사용하면 애플리케이션을 더 안전하고 쉽게 유지 관리할 수 있습니다.


                          4. 프로파일링 및 진단

                          Java Flight Recorder 

                          JFR(Java Flight Recorder)은 실행 중인 Java 애플리케이션에서 진단 및 프로파일링 데이터를 수집합니다.  JFR 및 JMC는 Java 8에서 상용 기능이지만 Java 11에서는 둘 다 오픈 소스입니다.

                          Java Mission Control 

                          JMC(Java Mission Control)는 JFR(Java Flight Recorder)에서 수집한 데이터를 그래픽으로 표시하고 Java에서는 오픈 소스로 제공됩니다. JFR 및 JMC를 사용하면 메모리 누수, GC 오버헤드, 핫 메서드, 스레드 병목 상태 및 I/O 블로킹과 같은 런타임 문제를 진단할 수 있습니다.

                          통합 로깅 

                          Java 11에는 JVM의 모든 구성 요소에 대한 일반적인 로깅 시스템이 있습니다.이 세분화된 로깅은 JVM 충돌에 대한 근본 원인 분석을 수행하고 프로덕션 환경에서 성능 문제를 진단하는 데 유용합니다.

                          오버헤드가 낮은 힙 프로파일링 

                          Java 힙 할당을 샘플링하는 데 사용할 수 있는 새 API가 JVMTI(Java Virtual Machine Tool Interface)에 추가되었습니다.JFR 구현에서는 할당이 누락될 수도 있습니다. 반면 Java 11의 힙 샘플링은 라이브 개체와 데드 개체 모두에 대한 정보를 제공할 수 있습니다. APM(애플리케이션 성능 모니터링) 공급업체가 이 새로운 기능을 활용하기 시작 했습니다.

                          StackWalker 

                          현재 스레드의 스택에 대한 스냅샷 가져오기는 로깅할 때 주로 사용됩니다.

                          5. 가비지 수집 

                          Java 11에서 사용할 수 있는 가비지 수집기는 직렬, 병렬, 가비지 우선 및 엡실론입니다. Java 11의 기본 가비지 수집기는 G1GC(가비지 우선 가비지 수집기)입니다.

                          ZGC일시 중지 시간을 10ms 미만으로 유지하려고 하는 대기 시간이 짧은 동시 수집기입니다. ZGC는 Java 11에서 실험적 기능으로 사용할 수 있습니다.CMS(Concurrent Mark and Sweep) 수집기는 사용할 수 있지만 Java 9 이후에는 사용되지 않습니다.

                          엡실론 

                          엡실론 가비지 수집기는 할당을 처리하지만 메모리를 회수하지는 않습니다. 힙이 소진되면 JVM이 종료됩니다. 엡실론은 수명이 짧은 서비스와 가비지를 사용하지 않는 것으로 알려진 애플리케이션에 유용합니다.

                          Docker 컨테이너의 향상된 기능 

                          Java 10 이전에 컨테이너에 설정된 메모리 및 CPU 제약 조건은 JVM에서 인식되지 않았습니다. 예를 들어 Java 8에서 JVM은 최대 힙 크기의 기본값을 기본 호스트의 실제 메모리의 ¼로 설정합니다. Java 10부터 JVM은 컨테이너 제어 그룹(cgroup)에 의해 설정된 제약 조건을 사용하여 메모리 및 CPU 제한을 설정합니다(아래 참고 사항 참조). 예를 들어 기본 최대 힙 크기는 컨테이너의 메모리 제한의 ¼입니다(예: -m2G의 경우 500MB).

                          다중 릴리스 jar 파일 

                          Java 11에서 클래스 파일의 여러 Java 릴리스별 버전을 포함하는 jar 파일을 만들 수 있습니다.

                          6. 성능 향상

                          JVM 성능향상) 

                          • JEP 197: Segmented Code Cache[14] - 코드 캐시를 고유 세그먼트로 나눕니다. 이러한 구분은 JVM 메모리 공간을 보다 효율적으로 제어하고, 컴파일된 메서드의 검색 시간을 단축하고, 코드 캐시의 조각화를 크게 줄이고, 성능을 향상시킵니다.

                          • JEP 254: Compact Strings[15] - 문자 인코딩에 따라 문자열의 내부 표현을 문자당 2바이트에서 문자당 1~2바이트로 변경합니다. 대부분의 문자열은 ISO-8859-1/라틴어-1 문자를 포함하므로 이 변경 내용으로 인해 문자열을 저장하는 데 필요한 공간이 효율적으로 변경됩니다.

                          • JEP 310: Application Class-Data Sharing[16] - 클래스-데이터 공유는 보관된 클래스가 런타임 시 메모리에 매핑될 수 있게 하여 시작 시간을 줄여줍니다. 애플리케이션 클래스-데이터 공유는 애플리케이션 클래스를 CDS 보관함에 배치할 수 있도록 하여 클래스-데이터 공유를 확장합니다. 여러 JVM이 동일한 보관 파일을 공유하는 경우 메모리가 저장되고 전체 시스템 응답 시간이 단축됩니다.

                          • JEP 312: Thread-Local Handshakes[17] - 글로벌 VM 세이프포인트를 수행하지 않고 스레드에 대한 콜백을 실행하여 VM이 글로벌 세이프포인트의 수를 줄여 대기 시간을 단축할 수 있게 해줍니다.

                          • Lazy Allocation of Compiler Threads[18] - VM은 단계별 컴파일 모드에서 다량의 컴파일러 스레드를 시작합니다. 이 모드는 CPU가 여러 개 있는 시스템에서 기본값입니다. 이러한 스레드는 사용 가능한 메모리 또는 컴파일 요청 수에 관계없이 생성됩니다. 스레드는 유휴 상태일 때(거의 모든 시간) 메모리를 사용하므로 리소스를 비효율적으로 사용합니다. 이 문제를 해결하기 위해 시작 시 각 유형의 컴파일러 스레드를 하나씩만 시작하도록 구현이 변경되었습니다. 추가 스레드를 시작하고 사용하지 않는 스레드를 종료하는 것은 동적으로 처리됩니다.

                          핵심 라이브러리 성능 향상) 

                          • JEP 193: Variable Handles[19] - 표준을 정의한다는 것은 개체 필드 및 배열 요소, 메모리 정렬의 세부적인 제어를 위한 표준 펜스 작업 세트, 참조된 개체의 강력한 연결성을 유지하기 위한 표준 연결성 펜스 작업에 대한 다양한 java.util.concurrent.atomic 및 sun.misc.Unsafe 작업의 동급 요소를 호출하는 것을 의미합니다.

                          • JEP 269: Convenience Factory Methods for Collections[20] - 소량의 요소를 사용하여 컬렉션 및 맵 인스턴스를 편리하게 만들 수 있게 해주는 라이브러리 API를 정의합니다. 컬렉션 인터페이스에서 간결하고 수정할 수 없는 컬렉션 인스턴스를 만드는 고정 팩터리 메서드입니다. 이러한 인스턴스는 본질적으로 더 효율적입니다. API는 조밀하게 표시되고 래퍼 클래스가 없는 컬렉션을 만듭니다.

                          • JEP 285: Spin-Wait Hints[21] - Java에서 스핀 루프에 있음을 런타임 시스템에 암시할 수 있게 해주는 API를 제공합니다. 특정 하드웨어 플랫폼은 스레드가 바쁜 대기(busy-wait) 상태라고 소프트웨어가 알려주면 이점을 얻을 수 있습니다.

                          • JEP 321: HTTP Client(Standard) [22]- HTTP/2 및 WebSocket을 구현하고 레거시 HttpURLConnection API를 대체할 수 있는 새로운 HTTP 클라이언트 API를 제공합니다.




                            P.S

                            다시 자바를 하면서 느낀게  "자바는 꾸준히 발전하고 있는 재밌고 가치있는 중심 언어이다"  입니다.

                            2020-09-24 18:53:33 에 아래 내용에서 변경 됨 #10


                            Java 11로 전환해야 하는 이유  /  OpenJDK 11 version  정리

                            (추가: Spring5 Webflux로 시작/전환하는 조직들도 많아 졌으면...정말 좋은데..)  

                            API에 대한 눈에 띄는 추가 및 수정 사항이 있으며,
                            시작, 성능 및 메모리 사용을 개선하는 향상된 기능이 있습니다.그리고 LTS 버전입니다.

                            1. 람다 파라미터를 위한 지역변수 표현 

                            java 10버전에 편리한 var 구문이 생겨난 상황에서, 11버전에서는 람다 파라미터에서  좀 더 명시적으로 var 를 이용 할 수 있게 되었습니다. 따라서 아래와 같이 어노테이션을 명시할 수 있게 되었습니다.

                            list.stream()
                                .map((@NotNull var s) -> s.toLowerCase())
                                .collect(Collectors.toList());

                            2. HTTP Client (Standard) 

                            Non-Blocking request and response 지원 (with CompletableFuture)
                            Backpressure 지원(java.util.concurrent.Flow 패키지를 통해 Rx Flow를 구현체에 적용)
                            Factory method 형태로 지원
                            HTTP/2 지원
                            HttpClient 예제) 
                            public void get(String uri) throws Exception {
                                HttpClient client = HttpClient.newHttpClient();
                                HttpRequest request = HttpRequest.newBuilder()
                                      .uri(URI.create(uri))
                                      .build();
                            
                                HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
                                System.out.println(response.body());
                            }
                            참고로 Spring5에서는 Rest Client에 RestTemplate 대신해 WebClient를 사용하여 비동기구현을 할 수 있게 되었습니다. 기존 멀티쓰레드 방식을 버리고 Reactor(WebFlux) 와 함께 스프링 기반 웹서비스를 구현할 경우 그에 따른  성능과 효율 향상은 어마어마 합니다.

                            3. 모듈 

                            모듈을 통해 애플리케이션에 필요한 구성 요소만 포함하는 런타임 구성을 사용자 지정할 수 있습니다. 이 사용자 지정은 메모리 공간을 더 적게 사용하며 애플리케이션이 jlink를 사용하여 배포용 사용자 지정 런타임에 정적으로 연결될 수 있게 해줍니다. 메모리 공간을 적게 사용하면 특히 마이크로서비스 아키텍처에서 유용할 수 있습니다.

                            내부적으로 JVM은 모듈을 활용하여 클래스 로딩을 보다 효율적으로 만들 수 있습니다. 그 결과 런타임이 더 작아지고, 더 가벼워져서 더 빠르게 시작할 수 있습니다. 모듈은 클래스에 필요한 구성 요소를 인코딩하기 때문에 JVM에서 애플리케이션 성능을 개선하기 위해 사용하는 최적화 기법의 효과가 더 좋아질 수 있습니다.

                            프로그래머의 경우 모듈은 모듈이 내보내는 패키지와 필요한 구성 요소를 명시적으로 선언하고 반사적 액세스를 제한하여 강력한 캡슐화를 적용하는 데 도움이 됩니다. 이 캡슐화 수준을 사용하면 애플리케이션을 더 안전하고 쉽게 유지 관리할 수 있습니다.


                            4. 프로파일링 및 진단

                            Java Flight Recorder 

                            JFR(Java Flight Recorder)은 실행 중인 Java 애플리케이션에서 진단 및 프로파일링 데이터를 수집합니다.  JFR 및 JMC는 Java 8에서 상용 기능이지만 Java 11에서는 둘 다 오픈 소스입니다.

                            Java Mission Control 

                            JMC(Java Mission Control)는 JFR(Java Flight Recorder)에서 수집한 데이터를 그래픽으로 표시하고 Java에서는 오픈 소스로 제공됩니다. JFR 및 JMC를 사용하면 메모리 누수, GC 오버헤드, 핫 메서드, 스레드 병목 상태 및 I/O 블로킹과 같은 런타임 문제를 진단할 수 있습니다.

                            통합 로깅 

                            Java 11에는 JVM의 모든 구성 요소에 대한 일반적인 로깅 시스템이 있습니다.이 세분화된 로깅은 JVM 충돌에 대한 근본 원인 분석을 수행하고 프로덕션 환경에서 성능 문제를 진단하는 데 유용합니다.

                            오버헤드가 낮은 힙 프로파일링 

                            Java 힙 할당을 샘플링하는 데 사용할 수 있는 새 API가 JVMTI(Java Virtual Machine Tool Interface)에 추가되었습니다.JFR 구현에서는 할당이 누락될 수도 있습니다. 반면 Java 11의 힙 샘플링은 라이브 개체와 데드 개체 모두에 대한 정보를 제공할 수 있습니다. APM(애플리케이션 성능 모니터링) 공급업체가 이 새로운 기능을 활용하기 시작 했습니다.

                            StackWalker 

                            현재 스레드의 스택에 대한 스냅샷 가져오기는 로깅할 때 주로 사용됩니다.

                            5. 가비지 수집 

                            Java 11에서 사용할 수 있는 가비지 수집기는 직렬, 병렬, 가비지 우선 및 엡실론입니다. Java 11의 기본 가비지 수집기는 G1GC(가비지 우선 가비지 수집기)입니다.

                            ZGC일시 중지 시간을 10ms 미만으로 유지하려고 하는 대기 시간이 짧은 동시 수집기입니다. ZGC는 Java 11에서 실험적 기능으로 사용할 수 있습니다.CMS(Concurrent Mark and Sweep) 수집기는 사용할 수 있지만 Java 9 이후에는 사용되지 않습니다.

                            엡실론 

                            엡실론 가비지 수집기는 할당을 처리하지만 메모리를 회수하지는 않습니다. 힙이 소진되면 JVM이 종료됩니다. 엡실론은 수명이 짧은 서비스와 가비지를 사용하지 않는 것으로 알려진 애플리케이션에 유용합니다.

                            Docker 컨테이너의 향상된 기능 

                            Java 10 이전에 컨테이너에 설정된 메모리 및 CPU 제약 조건은 JVM에서 인식되지 않았습니다. 예를 들어 Java 8에서 JVM은 최대 힙 크기의 기본값을 기본 호스트의 실제 메모리의 ¼로 설정합니다. Java 10부터 JVM은 컨테이너 제어 그룹(cgroup)에 의해 설정된 제약 조건을 사용하여 메모리 및 CPU 제한을 설정합니다(아래 참고 사항 참조). 예를 들어 기본 최대 힙 크기는 컨테이너의 메모리 제한의 ¼입니다(예: -m2G의 경우 500MB).

                            다중 릴리스 jar 파일 

                            Java 11에서 클래스 파일의 여러 Java 릴리스별 버전을 포함하는 jar 파일을 만들 수 있습니다.

                            6. 성능 향상

                            JVM 성능향상) 

                            • JEP 197: Segmented Code Cache[14] - 코드 캐시를 고유 세그먼트로 나눕니다. 이러한 구분은 JVM 메모리 공간을 보다 효율적으로 제어하고, 컴파일된 메서드의 검색 시간을 단축하고, 코드 캐시의 조각화를 크게 줄이고, 성능을 향상시킵니다.

                            • JEP 254: Compact Strings[15] - 문자 인코딩에 따라 문자열의 내부 표현을 문자당 2바이트에서 문자당 1~2바이트로 변경합니다. 대부분의 문자열은 ISO-8859-1/라틴어-1 문자를 포함하므로 이 변경 내용으로 인해 문자열을 저장하는 데 필요한 공간이 효율적으로 변경됩니다.

                            • JEP 310: Application Class-Data Sharing[16] - 클래스-데이터 공유는 보관된 클래스가 런타임 시 메모리에 매핑될 수 있게 하여 시작 시간을 줄여줍니다. 애플리케이션 클래스-데이터 공유는 애플리케이션 클래스를 CDS 보관함에 배치할 수 있도록 하여 클래스-데이터 공유를 확장합니다. 여러 JVM이 동일한 보관 파일을 공유하는 경우 메모리가 저장되고 전체 시스템 응답 시간이 단축됩니다.

                            • JEP 312: Thread-Local Handshakes[17] - 글로벌 VM 세이프포인트를 수행하지 않고 스레드에 대한 콜백을 실행하여 VM이 글로벌 세이프포인트의 수를 줄여 대기 시간을 단축할 수 있게 해줍니다.

                            • Lazy Allocation of Compiler Threads[18] - VM은 단계별 컴파일 모드에서 다량의 컴파일러 스레드를 시작합니다. 이 모드는 CPU가 여러 개 있는 시스템에서 기본값입니다. 이러한 스레드는 사용 가능한 메모리 또는 컴파일 요청 수에 관계없이 생성됩니다. 스레드는 유휴 상태일 때(거의 모든 시간) 메모리를 사용하므로 리소스를 비효율적으로 사용합니다. 이 문제를 해결하기 위해 시작 시 각 유형의 컴파일러 스레드를 하나씩만 시작하도록 구현이 변경되었습니다. 추가 스레드를 시작하고 사용하지 않는 스레드를 종료하는 것은 동적으로 처리됩니다.

                            핵심 라이브러리 성능 향상) 

                            • JEP 193: Variable Handles[19] - 표준을 정의한다는 것은 개체 필드 및 배열 요소, 메모리 정렬의 세부적인 제어를 위한 표준 펜스 작업 세트, 참조된 개체의 강력한 연결성을 유지하기 위한 표준 연결성 펜스 작업에 대한 다양한 java.util.concurrent.atomic 및 sun.misc.Unsafe 작업의 동급 요소를 호출하는 것을 의미합니다.

                            • JEP 269: Convenience Factory Methods for Collections[20] - 소량의 요소를 사용하여 컬렉션 및 맵 인스턴스를 편리하게 만들 수 있게 해주는 라이브러리 API를 정의합니다. 컬렉션 인터페이스에서 간결하고 수정할 수 없는 컬렉션 인스턴스를 만드는 고정 팩터리 메서드입니다. 이러한 인스턴스는 본질적으로 더 효율적입니다. API는 조밀하게 표시되고 래퍼 클래스가 없는 컬렉션을 만듭니다.

                            • JEP 285: Spin-Wait Hints[21] - Java에서 스핀 루프에 있음을 런타임 시스템에 암시할 수 있게 해주는 API를 제공합니다. 특정 하드웨어 플랫폼은 스레드가 바쁜 대기(busy-wait) 상태라고 소프트웨어가 알려주면 이점을 얻을 수 있습니다.

                            • JEP 321: HTTP Client(Standard) [22]- HTTP/2 및 WebSocket을 구현하고 레거시 HttpURLConnection API를 대체할 수 있는 새로운 HTTP 클라이언트 API를 제공합니다.




                              P.S

                              다시 자바를 하면서 느낀게  "자바는 꾸준히 발전하고 있는 재밌고 가치있는 중심 언어이다"  입니다.

                              2020-09-24 12:03:15 에 아래 내용에서 변경 됨 #9


                              Java 11로 전환해야 하는 이유  /  OpenJDK 11 version  정리

                              (추가: Spring5 Webflux로 시작/전환하는 조직들도 많아 졌으면...)  

                              API에 대한 눈에 띄는 추가 및 수정 사항이 있으며,
                              시작, 성능 및 메모리 사용을 개선하는 향상된 기능이 있습니다.그리고 LTS 버전입니다.

                              1. 람다 파라미터를 위한 지역변수 표현 

                              java 10버전에 편리한 var 구문이 생겨난 상황에서, 11버전에서는 람다 파라미터에서  좀 더 명시적으로 var 를 이용 할 수 있게 되었습니다. 따라서 아래와 같이 어노테이션을 명시할 수 있게 되었습니다.

                              list.stream()
                                  .map((@NotNull var s) -> s.toLowerCase())
                                  .collect(Collectors.toList());

                              2. HTTP Client (Standard) 

                              Non-Blocking request and response 지원 (with CompletableFuture)
                              Backpressure 지원(java.util.concurrent.Flow 패키지를 통해 Rx Flow를 구현체에 적용)
                              Factory method 형태로 지원
                              HTTP/2 지원
                              HttpClient 예제) 
                              public void get(String uri) throws Exception {
                                  HttpClient client = HttpClient.newHttpClient();
                                  HttpRequest request = HttpRequest.newBuilder()
                                        .uri(URI.create(uri))
                                        .build();
                              
                                  HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
                                  System.out.println(response.body());
                              }
                              참고로 Spring5에서는 Rest Client에 RestTemplate 대신해 WebClient를 사용하여 비동기구현을 할 수 있게 되었습니다. 기존 멀티쓰레드 방식을 버리고 Reactor(WebFlux) 와 함께 스프링 기반 웹서비스를 구현할 경우 그에 따른  성능과 효율 향상은 어마어마 합니다.

                              3. 모듈 

                              모듈을 통해 애플리케이션에 필요한 구성 요소만 포함하는 런타임 구성을 사용자 지정할 수 있습니다. 이 사용자 지정은 메모리 공간을 더 적게 사용하며 애플리케이션이 jlink를 사용하여 배포용 사용자 지정 런타임에 정적으로 연결될 수 있게 해줍니다. 메모리 공간을 적게 사용하면 특히 마이크로서비스 아키텍처에서 유용할 수 있습니다.

                              내부적으로 JVM은 모듈을 활용하여 클래스 로딩을 보다 효율적으로 만들 수 있습니다. 그 결과 런타임이 더 작아지고, 더 가벼워져서 더 빠르게 시작할 수 있습니다. 모듈은 클래스에 필요한 구성 요소를 인코딩하기 때문에 JVM에서 애플리케이션 성능을 개선하기 위해 사용하는 최적화 기법의 효과가 더 좋아질 수 있습니다.

                              프로그래머의 경우 모듈은 모듈이 내보내는 패키지와 필요한 구성 요소를 명시적으로 선언하고 반사적 액세스를 제한하여 강력한 캡슐화를 적용하는 데 도움이 됩니다. 이 캡슐화 수준을 사용하면 애플리케이션을 더 안전하고 쉽게 유지 관리할 수 있습니다.


                              4. 프로파일링 및 진단

                              Java Flight Recorder 

                              JFR(Java Flight Recorder)은 실행 중인 Java 애플리케이션에서 진단 및 프로파일링 데이터를 수집합니다.  JFR 및 JMC는 Java 8에서 상용 기능이지만 Java 11에서는 둘 다 오픈 소스입니다.

                              Java Mission Control 

                              JMC(Java Mission Control)는 JFR(Java Flight Recorder)에서 수집한 데이터를 그래픽으로 표시하고 Java에서는 오픈 소스로 제공됩니다. JFR 및 JMC를 사용하면 메모리 누수, GC 오버헤드, 핫 메서드, 스레드 병목 상태 및 I/O 블로킹과 같은 런타임 문제를 진단할 수 있습니다.

                              통합 로깅 

                              Java 11에는 JVM의 모든 구성 요소에 대한 일반적인 로깅 시스템이 있습니다.이 세분화된 로깅은 JVM 충돌에 대한 근본 원인 분석을 수행하고 프로덕션 환경에서 성능 문제를 진단하는 데 유용합니다.

                              오버헤드가 낮은 힙 프로파일링 

                              Java 힙 할당을 샘플링하는 데 사용할 수 있는 새 API가 JVMTI(Java Virtual Machine Tool Interface)에 추가되었습니다.JFR 구현에서는 할당이 누락될 수도 있습니다. 반면 Java 11의 힙 샘플링은 라이브 개체와 데드 개체 모두에 대한 정보를 제공할 수 있습니다. APM(애플리케이션 성능 모니터링) 공급업체가 이 새로운 기능을 활용하기 시작 했습니다.

                              StackWalker 

                              현재 스레드의 스택에 대한 스냅샷 가져오기는 로깅할 때 주로 사용됩니다.

                              5. 가비지 수집 

                              Java 11에서 사용할 수 있는 가비지 수집기는 직렬, 병렬, 가비지 우선 및 엡실론입니다. Java 11의 기본 가비지 수집기는 G1GC(가비지 우선 가비지 수집기)입니다.

                              ZGC일시 중지 시간을 10ms 미만으로 유지하려고 하는 대기 시간이 짧은 동시 수집기입니다. ZGC는 Java 11에서 실험적 기능으로 사용할 수 있습니다.CMS(Concurrent Mark and Sweep) 수집기는 사용할 수 있지만 Java 9 이후에는 사용되지 않습니다.

                              엡실론 

                              엡실론 가비지 수집기는 할당을 처리하지만 메모리를 회수하지는 않습니다. 힙이 소진되면 JVM이 종료됩니다. 엡실론은 수명이 짧은 서비스와 가비지를 사용하지 않는 것으로 알려진 애플리케이션에 유용합니다.

                              Docker 컨테이너의 향상된 기능 

                              Java 10 이전에 컨테이너에 설정된 메모리 및 CPU 제약 조건은 JVM에서 인식되지 않았습니다. 예를 들어 Java 8에서 JVM은 최대 힙 크기의 기본값을 기본 호스트의 실제 메모리의 ¼로 설정합니다. Java 10부터 JVM은 컨테이너 제어 그룹(cgroup)에 의해 설정된 제약 조건을 사용하여 메모리 및 CPU 제한을 설정합니다(아래 참고 사항 참조). 예를 들어 기본 최대 힙 크기는 컨테이너의 메모리 제한의 ¼입니다(예: -m2G의 경우 500MB).

                              다중 릴리스 jar 파일 

                              Java 11에서 클래스 파일의 여러 Java 릴리스별 버전을 포함하는 jar 파일을 만들 수 있습니다.

                              6. 성능 향상

                              JVM 성능향상) 

                              • JEP 197: Segmented Code Cache[14] - 코드 캐시를 고유 세그먼트로 나눕니다. 이러한 구분은 JVM 메모리 공간을 보다 효율적으로 제어하고, 컴파일된 메서드의 검색 시간을 단축하고, 코드 캐시의 조각화를 크게 줄이고, 성능을 향상시킵니다.

                              • JEP 254: Compact Strings[15] - 문자 인코딩에 따라 문자열의 내부 표현을 문자당 2바이트에서 문자당 1~2바이트로 변경합니다. 대부분의 문자열은 ISO-8859-1/라틴어-1 문자를 포함하므로 이 변경 내용으로 인해 문자열을 저장하는 데 필요한 공간이 효율적으로 변경됩니다.

                              • JEP 310: Application Class-Data Sharing[16] - 클래스-데이터 공유는 보관된 클래스가 런타임 시 메모리에 매핑될 수 있게 하여 시작 시간을 줄여줍니다. 애플리케이션 클래스-데이터 공유는 애플리케이션 클래스를 CDS 보관함에 배치할 수 있도록 하여 클래스-데이터 공유를 확장합니다. 여러 JVM이 동일한 보관 파일을 공유하는 경우 메모리가 저장되고 전체 시스템 응답 시간이 단축됩니다.

                              • JEP 312: Thread-Local Handshakes[17] - 글로벌 VM 세이프포인트를 수행하지 않고 스레드에 대한 콜백을 실행하여 VM이 글로벌 세이프포인트의 수를 줄여 대기 시간을 단축할 수 있게 해줍니다.

                              • Lazy Allocation of Compiler Threads[18] - VM은 단계별 컴파일 모드에서 다량의 컴파일러 스레드를 시작합니다. 이 모드는 CPU가 여러 개 있는 시스템에서 기본값입니다. 이러한 스레드는 사용 가능한 메모리 또는 컴파일 요청 수에 관계없이 생성됩니다. 스레드는 유휴 상태일 때(거의 모든 시간) 메모리를 사용하므로 리소스를 비효율적으로 사용합니다. 이 문제를 해결하기 위해 시작 시 각 유형의 컴파일러 스레드를 하나씩만 시작하도록 구현이 변경되었습니다. 추가 스레드를 시작하고 사용하지 않는 스레드를 종료하는 것은 동적으로 처리됩니다.

                              핵심 라이브러리 성능 향상) 

                              • JEP 193: Variable Handles[19] - 표준을 정의한다는 것은 개체 필드 및 배열 요소, 메모리 정렬의 세부적인 제어를 위한 표준 펜스 작업 세트, 참조된 개체의 강력한 연결성을 유지하기 위한 표준 연결성 펜스 작업에 대한 다양한 java.util.concurrent.atomic 및 sun.misc.Unsafe 작업의 동급 요소를 호출하는 것을 의미합니다.

                              • JEP 269: Convenience Factory Methods for Collections[20] - 소량의 요소를 사용하여 컬렉션 및 맵 인스턴스를 편리하게 만들 수 있게 해주는 라이브러리 API를 정의합니다. 컬렉션 인터페이스에서 간결하고 수정할 수 없는 컬렉션 인스턴스를 만드는 고정 팩터리 메서드입니다. 이러한 인스턴스는 본질적으로 더 효율적입니다. API는 조밀하게 표시되고 래퍼 클래스가 없는 컬렉션을 만듭니다.

                              • JEP 285: Spin-Wait Hints[21] - Java에서 스핀 루프에 있음을 런타임 시스템에 암시할 수 있게 해주는 API를 제공합니다. 특정 하드웨어 플랫폼은 스레드가 바쁜 대기(busy-wait) 상태라고 소프트웨어가 알려주면 이점을 얻을 수 있습니다.

                              • JEP 321: HTTP Client(Standard) [22]- HTTP/2 및 WebSocket을 구현하고 레거시 HttpURLConnection API를 대체할 수 있는 새로운 HTTP 클라이언트 API를 제공합니다.




                                P.S

                                다시 자바를 하면서 느낀게  "자바는 꾸준히 발전하고 있는 재밌고 가치있는 중심 언어이다"  입니다.

                                2020-09-24 10:17:51 에 아래 내용에서 변경 됨 #8


                                Java 11로 전환해야 하는 이유  /  OpenJDK 11 version  정리


                                API에 대한 눈에 띄는 추가 및 수정 사항이 있으며,
                                시작, 성능 및 메모리 사용을 개선하는 향상된 기능이 있습니다.그리고 LTS 버전입니다.

                                1. 람다 파라미터를 위한 지역변수 표현 

                                java 10버전에 편리한 var 구문이 생겨난 상황에서, 11버전에서는 람다 파라미터에서  좀 더 명시적으로 var 를 이용 할 수 있게 되었습니다. 따라서 아래와 같이 어노테이션을 명시할 수 있게 되었습니다.

                                list.stream()
                                    .map((@NotNull var s) -> s.toLowerCase())
                                    .collect(Collectors.toList());

                                2. HTTP Client (Standard) 

                                Non-Blocking request and response 지원 (with CompletableFuture)
                                Backpressure 지원(java.util.concurrent.Flow 패키지를 통해 Rx Flow를 구현체에 적용)
                                Factory method 형태로 지원
                                HTTP/2 지원
                                HttpClient 예제) 
                                public void get(String uri) throws Exception {
                                    HttpClient client = HttpClient.newHttpClient();
                                    HttpRequest request = HttpRequest.newBuilder()
                                          .uri(URI.create(uri))
                                          .build();
                                
                                    HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
                                    System.out.println(response.body());
                                }
                                참고로 Spring5에서는 Rest Client에 RestTemplate 대신해 WebClient를 사용하여 비동기구현을 할 수 있게 되었습니다. 기존 멀티쓰레드 방식을 버리고 Reactor(WebFlux) 와 함께 스프링 기반 웹서비스를 구현할 경우 그에 따른  성능과 효율 향상은 어마어마 합니다.

                                3. 모듈 

                                모듈을 통해 애플리케이션에 필요한 구성 요소만 포함하는 런타임 구성을 사용자 지정할 수 있습니다. 이 사용자 지정은 메모리 공간을 더 적게 사용하며 애플리케이션이 jlink를 사용하여 배포용 사용자 지정 런타임에 정적으로 연결될 수 있게 해줍니다. 메모리 공간을 적게 사용하면 특히 마이크로서비스 아키텍처에서 유용할 수 있습니다.

                                내부적으로 JVM은 모듈을 활용하여 클래스 로딩을 보다 효율적으로 만들 수 있습니다. 그 결과 런타임이 더 작아지고, 더 가벼워져서 더 빠르게 시작할 수 있습니다. 모듈은 클래스에 필요한 구성 요소를 인코딩하기 때문에 JVM에서 애플리케이션 성능을 개선하기 위해 사용하는 최적화 기법의 효과가 더 좋아질 수 있습니다.

                                프로그래머의 경우 모듈은 모듈이 내보내는 패키지와 필요한 구성 요소를 명시적으로 선언하고 반사적 액세스를 제한하여 강력한 캡슐화를 적용하는 데 도움이 됩니다. 이 캡슐화 수준을 사용하면 애플리케이션을 더 안전하고 쉽게 유지 관리할 수 있습니다.


                                4. 프로파일링 및 진단

                                Java Flight Recorder 

                                JFR(Java Flight Recorder)은 실행 중인 Java 애플리케이션에서 진단 및 프로파일링 데이터를 수집합니다.  JFR 및 JMC는 Java 8에서 상용 기능이지만 Java 11에서는 둘 다 오픈 소스입니다.

                                Java Mission Control 

                                JMC(Java Mission Control)는 JFR(Java Flight Recorder)에서 수집한 데이터를 그래픽으로 표시하고 Java에서는 오픈 소스로 제공됩니다. JFR 및 JMC를 사용하면 메모리 누수, GC 오버헤드, 핫 메서드, 스레드 병목 상태 및 I/O 블로킹과 같은 런타임 문제를 진단할 수 있습니다.

                                통합 로깅 

                                Java 11에는 JVM의 모든 구성 요소에 대한 일반적인 로깅 시스템이 있습니다.이 세분화된 로깅은 JVM 충돌에 대한 근본 원인 분석을 수행하고 프로덕션 환경에서 성능 문제를 진단하는 데 유용합니다.

                                오버헤드가 낮은 힙 프로파일링 

                                Java 힙 할당을 샘플링하는 데 사용할 수 있는 새 API가 JVMTI(Java Virtual Machine Tool Interface)에 추가되었습니다.JFR 구현에서는 할당이 누락될 수도 있습니다. 반면 Java 11의 힙 샘플링은 라이브 개체와 데드 개체 모두에 대한 정보를 제공할 수 있습니다. APM(애플리케이션 성능 모니터링) 공급업체가 이 새로운 기능을 활용하기 시작 했습니다.

                                StackWalker 

                                현재 스레드의 스택에 대한 스냅샷 가져오기는 로깅할 때 주로 사용됩니다.

                                5. 가비지 수집 

                                Java 11에서 사용할 수 있는 가비지 수집기는 직렬, 병렬, 가비지 우선 및 엡실론입니다. Java 11의 기본 가비지 수집기는 G1GC(가비지 우선 가비지 수집기)입니다.

                                ZGC일시 중지 시간을 10ms 미만으로 유지하려고 하는 대기 시간이 짧은 동시 수집기입니다. ZGC는 Java 11에서 실험적 기능으로 사용할 수 있습니다.CMS(Concurrent Mark and Sweep) 수집기는 사용할 수 있지만 Java 9 이후에는 사용되지 않습니다.

                                엡실론 

                                엡실론 가비지 수집기는 할당을 처리하지만 메모리를 회수하지는 않습니다. 힙이 소진되면 JVM이 종료됩니다. 엡실론은 수명이 짧은 서비스와 가비지를 사용하지 않는 것으로 알려진 애플리케이션에 유용합니다.

                                Docker 컨테이너의 향상된 기능 

                                Java 10 이전에 컨테이너에 설정된 메모리 및 CPU 제약 조건은 JVM에서 인식되지 않았습니다. 예를 들어 Java 8에서 JVM은 최대 힙 크기의 기본값을 기본 호스트의 실제 메모리의 ¼로 설정합니다. Java 10부터 JVM은 컨테이너 제어 그룹(cgroup)에 의해 설정된 제약 조건을 사용하여 메모리 및 CPU 제한을 설정합니다(아래 참고 사항 참조). 예를 들어 기본 최대 힙 크기는 컨테이너의 메모리 제한의 ¼입니다(예: -m2G의 경우 500MB).

                                다중 릴리스 jar 파일 

                                Java 11에서 클래스 파일의 여러 Java 릴리스별 버전을 포함하는 jar 파일을 만들 수 있습니다.

                                6. 성능 향상

                                JVM 성능향상) 

                                • JEP 197: Segmented Code Cache[14] - 코드 캐시를 고유 세그먼트로 나눕니다. 이러한 구분은 JVM 메모리 공간을 보다 효율적으로 제어하고, 컴파일된 메서드의 검색 시간을 단축하고, 코드 캐시의 조각화를 크게 줄이고, 성능을 향상시킵니다.

                                • JEP 254: Compact Strings[15] - 문자 인코딩에 따라 문자열의 내부 표현을 문자당 2바이트에서 문자당 1~2바이트로 변경합니다. 대부분의 문자열은 ISO-8859-1/라틴어-1 문자를 포함하므로 이 변경 내용으로 인해 문자열을 저장하는 데 필요한 공간이 효율적으로 변경됩니다.

                                • JEP 310: Application Class-Data Sharing[16] - 클래스-데이터 공유는 보관된 클래스가 런타임 시 메모리에 매핑될 수 있게 하여 시작 시간을 줄여줍니다. 애플리케이션 클래스-데이터 공유는 애플리케이션 클래스를 CDS 보관함에 배치할 수 있도록 하여 클래스-데이터 공유를 확장합니다. 여러 JVM이 동일한 보관 파일을 공유하는 경우 메모리가 저장되고 전체 시스템 응답 시간이 단축됩니다.

                                • JEP 312: Thread-Local Handshakes[17] - 글로벌 VM 세이프포인트를 수행하지 않고 스레드에 대한 콜백을 실행하여 VM이 글로벌 세이프포인트의 수를 줄여 대기 시간을 단축할 수 있게 해줍니다.

                                • Lazy Allocation of Compiler Threads[18] - VM은 단계별 컴파일 모드에서 다량의 컴파일러 스레드를 시작합니다. 이 모드는 CPU가 여러 개 있는 시스템에서 기본값입니다. 이러한 스레드는 사용 가능한 메모리 또는 컴파일 요청 수에 관계없이 생성됩니다. 스레드는 유휴 상태일 때(거의 모든 시간) 메모리를 사용하므로 리소스를 비효율적으로 사용합니다. 이 문제를 해결하기 위해 시작 시 각 유형의 컴파일러 스레드를 하나씩만 시작하도록 구현이 변경되었습니다. 추가 스레드를 시작하고 사용하지 않는 스레드를 종료하는 것은 동적으로 처리됩니다.

                                핵심 라이브러리 성능 향상) 

                                • JEP 193: Variable Handles[19] - 표준을 정의한다는 것은 개체 필드 및 배열 요소, 메모리 정렬의 세부적인 제어를 위한 표준 펜스 작업 세트, 참조된 개체의 강력한 연결성을 유지하기 위한 표준 연결성 펜스 작업에 대한 다양한 java.util.concurrent.atomic 및 sun.misc.Unsafe 작업의 동급 요소를 호출하는 것을 의미합니다.

                                • JEP 269: Convenience Factory Methods for Collections[20] - 소량의 요소를 사용하여 컬렉션 및 맵 인스턴스를 편리하게 만들 수 있게 해주는 라이브러리 API를 정의합니다. 컬렉션 인터페이스에서 간결하고 수정할 수 없는 컬렉션 인스턴스를 만드는 고정 팩터리 메서드입니다. 이러한 인스턴스는 본질적으로 더 효율적입니다. API는 조밀하게 표시되고 래퍼 클래스가 없는 컬렉션을 만듭니다.

                                • JEP 285: Spin-Wait Hints[21] - Java에서 스핀 루프에 있음을 런타임 시스템에 암시할 수 있게 해주는 API를 제공합니다. 특정 하드웨어 플랫폼은 스레드가 바쁜 대기(busy-wait) 상태라고 소프트웨어가 알려주면 이점을 얻을 수 있습니다.

                                • JEP 321: HTTP Client(Standard) [22]- HTTP/2 및 WebSocket을 구현하고 레거시 HttpURLConnection API를 대체할 수 있는 새로운 HTTP 클라이언트 API를 제공합니다.




                                  P.S

                                  다시 자바를 하면서 느낀게  "자바는 꾸준히 발전하고 있는 재밌고 가치있는 중심 언어이다"  입니다.

                                  2020-09-23 11:53:38 에 아래 내용에서 변경 됨 #7


                                  Java 11로 전환해야 하는 이유  /  OpenJDK 11 version  정리


                                  API에 대한 눈에 띄는 추가 및 수정 사항이 있으며,
                                  시작, 성능 및 메모리 사용을 개선하는 향상된 기능이 있습니다.그리고 LTS 버전입니다.

                                  1. 람다 파라미터를 위한 지역변수 표현 

                                  java 10버전에 편리한 var 구문이 생겨난 상황에서, 11버전에서는 람다 파라미터에서  좀 더 명시적으로 var 를 이용 할 수 있게 되었습니다. 따라서 아래와 같이 어노테이션을 명시할 수 있게 되었습니다.

                                  list.stream()
                                      .map((@NotNull var s) -> s.toLowerCase())
                                      .collect(Collectors.toList());

                                  2. HTTP Client (Standard) 

                                  Non-Blocking request and response 지원 (with CompletableFuture)
                                  Backpressure 지원(java.util.concurrent.Flow 패키지를 통해 Rx Flow를 구현체에 적용)
                                  Factory method 형태로 지원
                                  HTTP/2 지원
                                  HttpClient 예제) 
                                  public void get(String uri) throws Exception {
                                      HttpClient client = HttpClient.newHttpClient();
                                      HttpRequest request = HttpRequest.newBuilder()
                                            .uri(URI.create(uri))
                                            .build();
                                  
                                      HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
                                      System.out.println(response.body());
                                  }
                                  참고로 Spring5에서는 Rest Client에 RestTemplate 대신해 WebClient를 사용하여 비동기구현을 할 수 있게 되었습니다. 기존 멀티쓰레드 방식을 버리고 Reactor(WebFlux) 와 함께 스프링 기반 웹서비스를 구현할 경우 그에 따른  성능과 효율 향상은 어마어마 합니다.

                                  3. 모듈 

                                  모듈을 통해 애플리케이션에 필요한 구성 요소만 포함하는 런타임 구성을 사용자 지정할 수 있습니다. 이 사용자 지정은 메모리 공간을 더 적게 사용하며 애플리케이션이 jlink를 사용하여 배포용 사용자 지정 런타임에 정적으로 연결될 수 있게 해줍니다. 메모리 공간을 적게 사용하면 특히 마이크로서비스 아키텍처에서 유용할 수 있습니다.

                                  내부적으로 JVM은 모듈을 활용하여 클래스 로딩을 보다 효율적으로 만들 수 있습니다. 그 결과 런타임이 더 작아지고, 더 가벼워져서 더 빠르게 시작할 수 있습니다. 모듈은 클래스에 필요한 구성 요소를 인코딩하기 때문에 JVM에서 애플리케이션 성능을 개선하기 위해 사용하는 최적화 기법의 효과가 더 좋아질 수 있습니다.

                                  프로그래머의 경우 모듈은 모듈이 내보내는 패키지와 필요한 구성 요소를 명시적으로 선언하고 반사적 액세스를 제한하여 강력한 캡슐화를 적용하는 데 도움이 됩니다. 이 캡슐화 수준을 사용하면 애플리케이션을 더 안전하고 쉽게 유지 관리할 수 있습니다.


                                  4. 프로파일링 및 진단

                                  Java Flight Recorder 

                                  JFR(Java Flight Recorder)은 실행 중인 Java 애플리케이션에서 진단 및 프로파일링 데이터를 수집합니다.  JFR 및 JMC는 Java 8에서 상용 기능이지만 Java 11에서는 둘 다 오픈 소스입니다.

                                  Java Mission Control 

                                  JMC(Java Mission Control)는 JFR(Java Flight Recorder)에서 수집한 데이터를 그래픽으로 표시하고 Java에서는 오픈 소스로 제공됩니다. JFR 및 JMC를 사용하면 메모리 누수, GC 오버헤드, 핫 메서드, 스레드 병목 상태 및 I/O 블로킹과 같은 런타임 문제를 진단할 수 있습니다.

                                  통합 로깅 

                                  Java 11에는 JVM의 모든 구성 요소에 대한 일반적인 로깅 시스템이 있습니다.이 세분화된 로깅은 JVM 충돌에 대한 근본 원인 분석을 수행하고 프로덕션 환경에서 성능 문제를 진단하는 데 유용합니다.

                                  오버헤드가 낮은 힙 프로파일링 

                                  Java 힙 할당을 샘플링하는 데 사용할 수 있는 새 API가 JVMTI(Java Virtual Machine Tool Interface)에 추가되었습니다.JFR 구현에서는 할당이 누락될 수도 있습니다. 반면 Java 11의 힙 샘플링은 라이브 개체와 데드 개체 모두에 대한 정보를 제공할 수 있습니다. APM(애플리케이션 성능 모니터링) 공급업체가 이 새로운 기능을 활용하기 시작 했습니다.

                                  StackWalker 

                                  현재 스레드의 스택에 대한 스냅샷 가져오기는 로깅할 때 주로 사용됩니다.

                                  5. 가비지 수집 

                                  Java 11에서 사용할 수 있는 가비지 수집기는 직렬, 병렬, 가비지 우선 및 엡실론입니다. Java 11의 기본 가비지 수집기는 G1GC(가비지 우선 가비지 수집기)입니다.

                                  ZGC일시 중지 시간을 10ms 미만으로 유지하려고 하는 대기 시간이 짧은 동시 수집기입니다. ZGC는 Java 11에서 실험적 기능으로 사용할 수 있습니다.CMS(Concurrent Mark and Sweep) 수집기는 사용할 수 있지만 Java 9 이후에는 사용되지 않습니다.

                                  엡실론 

                                  엡실론 가비지 수집기는 할당을 처리하지만 메모리를 회수하지는 않습니다. 힙이 소진되면 JVM이 종료됩니다. 엡실론은 수명이 짧은 서비스와 가비지를 사용하지 않는 것으로 알려진 애플리케이션에 유용합니다.

                                  Docker 컨테이너의 향상된 기능 

                                  Java 10 이전에 컨테이너에 설정된 메모리 및 CPU 제약 조건은 JVM에서 인식되지 않았습니다. 예를 들어 Java 8에서 JVM은 최대 힙 크기의 기본값을 기본 호스트의 실제 메모리의 ¼로 설정합니다. Java 10부터 JVM은 컨테이너 제어 그룹(cgroup)에 의해 설정된 제약 조건을 사용하여 메모리 및 CPU 제한을 설정합니다(아래 참고 사항 참조). 예를 들어 기본 최대 힙 크기는 컨테이너의 메모리 제한의 ¼입니다(예: -m2G의 경우 500MB).

                                  다중 릴리스 jar 파일 

                                  Java 11에서 클래스 파일의 여러 Java 릴리스별 버전을 포함하는 jar 파일을 만들 수 있습니다.

                                  6. 성능 향상

                                  JVM 성능향상) 

                                  • JEP 197: Segmented Code Cache[14] - 코드 캐시를 고유 세그먼트로 나눕니다. 이러한 구분은 JVM 메모리 공간을 보다 효율적으로 제어하고, 컴파일된 메서드의 검색 시간을 단축하고, 코드 캐시의 조각화를 크게 줄이고, 성능을 향상시킵니다.

                                  • JEP 254: Compact Strings[15] - 문자 인코딩에 따라 문자열의 내부 표현을 문자당 2바이트에서 문자당 1~2바이트로 변경합니다. 대부분의 문자열은 ISO-8859-1/라틴어-1 문자를 포함하므로 이 변경 내용으로 인해 문자열을 저장하는 데 필요한 공간이 효율적으로 변경됩니다.

                                  • JEP 310: Application Class-Data Sharing[16] - 클래스-데이터 공유는 보관된 클래스가 런타임 시 메모리에 매핑될 수 있게 하여 시작 시간을 줄여줍니다. 애플리케이션 클래스-데이터 공유는 애플리케이션 클래스를 CDS 보관함에 배치할 수 있도록 하여 클래스-데이터 공유를 확장합니다. 여러 JVM이 동일한 보관 파일을 공유하는 경우 메모리가 저장되고 전체 시스템 응답 시간이 단축됩니다.

                                  • JEP 312: Thread-Local Handshakes[17] - 글로벌 VM 세이프포인트를 수행하지 않고 스레드에 대한 콜백을 실행하여 VM이 글로벌 세이프포인트의 수를 줄여 대기 시간을 단축할 수 있게 해줍니다.

                                  • Lazy Allocation of Compiler Threads[18] - VM은 단계별 컴파일 모드에서 다량의 컴파일러 스레드를 시작합니다. 이 모드는 CPU가 여러 개 있는 시스템에서 기본값입니다. 이러한 스레드는 사용 가능한 메모리 또는 컴파일 요청 수에 관계없이 생성됩니다. 스레드는 유휴 상태일 때(거의 모든 시간) 메모리를 사용하므로 리소스를 비효율적으로 사용합니다. 이 문제를 해결하기 위해 시작 시 각 유형의 컴파일러 스레드를 하나씩만 시작하도록 구현이 변경되었습니다. 추가 스레드를 시작하고 사용하지 않는 스레드를 종료하는 것은 동적으로 처리됩니다.

                                  핵심 라이브러리 성능 향상) 

                                  • JEP 193: Variable Handles[19] - 표준을 정의한다는 것은 개체 필드 및 배열 요소, 메모리 정렬의 세부적인 제어를 위한 표준 펜스 작업 세트, 참조된 개체의 강력한 연결성을 유지하기 위한 표준 연결성 펜스 작업에 대한 다양한 java.util.concurrent.atomic 및 sun.misc.Unsafe 작업의 동급 요소를 호출하는 것을 의미합니다.

                                  • JEP 269: Convenience Factory Methods for Collections[20] - 소량의 요소를 사용하여 컬렉션 및 맵 인스턴스를 편리하게 만들 수 있게 해주는 라이브러리 API를 정의합니다. 컬렉션 인터페이스에서 간결하고 수정할 수 없는 컬렉션 인스턴스를 만드는 고정 팩터리 메서드입니다. 이러한 인스턴스는 본질적으로 더 효율적입니다. API는 조밀하게 표시되고 래퍼 클래스가 없는 컬렉션을 만듭니다.

                                  • JEP 285: Spin-Wait Hints[21] - Java에서 스핀 루프에 있음을 런타임 시스템에 암시할 수 있게 해주는 API를 제공합니다. 특정 하드웨어 플랫폼은 스레드가 바쁜 대기(busy-wait) 상태라고 소프트웨어가 알려주면 이점을 얻을 수 있습니다.

                                  • JEP 321: HTTP Client(Standard) [22]- HTTP/2 및 WebSocket을 구현하고 레거시 HttpURLConnection API를 대체할 수 있는 새로운 HTTP 클라이언트 API를 제공합니다.




                                    P.S

                                    다시 자바를 하게 되면서 느낀게, "자바는 꾸준히 발전하고 있는 재밌고 가치있는 언어이다" 같습니다.

                                    2020-09-23 11:50:19 에 아래 내용에서 변경 됨 #6


                                    Java 11로 전환해야 하는 이유  /  OpenJDK 11 version  정리


                                    API에 대한 눈에 띄는 추가 및 수정 사항이 있으며,
                                    시작, 성능 및 메모리 사용을 개선하는 향상된 기능이 있습니다.

                                    1. 람다 파라미터를 위한 지역변수 표현 

                                    java 10버전에 편리한 var 구문이 생겨난 상황에서, 11버전에서는 람다 파라미터에서  좀 더 명시적으로 var 를 이용 할 수 있게 되었습니다. 따라서 아래와 같이 어노테이션을 명시할 수 있게 되었습니다.

                                    list.stream()
                                        .map((@NotNull var s) -> s.toLowerCase())
                                        .collect(Collectors.toList());

                                    2. HTTP Client (Standard) 

                                    Non-Blocking request and response 지원 (with CompletableFuture)
                                    Backpressure 지원(java.util.concurrent.Flow 패키지를 통해 Rx Flow를 구현체에 적용)
                                    Factory method 형태로 지원
                                    HTTP/2 지원
                                    HttpClient 예제) 
                                    public void get(String uri) throws Exception {
                                        HttpClient client = HttpClient.newHttpClient();
                                        HttpRequest request = HttpRequest.newBuilder()
                                              .uri(URI.create(uri))
                                              .build();
                                    
                                        HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
                                        System.out.println(response.body());
                                    }
                                    참고로 Spring5에서는 Rest Client에 RestTemplate 대신해 WebClient를 사용하여 비동기구현을 할 수 있게 되었습니다. 기존 멀티쓰레드 방식을 버리고 Reactor(WebFlux) 와 함께 스프링 기반 웹서비스를 구현할 경우 그에 따른  성능과 효율 향상은 어마어마 합니다.

                                    3. 모듈 

                                    모듈을 통해 애플리케이션에 필요한 구성 요소만 포함하는 런타임 구성을 사용자 지정할 수 있습니다. 이 사용자 지정은 메모리 공간을 더 적게 사용하며 애플리케이션이 jlink를 사용하여 배포용 사용자 지정 런타임에 정적으로 연결될 수 있게 해줍니다. 메모리 공간을 적게 사용하면 특히 마이크로서비스 아키텍처에서 유용할 수 있습니다.

                                    내부적으로 JVM은 모듈을 활용하여 클래스 로딩을 보다 효율적으로 만들 수 있습니다. 그 결과 런타임이 더 작아지고, 더 가벼워져서 더 빠르게 시작할 수 있습니다. 모듈은 클래스에 필요한 구성 요소를 인코딩하기 때문에 JVM에서 애플리케이션 성능을 개선하기 위해 사용하는 최적화 기법의 효과가 더 좋아질 수 있습니다.

                                    프로그래머의 경우 모듈은 모듈이 내보내는 패키지와 필요한 구성 요소를 명시적으로 선언하고 반사적 액세스를 제한하여 강력한 캡슐화를 적용하는 데 도움이 됩니다. 이 캡슐화 수준을 사용하면 애플리케이션을 더 안전하고 쉽게 유지 관리할 수 있습니다.


                                    4. 프로파일링 및 진단

                                    Java Flight Recorder 

                                    JFR(Java Flight Recorder)은 실행 중인 Java 애플리케이션에서 진단 및 프로파일링 데이터를 수집합니다.  JFR 및 JMC는 Java 8에서 상용 기능이지만 Java 11에서는 둘 다 오픈 소스입니다.

                                    Java Mission Control 

                                    JMC(Java Mission Control)는 JFR(Java Flight Recorder)에서 수집한 데이터를 그래픽으로 표시하고 Java에서는 오픈 소스로 제공됩니다. JFR 및 JMC를 사용하면 메모리 누수, GC 오버헤드, 핫 메서드, 스레드 병목 상태 및 I/O 블로킹과 같은 런타임 문제를 진단할 수 있습니다.

                                    통합 로깅 

                                    Java 11에는 JVM의 모든 구성 요소에 대한 일반적인 로깅 시스템이 있습니다.이 세분화된 로깅은 JVM 충돌에 대한 근본 원인 분석을 수행하고 프로덕션 환경에서 성능 문제를 진단하는 데 유용합니다.

                                    오버헤드가 낮은 힙 프로파일링 

                                    Java 힙 할당을 샘플링하는 데 사용할 수 있는 새 API가 JVMTI(Java Virtual Machine Tool Interface)에 추가되었습니다.JFR 구현에서는 할당이 누락될 수도 있습니다. 반면 Java 11의 힙 샘플링은 라이브 개체와 데드 개체 모두에 대한 정보를 제공할 수 있습니다. APM(애플리케이션 성능 모니터링) 공급업체가 이 새로운 기능을 활용하기 시작 했습니다.

                                    StackWalker 

                                    현재 스레드의 스택에 대한 스냅샷 가져오기는 로깅할 때 주로 사용됩니다.

                                    5. 가비지 수집 

                                    Java 11에서 사용할 수 있는 가비지 수집기는 직렬, 병렬, 가비지 우선 및 엡실론입니다. Java 11의 기본 가비지 수집기는 G1GC(가비지 우선 가비지 수집기)입니다.

                                    ZGC일시 중지 시간을 10ms 미만으로 유지하려고 하는 대기 시간이 짧은 동시 수집기입니다. ZGC는 Java 11에서 실험적 기능으로 사용할 수 있습니다.CMS(Concurrent Mark and Sweep) 수집기는 사용할 수 있지만 Java 9 이후에는 사용되지 않습니다.

                                    엡실론 

                                    엡실론 가비지 수집기는 할당을 처리하지만 메모리를 회수하지는 않습니다. 힙이 소진되면 JVM이 종료됩니다. 엡실론은 수명이 짧은 서비스와 가비지를 사용하지 않는 것으로 알려진 애플리케이션에 유용합니다.

                                    Docker 컨테이너의 향상된 기능 

                                    Java 10 이전에 컨테이너에 설정된 메모리 및 CPU 제약 조건은 JVM에서 인식되지 않았습니다. 예를 들어 Java 8에서 JVM은 최대 힙 크기의 기본값을 기본 호스트의 실제 메모리의 ¼로 설정합니다. Java 10부터 JVM은 컨테이너 제어 그룹(cgroup)에 의해 설정된 제약 조건을 사용하여 메모리 및 CPU 제한을 설정합니다(아래 참고 사항 참조). 예를 들어 기본 최대 힙 크기는 컨테이너의 메모리 제한의 ¼입니다(예: -m2G의 경우 500MB).

                                    다중 릴리스 jar 파일 

                                    Java 11에서 클래스 파일의 여러 Java 릴리스별 버전을 포함하는 jar 파일을 만들 수 있습니다.

                                    6. 성능 향상

                                    JVM 성능향상) 

                                    • JEP 197: Segmented Code Cache[14] - 코드 캐시를 고유 세그먼트로 나눕니다. 이러한 구분은 JVM 메모리 공간을 보다 효율적으로 제어하고, 컴파일된 메서드의 검색 시간을 단축하고, 코드 캐시의 조각화를 크게 줄이고, 성능을 향상시킵니다.

                                    • JEP 254: Compact Strings[15] - 문자 인코딩에 따라 문자열의 내부 표현을 문자당 2바이트에서 문자당 1~2바이트로 변경합니다. 대부분의 문자열은 ISO-8859-1/라틴어-1 문자를 포함하므로 이 변경 내용으로 인해 문자열을 저장하는 데 필요한 공간이 효율적으로 변경됩니다.

                                    • JEP 310: Application Class-Data Sharing[16] - 클래스-데이터 공유는 보관된 클래스가 런타임 시 메모리에 매핑될 수 있게 하여 시작 시간을 줄여줍니다. 애플리케이션 클래스-데이터 공유는 애플리케이션 클래스를 CDS 보관함에 배치할 수 있도록 하여 클래스-데이터 공유를 확장합니다. 여러 JVM이 동일한 보관 파일을 공유하는 경우 메모리가 저장되고 전체 시스템 응답 시간이 단축됩니다.

                                    • JEP 312: Thread-Local Handshakes[17] - 글로벌 VM 세이프포인트를 수행하지 않고 스레드에 대한 콜백을 실행하여 VM이 글로벌 세이프포인트의 수를 줄여 대기 시간을 단축할 수 있게 해줍니다.

                                    • Lazy Allocation of Compiler Threads[18] - VM은 단계별 컴파일 모드에서 다량의 컴파일러 스레드를 시작합니다. 이 모드는 CPU가 여러 개 있는 시스템에서 기본값입니다. 이러한 스레드는 사용 가능한 메모리 또는 컴파일 요청 수에 관계없이 생성됩니다. 스레드는 유휴 상태일 때(거의 모든 시간) 메모리를 사용하므로 리소스를 비효율적으로 사용합니다. 이 문제를 해결하기 위해 시작 시 각 유형의 컴파일러 스레드를 하나씩만 시작하도록 구현이 변경되었습니다. 추가 스레드를 시작하고 사용하지 않는 스레드를 종료하는 것은 동적으로 처리됩니다.

                                    핵심 라이브러리 성능 향상) 

                                    • JEP 193: Variable Handles[19] - 표준을 정의한다는 것은 개체 필드 및 배열 요소, 메모리 정렬의 세부적인 제어를 위한 표준 펜스 작업 세트, 참조된 개체의 강력한 연결성을 유지하기 위한 표준 연결성 펜스 작업에 대한 다양한 java.util.concurrent.atomic 및 sun.misc.Unsafe 작업의 동급 요소를 호출하는 것을 의미합니다.

                                    • JEP 269: Convenience Factory Methods for Collections[20] - 소량의 요소를 사용하여 컬렉션 및 맵 인스턴스를 편리하게 만들 수 있게 해주는 라이브러리 API를 정의합니다. 컬렉션 인터페이스에서 간결하고 수정할 수 없는 컬렉션 인스턴스를 만드는 고정 팩터리 메서드입니다. 이러한 인스턴스는 본질적으로 더 효율적입니다. API는 조밀하게 표시되고 래퍼 클래스가 없는 컬렉션을 만듭니다.

                                    • JEP 285: Spin-Wait Hints[21] - Java에서 스핀 루프에 있음을 런타임 시스템에 암시할 수 있게 해주는 API를 제공합니다. 특정 하드웨어 플랫폼은 스레드가 바쁜 대기(busy-wait) 상태라고 소프트웨어가 알려주면 이점을 얻을 수 있습니다.

                                    • JEP 321: HTTP Client(Standard) [22]- HTTP/2 및 WebSocket을 구현하고 레거시 HttpURLConnection API를 대체할 수 있는 새로운 HTTP 클라이언트 API를 제공합니다.




                                      P.S

                                      다시 자바를 하게 되면서 느낀게, "자바는 꾸준히 발전하고 있는 재밌고 가치있는 언어이다" 같습니다.

                                      2020-09-23 11:49:46 에 아래 내용에서 변경 됨 #5


                                      Java 11로 전환해야 하는 이유  /  OpenJDK 11 version  정리


                                      API에 대한 눈에 띄는 추가 및 수정 사항이 있으며,
                                      시작, 성능 및 메모리 사용을 개선하는 향상된 기능이 있습니다.

                                      1. 람다 파라미터를 위한 지역변수 표현 

                                      java 10버전에 편리한 var 구문이 생겨난 상황에서, 11버전에서는 람다 파라미터에서  좀 더 명시적으로 var 를 이용 할 수 있게 되었다. 따라서 아래와 같이 어노테이션을 명시할 수 있게 되었다. 

                                      list.stream()
                                          .map((@NotNull var s) -> s.toLowerCase())
                                          .collect(Collectors.toList());

                                      2. HTTP Client (Standard) 

                                      Non-Blocking request and response 지원 (with CompletableFuture)
                                      Backpressure 지원(java.util.concurrent.Flow 패키지를 통해 Rx Flow를 구현체에 적용)
                                      Factory method 형태로 지원
                                      HTTP/2 지원
                                      HttpClient 예제) 
                                      public void get(String uri) throws Exception {
                                          HttpClient client = HttpClient.newHttpClient();
                                          HttpRequest request = HttpRequest.newBuilder()
                                                .uri(URI.create(uri))
                                                .build();
                                      
                                          HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
                                          System.out.println(response.body());
                                      }
                                      참고로 Spring5에서는 Rest Client에 RestTemplate 대신해 WebClient를 사용하여 비동기구현을 할 수 있게 되었다. 기존 멀티쓰레드 방식을 버리고 Reactor(WebFlux) 와 함께 스프링 기반 웹서비스를 구현할 경우 그에 따른  성능과 효율 향상은 어마어마 하다. 

                                      3. 모듈 

                                      모듈을 통해 애플리케이션에 필요한 구성 요소만 포함하는 런타임 구성을 사용자 지정할 수 있습니다. 이 사용자 지정은 메모리 공간을 더 적게 사용하며 애플리케이션이 jlink를 사용하여 배포용 사용자 지정 런타임에 정적으로 연결될 수 있게 해줍니다. 메모리 공간을 적게 사용하면 특히 마이크로서비스 아키텍처에서 유용할 수 있습니다.

                                      내부적으로 JVM은 모듈을 활용하여 클래스 로딩을 보다 효율적으로 만들 수 있습니다. 그 결과 런타임이 더 작아지고, 더 가벼워져서 더 빠르게 시작할 수 있습니다. 모듈은 클래스에 필요한 구성 요소를 인코딩하기 때문에 JVM에서 애플리케이션 성능을 개선하기 위해 사용하는 최적화 기법의 효과가 더 좋아질 수 있습니다.

                                      프로그래머의 경우 모듈은 모듈이 내보내는 패키지와 필요한 구성 요소를 명시적으로 선언하고 반사적 액세스를 제한하여 강력한 캡슐화를 적용하는 데 도움이 됩니다. 이 캡슐화 수준을 사용하면 애플리케이션을 더 안전하고 쉽게 유지 관리할 수 있습니다.


                                      4. 프로파일링 및 진단

                                      Java Flight Recorder 

                                      JFR(Java Flight Recorder)은 실행 중인 Java 애플리케이션에서 진단 및 프로파일링 데이터를 수집합니다.  JFR 및 JMC는 Java 8에서 상용 기능이지만 Java 11에서는 둘 다 오픈 소스입니다.

                                      Java Mission Control 

                                      JMC(Java Mission Control)는 JFR(Java Flight Recorder)에서 수집한 데이터를 그래픽으로 표시하고 Java에서는 오픈 소스로 제공됩니다. JFR 및 JMC를 사용하면 메모리 누수, GC 오버헤드, 핫 메서드, 스레드 병목 상태 및 I/O 블로킹과 같은 런타임 문제를 진단할 수 있습니다.

                                      통합 로깅 

                                      Java 11에는 JVM의 모든 구성 요소에 대한 일반적인 로깅 시스템이 있습니다.이 세분화된 로깅은 JVM 충돌에 대한 근본 원인 분석을 수행하고 프로덕션 환경에서 성능 문제를 진단하는 데 유용합니다.

                                      오버헤드가 낮은 힙 프로파일링 

                                      Java 힙 할당을 샘플링하는 데 사용할 수 있는 새 API가 JVMTI(Java Virtual Machine Tool Interface)에 추가되었습니다.JFR 구현에서는 할당이 누락될 수도 있습니다. 반면 Java 11의 힙 샘플링은 라이브 개체와 데드 개체 모두에 대한 정보를 제공할 수 있습니다. APM(애플리케이션 성능 모니터링) 공급업체가 이 새로운 기능을 활용하기 시작 했습니다.

                                      StackWalker 

                                      현재 스레드의 스택에 대한 스냅샷 가져오기는 로깅할 때 주로 사용됩니다.

                                      5. 가비지 수집 

                                      Java 11에서 사용할 수 있는 가비지 수집기는 직렬, 병렬, 가비지 우선 및 엡실론입니다. Java 11의 기본 가비지 수집기는 G1GC(가비지 우선 가비지 수집기)입니다.

                                      ZGC일시 중지 시간을 10ms 미만으로 유지하려고 하는 대기 시간이 짧은 동시 수집기입니다. ZGC는 Java 11에서 실험적 기능으로 사용할 수 있습니다.CMS(Concurrent Mark and Sweep) 수집기는 사용할 수 있지만 Java 9 이후에는 사용되지 않습니다.

                                      엡실론 

                                      엡실론 가비지 수집기는 할당을 처리하지만 메모리를 회수하지는 않습니다. 힙이 소진되면 JVM이 종료됩니다. 엡실론은 수명이 짧은 서비스와 가비지를 사용하지 않는 것으로 알려진 애플리케이션에 유용합니다.

                                      Docker 컨테이너의 향상된 기능 

                                      Java 10 이전에 컨테이너에 설정된 메모리 및 CPU 제약 조건은 JVM에서 인식되지 않았습니다. 예를 들어 Java 8에서 JVM은 최대 힙 크기의 기본값을 기본 호스트의 실제 메모리의 ¼로 설정합니다. Java 10부터 JVM은 컨테이너 제어 그룹(cgroup)에 의해 설정된 제약 조건을 사용하여 메모리 및 CPU 제한을 설정합니다(아래 참고 사항 참조). 예를 들어 기본 최대 힙 크기는 컨테이너의 메모리 제한의 ¼입니다(예: -m2G의 경우 500MB).

                                      다중 릴리스 jar 파일 

                                      Java 11에서 클래스 파일의 여러 Java 릴리스별 버전을 포함하는 jar 파일을 만들 수 있습니다.

                                      6. 성능 향상

                                      JVM 성능향상) 

                                      • JEP 197: Segmented Code Cache[14] - 코드 캐시를 고유 세그먼트로 나눕니다. 이러한 구분은 JVM 메모리 공간을 보다 효율적으로 제어하고, 컴파일된 메서드의 검색 시간을 단축하고, 코드 캐시의 조각화를 크게 줄이고, 성능을 향상시킵니다.

                                      • JEP 254: Compact Strings[15] - 문자 인코딩에 따라 문자열의 내부 표현을 문자당 2바이트에서 문자당 1~2바이트로 변경합니다. 대부분의 문자열은 ISO-8859-1/라틴어-1 문자를 포함하므로 이 변경 내용으로 인해 문자열을 저장하는 데 필요한 공간이 효율적으로 변경됩니다.

                                      • JEP 310: Application Class-Data Sharing[16] - 클래스-데이터 공유는 보관된 클래스가 런타임 시 메모리에 매핑될 수 있게 하여 시작 시간을 줄여줍니다. 애플리케이션 클래스-데이터 공유는 애플리케이션 클래스를 CDS 보관함에 배치할 수 있도록 하여 클래스-데이터 공유를 확장합니다. 여러 JVM이 동일한 보관 파일을 공유하는 경우 메모리가 저장되고 전체 시스템 응답 시간이 단축됩니다.

                                      • JEP 312: Thread-Local Handshakes[17] - 글로벌 VM 세이프포인트를 수행하지 않고 스레드에 대한 콜백을 실행하여 VM이 글로벌 세이프포인트의 수를 줄여 대기 시간을 단축할 수 있게 해줍니다.

                                      • Lazy Allocation of Compiler Threads[18] - VM은 단계별 컴파일 모드에서 다량의 컴파일러 스레드를 시작합니다. 이 모드는 CPU가 여러 개 있는 시스템에서 기본값입니다. 이러한 스레드는 사용 가능한 메모리 또는 컴파일 요청 수에 관계없이 생성됩니다. 스레드는 유휴 상태일 때(거의 모든 시간) 메모리를 사용하므로 리소스를 비효율적으로 사용합니다. 이 문제를 해결하기 위해 시작 시 각 유형의 컴파일러 스레드를 하나씩만 시작하도록 구현이 변경되었습니다. 추가 스레드를 시작하고 사용하지 않는 스레드를 종료하는 것은 동적으로 처리됩니다.

                                      핵심 라이브러리 성능 향상) 

                                      • JEP 193: Variable Handles[19] - 표준을 정의한다는 것은 개체 필드 및 배열 요소, 메모리 정렬의 세부적인 제어를 위한 표준 펜스 작업 세트, 참조된 개체의 강력한 연결성을 유지하기 위한 표준 연결성 펜스 작업에 대한 다양한 java.util.concurrent.atomic 및 sun.misc.Unsafe 작업의 동급 요소를 호출하는 것을 의미합니다.

                                      • JEP 269: Convenience Factory Methods for Collections[20] - 소량의 요소를 사용하여 컬렉션 및 맵 인스턴스를 편리하게 만들 수 있게 해주는 라이브러리 API를 정의합니다. 컬렉션 인터페이스에서 간결하고 수정할 수 없는 컬렉션 인스턴스를 만드는 고정 팩터리 메서드입니다. 이러한 인스턴스는 본질적으로 더 효율적입니다. API는 조밀하게 표시되고 래퍼 클래스가 없는 컬렉션을 만듭니다.

                                      • JEP 285: Spin-Wait Hints[21] - Java에서 스핀 루프에 있음을 런타임 시스템에 암시할 수 있게 해주는 API를 제공합니다. 특정 하드웨어 플랫폼은 스레드가 바쁜 대기(busy-wait) 상태라고 소프트웨어가 알려주면 이점을 얻을 수 있습니다.

                                      • JEP 321: HTTP Client(Standard) [22]- HTTP/2 및 WebSocket을 구현하고 레거시 HttpURLConnection API를 대체할 수 있는 새로운 HTTP 클라이언트 API를 제공합니다.




                                        P.S

                                        다시 자바를 하게 되면서 느낀게, "자바는 꾸준히 발전하고 있는 재밌고 가치있는 언어이다" 같습니다.

                                        2020-09-23 11:48:45 에 아래 내용에서 변경 됨 #4


                                        Java 11로 전환해야 하는 이유  /  OpenJDK 11 version  정리


                                        API에 대한 눈에 띄는 추가 및 수정 사항이 있으며,
                                        시작, 성능 및 메모리 사용을 개선하는 향상된 기능이 있습니다.

                                        람다 파라미터를 위한 지역변수 표현 

                                        java 10버전에 편리한 var 구문이 생겨난 상황에서, 11버전에서는 람다 파라미터에서  좀 더 명시적으로 var 를 이용 할 수 있게 되었다. 따라서 아래와 같이 어노테이션을 명시할 수 있게 되었다. 

                                        list.stream()
                                            .map((@NotNull var s) -> s.toLowerCase())
                                            .collect(Collectors.toList());

                                        HTTP Client (Standard) 

                                        Non-Blocking request and response 지원 (with CompletableFuture)
                                        Backpressure 지원(java.util.concurrent.Flow 패키지를 통해 Rx Flow를 구현체에 적용)
                                        Factory method 형태로 지원
                                        HTTP/2 지원
                                        HttpClient 예제) 
                                        public void get(String uri) throws Exception {
                                            HttpClient client = HttpClient.newHttpClient();
                                            HttpRequest request = HttpRequest.newBuilder()
                                                  .uri(URI.create(uri))
                                                  .build();
                                        
                                            HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
                                            System.out.println(response.body());
                                        }
                                        참고로 Spring5에서는 Rest Client에 RestTemplate 대신해 WebClient를 사용하여 비동기구현을 할 수 있게 되었다. 기존 멀티쓰레드 방식을 버리고 Reactor(WebFlux) 와 함께 스프링 기반 웹서비스를 구현할 경우 그에 따른  성능과 효율 향상은 어마어마 하다. 

                                        모듈 

                                        모듈을 통해 애플리케이션에 필요한 구성 요소만 포함하는 런타임 구성을 사용자 지정할 수 있습니다. 이 사용자 지정은 메모리 공간을 더 적게 사용하며 애플리케이션이 jlink를 사용하여 배포용 사용자 지정 런타임에 정적으로 연결될 수 있게 해줍니다. 메모리 공간을 적게 사용하면 특히 마이크로서비스 아키텍처에서 유용할 수 있습니다.

                                        내부적으로 JVM은 모듈을 활용하여 클래스 로딩을 보다 효율적으로 만들 수 있습니다. 그 결과 런타임이 더 작아지고, 더 가벼워져서 더 빠르게 시작할 수 있습니다. 모듈은 클래스에 필요한 구성 요소를 인코딩하기 때문에 JVM에서 애플리케이션 성능을 개선하기 위해 사용하는 최적화 기법의 효과가 더 좋아질 수 있습니다.

                                        프로그래머의 경우 모듈은 모듈이 내보내는 패키지와 필요한 구성 요소를 명시적으로 선언하고 반사적 액세스를 제한하여 강력한 캡슐화를 적용하는 데 도움이 됩니다. 이 캡슐화 수준을 사용하면 애플리케이션을 더 안전하고 쉽게 유지 관리할 수 있습니다.


                                        프로파일링 및 진단

                                        Java Flight Recorder 

                                        JFR(Java Flight Recorder)은 실행 중인 Java 애플리케이션에서 진단 및 프로파일링 데이터를 수집합니다.  JFR 및 JMC는 Java 8에서 상용 기능이지만 Java 11에서는 둘 다 오픈 소스입니다.

                                        Java Mission Control 

                                        JMC(Java Mission Control)는 JFR(Java Flight Recorder)에서 수집한 데이터를 그래픽으로 표시하고 Java에서는 오픈 소스로 제공됩니다. JFR 및 JMC를 사용하면 메모리 누수, GC 오버헤드, 핫 메서드, 스레드 병목 상태 및 I/O 블로킹과 같은 런타임 문제를 진단할 수 있습니다.

                                        통합 로깅 

                                        Java 11에는 JVM의 모든 구성 요소에 대한 일반적인 로깅 시스템이 있습니다.이 세분화된 로깅은 JVM 충돌에 대한 근본 원인 분석을 수행하고 프로덕션 환경에서 성능 문제를 진단하는 데 유용합니다.

                                        오버헤드가 낮은 힙 프로파일링 

                                        Java 힙 할당을 샘플링하는 데 사용할 수 있는 새 API가 JVMTI(Java Virtual Machine Tool Interface)에 추가되었습니다.JFR 구현에서는 할당이 누락될 수도 있습니다. 반면 Java 11의 힙 샘플링은 라이브 개체와 데드 개체 모두에 대한 정보를 제공할 수 있습니다. APM(애플리케이션 성능 모니터링) 공급업체가 이 새로운 기능을 활용하기 시작 했습니다.

                                        StackWalker 

                                        현재 스레드의 스택에 대한 스냅샷 가져오기는 로깅할 때 주로 사용됩니다.

                                        가비지 수집 

                                        Java 11에서 사용할 수 있는 가비지 수집기는 직렬, 병렬, 가비지 우선 및 엡실론입니다. Java 11의 기본 가비지 수집기는 G1GC(가비지 우선 가비지 수집기)입니다.

                                        ZGC일시 중지 시간을 10ms 미만으로 유지하려고 하는 대기 시간이 짧은 동시 수집기입니다. ZGC는 Java 11에서 실험적 기능으로 사용할 수 있습니다.CMS(Concurrent Mark and Sweep) 수집기는 사용할 수 있지만 Java 9 이후에는 사용되지 않습니다.

                                        엡실론 

                                        엡실론 가비지 수집기는 할당을 처리하지만 메모리를 회수하지는 않습니다. 힙이 소진되면 JVM이 종료됩니다. 엡실론은 수명이 짧은 서비스와 가비지를 사용하지 않는 것으로 알려진 애플리케이션에 유용합니다.

                                        Docker 컨테이너의 향상된 기능 

                                        Java 10 이전에 컨테이너에 설정된 메모리 및 CPU 제약 조건은 JVM에서 인식되지 않았습니다. 예를 들어 Java 8에서 JVM은 최대 힙 크기의 기본값을 기본 호스트의 실제 메모리의 ¼로 설정합니다. Java 10부터 JVM은 컨테이너 제어 그룹(cgroup)에 의해 설정된 제약 조건을 사용하여 메모리 및 CPU 제한을 설정합니다(아래 참고 사항 참조). 예를 들어 기본 최대 힙 크기는 컨테이너의 메모리 제한의 ¼입니다(예: -m2G의 경우 500MB).


                                        다중 릴리스 jar 파일 

                                        Java 11에서 클래스 파일의 여러 Java 릴리스별 버전을 포함하는 jar 파일을 만들 수 있습니다.

                                        성능 향상

                                        JVM 성능향상) 

                                        • JEP 197: Segmented Code Cache[14] - 코드 캐시를 고유 세그먼트로 나눕니다. 이러한 구분은 JVM 메모리 공간을 보다 효율적으로 제어하고, 컴파일된 메서드의 검색 시간을 단축하고, 코드 캐시의 조각화를 크게 줄이고, 성능을 향상시킵니다.

                                        • JEP 254: Compact Strings[15] - 문자 인코딩에 따라 문자열의 내부 표현을 문자당 2바이트에서 문자당 1~2바이트로 변경합니다. 대부분의 문자열은 ISO-8859-1/라틴어-1 문자를 포함하므로 이 변경 내용으로 인해 문자열을 저장하는 데 필요한 공간이 효율적으로 변경됩니다.

                                        • JEP 310: Application Class-Data Sharing[16] - 클래스-데이터 공유는 보관된 클래스가 런타임 시 메모리에 매핑될 수 있게 하여 시작 시간을 줄여줍니다. 애플리케이션 클래스-데이터 공유는 애플리케이션 클래스를 CDS 보관함에 배치할 수 있도록 하여 클래스-데이터 공유를 확장합니다. 여러 JVM이 동일한 보관 파일을 공유하는 경우 메모리가 저장되고 전체 시스템 응답 시간이 단축됩니다.

                                        • JEP 312: Thread-Local Handshakes[17] - 글로벌 VM 세이프포인트를 수행하지 않고 스레드에 대한 콜백을 실행하여 VM이 글로벌 세이프포인트의 수를 줄여 대기 시간을 단축할 수 있게 해줍니다.

                                        • Lazy Allocation of Compiler Threads[18] - VM은 단계별 컴파일 모드에서 다량의 컴파일러 스레드를 시작합니다. 이 모드는 CPU가 여러 개 있는 시스템에서 기본값입니다. 이러한 스레드는 사용 가능한 메모리 또는 컴파일 요청 수에 관계없이 생성됩니다. 스레드는 유휴 상태일 때(거의 모든 시간) 메모리를 사용하므로 리소스를 비효율적으로 사용합니다. 이 문제를 해결하기 위해 시작 시 각 유형의 컴파일러 스레드를 하나씩만 시작하도록 구현이 변경되었습니다. 추가 스레드를 시작하고 사용하지 않는 스레드를 종료하는 것은 동적으로 처리됩니다.

                                        핵심 라이브러리 성능 향상) 

                                        • JEP 193: Variable Handles[19] - 표준을 정의한다는 것은 개체 필드 및 배열 요소, 메모리 정렬의 세부적인 제어를 위한 표준 펜스 작업 세트, 참조된 개체의 강력한 연결성을 유지하기 위한 표준 연결성 펜스 작업에 대한 다양한 java.util.concurrent.atomic 및 sun.misc.Unsafe 작업의 동급 요소를 호출하는 것을 의미합니다.

                                        • JEP 269: Convenience Factory Methods for Collections[20] - 소량의 요소를 사용하여 컬렉션 및 맵 인스턴스를 편리하게 만들 수 있게 해주는 라이브러리 API를 정의합니다. 컬렉션 인터페이스에서 간결하고 수정할 수 없는 컬렉션 인스턴스를 만드는 고정 팩터리 메서드입니다. 이러한 인스턴스는 본질적으로 더 효율적입니다. API는 조밀하게 표시되고 래퍼 클래스가 없는 컬렉션을 만듭니다.

                                        • JEP 285: Spin-Wait Hints[21] - Java에서 스핀 루프에 있음을 런타임 시스템에 암시할 수 있게 해주는 API를 제공합니다. 특정 하드웨어 플랫폼은 스레드가 바쁜 대기(busy-wait) 상태라고 소프트웨어가 알려주면 이점을 얻을 수 있습니다.

                                        • JEP 321: HTTP Client(Standard) [22]- HTTP/2 및 WebSocket을 구현하고 레거시 HttpURLConnection API를 대체할 수 있는 새로운 HTTP 클라이언트 API를 제공합니다.




                                          P.S

                                          다시 자바를 하게 되면서 느낀게, "자바는 꾸준히 발전하고 있는 재밌고 가치있는 언어이다" 같습니다.

                                          2020-09-23 11:47:36 에 아래 내용에서 변경 됨 #3

                                          다시 자바를 하게 되면서 느낀게, "자바는 꾸준히 발전하고 있는 재밌고 가치있는 언어이다" 같습니다.





                                          Java 11로 전환해야 하는 이유  /  OpenJDK 11 version  정리


                                          API에 대한 눈에 띄는 추가 및 수정 사항이 있으며,
                                          시작, 성능 및 메모리 사용을 개선하는 향상된 기능이 있습니다.

                                          람다 파라미터를 위한 지역변수 표현 

                                          java 10버전에 편리한 var 구문이 생겨난 상황에서, 11버전에서는 람다 파라미터에서  좀 더 명시적으로 var 를 이용 할 수 있게 되었다. 따라서 아래와 같이 어노테이션을 명시할 수 있게 되었다. 

                                          list.stream()
                                              .map((@NotNull var s) -> s.toLowerCase())
                                              .collect(Collectors.toList());

                                          HTTP Client (Standard) 

                                          Non-Blocking request and response 지원 (with CompletableFuture)
                                          Backpressure 지원(java.util.concurrent.Flow 패키지를 통해 Rx Flow를 구현체에 적용)
                                          Factory method 형태로 지원
                                          HTTP/2 지원
                                          HttpClient 예제) 
                                          public void get(String uri) throws Exception {
                                              HttpClient client = HttpClient.newHttpClient();
                                              HttpRequest request = HttpRequest.newBuilder()
                                                    .uri(URI.create(uri))
                                                    .build();
                                          
                                              HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
                                              System.out.println(response.body());
                                          }
                                          참고로 Spring5에서는 Rest Client에 RestTemplate 대신해 WebClient를 사용하여 비동기구현을 할 수 있게 되었다. 기존 멀티쓰레드 방식을 버리고 Reactor(WebFlux) 와 함께 스프링 기반 웹서비스를 구현할 경우 그에 따른  성능과 효율 향상은 어마어마 하다. 

                                          모듈 

                                          모듈을 통해 애플리케이션에 필요한 구성 요소만 포함하는 런타임 구성을 사용자 지정할 수 있습니다. 이 사용자 지정은 메모리 공간을 더 적게 사용하며 애플리케이션이 jlink를 사용하여 배포용 사용자 지정 런타임에 정적으로 연결될 수 있게 해줍니다. 메모리 공간을 적게 사용하면 특히 마이크로서비스 아키텍처에서 유용할 수 있습니다.

                                          내부적으로 JVM은 모듈을 활용하여 클래스 로딩을 보다 효율적으로 만들 수 있습니다. 그 결과 런타임이 더 작아지고, 더 가벼워져서 더 빠르게 시작할 수 있습니다. 모듈은 클래스에 필요한 구성 요소를 인코딩하기 때문에 JVM에서 애플리케이션 성능을 개선하기 위해 사용하는 최적화 기법의 효과가 더 좋아질 수 있습니다.

                                          프로그래머의 경우 모듈은 모듈이 내보내는 패키지와 필요한 구성 요소를 명시적으로 선언하고 반사적 액세스를 제한하여 강력한 캡슐화를 적용하는 데 도움이 됩니다. 이 캡슐화 수준을 사용하면 애플리케이션을 더 안전하고 쉽게 유지 관리할 수 있습니다.


                                          프로파일링 및 진단

                                          Java Flight Recorder 

                                          JFR(Java Flight Recorder)은 실행 중인 Java 애플리케이션에서 진단 및 프로파일링 데이터를 수집합니다.  JFR 및 JMC는 Java 8에서 상용 기능이지만 Java 11에서는 둘 다 오픈 소스입니다.

                                          Java Mission Control 

                                          JMC(Java Mission Control)는 JFR(Java Flight Recorder)에서 수집한 데이터를 그래픽으로 표시하고 Java에서는 오픈 소스로 제공됩니다. JFR 및 JMC를 사용하면 메모리 누수, GC 오버헤드, 핫 메서드, 스레드 병목 상태 및 I/O 블로킹과 같은 런타임 문제를 진단할 수 있습니다.

                                          통합 로깅 

                                          Java 11에는 JVM의 모든 구성 요소에 대한 일반적인 로깅 시스템이 있습니다.이 세분화된 로깅은 JVM 충돌에 대한 근본 원인 분석을 수행하고 프로덕션 환경에서 성능 문제를 진단하는 데 유용합니다.

                                          오버헤드가 낮은 힙 프로파일링 

                                          Java 힙 할당을 샘플링하는 데 사용할 수 있는 새 API가 JVMTI(Java Virtual Machine Tool Interface)에 추가되었습니다.JFR 구현에서는 할당이 누락될 수도 있습니다. 반면 Java 11의 힙 샘플링은 라이브 개체와 데드 개체 모두에 대한 정보를 제공할 수 있습니다. APM(애플리케이션 성능 모니터링) 공급업체가 이 새로운 기능을 활용하기 시작 했습니다.

                                          StackWalker 

                                          현재 스레드의 스택에 대한 스냅샷 가져오기는 로깅할 때 주로 사용됩니다.

                                          가비지 수집 

                                          Java 11에서 사용할 수 있는 가비지 수집기는 직렬, 병렬, 가비지 우선 및 엡실론입니다. Java 11의 기본 가비지 수집기는 G1GC(가비지 우선 가비지 수집기)입니다.

                                          ZGC일시 중지 시간을 10ms 미만으로 유지하려고 하는 대기 시간이 짧은 동시 수집기입니다. ZGC는 Java 11에서 실험적 기능으로 사용할 수 있습니다.CMS(Concurrent Mark and Sweep) 수집기는 사용할 수 있지만 Java 9 이후에는 사용되지 않습니다.

                                          엡실론 

                                          엡실론 가비지 수집기는 할당을 처리하지만 메모리를 회수하지는 않습니다. 힙이 소진되면 JVM이 종료됩니다. 엡실론은 수명이 짧은 서비스와 가비지를 사용하지 않는 것으로 알려진 애플리케이션에 유용합니다.

                                          Docker 컨테이너의 향상된 기능 

                                          Java 10 이전에 컨테이너에 설정된 메모리 및 CPU 제약 조건은 JVM에서 인식되지 않았습니다. 예를 들어 Java 8에서 JVM은 최대 힙 크기의 기본값을 기본 호스트의 실제 메모리의 ¼로 설정합니다. Java 10부터 JVM은 컨테이너 제어 그룹(cgroup)에 의해 설정된 제약 조건을 사용하여 메모리 및 CPU 제한을 설정합니다(아래 참고 사항 참조). 예를 들어 기본 최대 힙 크기는 컨테이너의 메모리 제한의 ¼입니다(예: -m2G의 경우 500MB).


                                          다중 릴리스 jar 파일 

                                          Java 11에서 클래스 파일의 여러 Java 릴리스별 버전을 포함하는 jar 파일을 만들 수 있습니다.

                                          성능 향상

                                          JVM 성능향상) 

                                          • JEP 197: Segmented Code Cache[14] - 코드 캐시를 고유 세그먼트로 나눕니다. 이러한 구분은 JVM 메모리 공간을 보다 효율적으로 제어하고, 컴파일된 메서드의 검색 시간을 단축하고, 코드 캐시의 조각화를 크게 줄이고, 성능을 향상시킵니다.

                                          • JEP 254: Compact Strings[15] - 문자 인코딩에 따라 문자열의 내부 표현을 문자당 2바이트에서 문자당 1~2바이트로 변경합니다. 대부분의 문자열은 ISO-8859-1/라틴어-1 문자를 포함하므로 이 변경 내용으로 인해 문자열을 저장하는 데 필요한 공간이 효율적으로 변경됩니다.

                                          • JEP 310: Application Class-Data Sharing[16] - 클래스-데이터 공유는 보관된 클래스가 런타임 시 메모리에 매핑될 수 있게 하여 시작 시간을 줄여줍니다. 애플리케이션 클래스-데이터 공유는 애플리케이션 클래스를 CDS 보관함에 배치할 수 있도록 하여 클래스-데이터 공유를 확장합니다. 여러 JVM이 동일한 보관 파일을 공유하는 경우 메모리가 저장되고 전체 시스템 응답 시간이 단축됩니다.

                                          • JEP 312: Thread-Local Handshakes[17] - 글로벌 VM 세이프포인트를 수행하지 않고 스레드에 대한 콜백을 실행하여 VM이 글로벌 세이프포인트의 수를 줄여 대기 시간을 단축할 수 있게 해줍니다.

                                          • Lazy Allocation of Compiler Threads[18] - VM은 단계별 컴파일 모드에서 다량의 컴파일러 스레드를 시작합니다. 이 모드는 CPU가 여러 개 있는 시스템에서 기본값입니다. 이러한 스레드는 사용 가능한 메모리 또는 컴파일 요청 수에 관계없이 생성됩니다. 스레드는 유휴 상태일 때(거의 모든 시간) 메모리를 사용하므로 리소스를 비효율적으로 사용합니다. 이 문제를 해결하기 위해 시작 시 각 유형의 컴파일러 스레드를 하나씩만 시작하도록 구현이 변경되었습니다. 추가 스레드를 시작하고 사용하지 않는 스레드를 종료하는 것은 동적으로 처리됩니다.

                                          핵심 라이브러리 성능 향상) 

                                          • JEP 193: Variable Handles[19] - 표준을 정의한다는 것은 개체 필드 및 배열 요소, 메모리 정렬의 세부적인 제어를 위한 표준 펜스 작업 세트, 참조된 개체의 강력한 연결성을 유지하기 위한 표준 연결성 펜스 작업에 대한 다양한 java.util.concurrent.atomic 및 sun.misc.Unsafe 작업의 동급 요소를 호출하는 것을 의미합니다.

                                          • JEP 269: Convenience Factory Methods for Collections[20] - 소량의 요소를 사용하여 컬렉션 및 맵 인스턴스를 편리하게 만들 수 있게 해주는 라이브러리 API를 정의합니다. 컬렉션 인터페이스에서 간결하고 수정할 수 없는 컬렉션 인스턴스를 만드는 고정 팩터리 메서드입니다. 이러한 인스턴스는 본질적으로 더 효율적입니다. API는 조밀하게 표시되고 래퍼 클래스가 없는 컬렉션을 만듭니다.

                                          • JEP 285: Spin-Wait Hints[21] - Java에서 스핀 루프에 있음을 런타임 시스템에 암시할 수 있게 해주는 API를 제공합니다. 특정 하드웨어 플랫폼은 스레드가 바쁜 대기(busy-wait) 상태라고 소프트웨어가 알려주면 이점을 얻을 수 있습니다.

                                          • JEP 321: HTTP Client(Standard) [22]- HTTP/2 및 WebSocket을 구현하고 레거시 HttpURLConnection API를 대체할 수 있는 새로운 HTTP 클라이언트 API를 제공합니다.






                                          2020-09-23 11:45:03 에 아래 제목에서 변경 됨 #2

                                          Java 11 (LTS) 로 전환해야 하는 이유

                                          2020-09-23 11:45:03 에 아래 내용에서 변경 됨 #1

                                          다시 자바를 하게 되면서 느낀게, "자바는 꾸준히 발전하고 있는 재밌고 가치있는 언어이다" 같습니다.





                                          Java 11로 전환해야 하는 이유  /  OpenJDK 11 version  정리


                                          API에 대한 눈에 띄는 추가 및 수정 사항이 있으며,
                                          시작, 성능 및 메모리 사용을 개선하는 향상된 기능이 있습니다.

                                          람다 파라미터를 위한 지역변수 표현 

                                          java 10버전에 편리한 var 구문이 생겨난 상황에서, 11버전에서는 람다 파라미터에서  좀 더 명시적으로 var 를 이용 할 수 있게 되었다. 따라서 아래와 같이 어노테이션을 명시할 수 있게 되었다. 

                                          list.stream()
                                              .map((@NotNull var s) -> s.toLowerCase())
                                              .collect(Collectors.toList());

                                          HTTP Client (Standard) 

                                          Non-Blocking request and response 지원 (with CompletableFuture)
                                          Backpressure 지원(java.util.concurrent.Flow 패키지를 통해 Rx Flow를 구현체에 적용)
                                          Factory method 형태로 지원
                                          HTTP/2 지원
                                          HttpClient 예제) 
                                          public void get(String uri) throws Exception {
                                              HttpClient client = HttpClient.newHttpClient();
                                              HttpRequest request = HttpRequest.newBuilder()
                                                    .uri(URI.create(uri))
                                                    .build();
                                          
                                              HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
                                              System.out.println(response.body());
                                          }
                                          참고로 Spring5에서는 Rest Client에 RestTemplate 대신해 WebClient를 사용하여 비동기구현을 할 수 있게 되었다. 기존 멀티쓰레드 방식을 버리고 Reactor(WebFlux) 와 함께 스프링 기반 웹서비스를 구현할 경우 그에 따른  성능과 효율 향상은 어마어마 하다. 

                                          모듈 

                                          모듈을 통해 애플리케이션에 필요한 구성 요소만 포함하는 런타임 구성을 사용자 지정할 수 있습니다. 이 사용자 지정은 메모리 공간을 더 적게 사용하며 애플리케이션이 jlink를 사용하여 배포용 사용자 지정 런타임에 정적으로 연결될 수 있게 해줍니다. 메모리 공간을 적게 사용하면 특히 마이크로서비스 아키텍처에서 유용할 수 있습니다.

                                          내부적으로 JVM은 모듈을 활용하여 클래스 로딩을 보다 효율적으로 만들 수 있습니다. 그 결과 런타임이 더 작아지고, 더 가벼워져서 더 빠르게 시작할 수 있습니다. 모듈은 클래스에 필요한 구성 요소를 인코딩하기 때문에 JVM에서 애플리케이션 성능을 개선하기 위해 사용하는 최적화 기법의 효과가 더 좋아질 수 있습니다.

                                          프로그래머의 경우 모듈은 모듈이 내보내는 패키지와 필요한 구성 요소를 명시적으로 선언하고 반사적 액세스를 제한하여 강력한 캡슐화를 적용하는 데 도움이 됩니다. 이 캡슐화 수준을 사용하면 애플리케이션을 더 안전하고 쉽게 유지 관리할 수 있습니다.


                                          프로파일링 및 진단

                                          Java Flight Recorder 

                                          JFR(Java Flight Recorder)은 실행 중인 Java 애플리케이션에서 진단 및 프로파일링 데이터를 수집합니다.  JFR 및 JMC는 Java 8에서 상용 기능이지만 Java 11에서는 둘 다 오픈 소스입니다.

                                          Java Mission Control 

                                          JMC(Java Mission Control)는 JFR(Java Flight Recorder)에서 수집한 데이터를 그래픽으로 표시하고 Java에서는 오픈 소스로 제공됩니다. JFR 및 JMC를 사용하면 메모리 누수, GC 오버헤드, 핫 메서드, 스레드 병목 상태 및 I/O 블로킹과 같은 런타임 문제를 진단할 수 있습니다.

                                          통합 로깅 

                                          Java 11에는 JVM의 모든 구성 요소에 대한 일반적인 로깅 시스템이 있습니다.이 세분화된 로깅은 JVM 충돌에 대한 근본 원인 분석을 수행하고 프로덕션 환경에서 성능 문제를 진단하는 데 유용합니다.

                                          오버헤드가 낮은 힙 프로파일링 

                                          Java 힙 할당을 샘플링하는 데 사용할 수 있는 새 API가 JVMTI(Java Virtual Machine Tool Interface)에 추가되었습니다.JFR 구현에서는 할당이 누락될 수도 있습니다. 반면 Java 11의 힙 샘플링은 라이브 개체와 데드 개체 모두에 대한 정보를 제공할 수 있습니다. APM(애플리케이션 성능 모니터링) 공급업체가 이 새로운 기능을 활용하기 시작 했습니다.

                                          StackWalker 

                                          현재 스레드의 스택에 대한 스냅샷 가져오기는 로깅할 때 주로 사용됩니다.

                                          가비지 수집 

                                          Java 11에서 사용할 수 있는 가비지 수집기는 직렬, 병렬, 가비지 우선 및 엡실론입니다. Java 11의 기본 가비지 수집기는 G1GC(가비지 우선 가비지 수집기)입니다.

                                          ZGC일시 중지 시간을 10ms 미만으로 유지하려고 하는 대기 시간이 짧은 동시 수집기입니다. ZGC는 Java 11에서 실험적 기능으로 사용할 수 있습니다.CMS(Concurrent Mark and Sweep) 수집기는 사용할 수 있지만 Java 9 이후에는 사용되지 않습니다.

                                          엡실론 

                                          엡실론 가비지 수집기는 할당을 처리하지만 메모리를 회수하지는 않습니다. 힙이 소진되면 JVM이 종료됩니다. 엡실론은 수명이 짧은 서비스와 가비지를 사용하지 않는 것으로 알려진 애플리케이션에 유용합니다.

                                          Docker 컨테이너의 향상된 기능 

                                          Java 10 이전에 컨테이너에 설정된 메모리 및 CPU 제약 조건은 JVM에서 인식되지 않았습니다. 예를 들어 Java 8에서 JVM은 최대 힙 크기의 기본값을 기본 호스트의 실제 메모리의 ¼로 설정합니다. Java 10부터 JVM은 컨테이너 제어 그룹(cgroup)에 의해 설정된 제약 조건을 사용하여 메모리 및 CPU 제한을 설정합니다(아래 참고 사항 참조). 예를 들어 기본 최대 힙 크기는 컨테이너의 메모리 제한의 ¼입니다(예: -m2G의 경우 500MB).


                                          다중 릴리스 jar 파일 

                                          Java 11에서 클래스 파일의 여러 Java 릴리스별 버전을 포함하는 jar 파일을 만들 수 있습니다.

                                          성능 향상

                                          JVM 성능향상) 

                                          • JEP 197: Segmented Code Cache[14] - 코드 캐시를 고유 세그먼트로 나눕니다. 이러한 구분은 JVM 메모리 공간을 보다 효율적으로 제어하고, 컴파일된 메서드의 검색 시간을 단축하고, 코드 캐시의 조각화를 크게 줄이고, 성능을 향상시킵니다.

                                          • JEP 254: Compact Strings[15] - 문자 인코딩에 따라 문자열의 내부 표현을 문자당 2바이트에서 문자당 1~2바이트로 변경합니다. 대부분의 문자열은 ISO-8859-1/라틴어-1 문자를 포함하므로 이 변경 내용으로 인해 문자열을 저장하는 데 필요한 공간이 효율적으로 변경됩니다.

                                          • JEP 310: Application Class-Data Sharing[16] - 클래스-데이터 공유는 보관된 클래스가 런타임 시 메모리에 매핑될 수 있게 하여 시작 시간을 줄여줍니다. 애플리케이션 클래스-데이터 공유는 애플리케이션 클래스를 CDS 보관함에 배치할 수 있도록 하여 클래스-데이터 공유를 확장합니다. 여러 JVM이 동일한 보관 파일을 공유하는 경우 메모리가 저장되고 전체 시스템 응답 시간이 단축됩니다.

                                          • JEP 312: Thread-Local Handshakes[17] - 글로벌 VM 세이프포인트를 수행하지 않고 스레드에 대한 콜백을 실행하여 VM이 글로벌 세이프포인트의 수를 줄여 대기 시간을 단축할 수 있게 해줍니다.

                                          • Lazy Allocation of Compiler Threads[18] - VM은 단계별 컴파일 모드에서 다량의 컴파일러 스레드를 시작합니다. 이 모드는 CPU가 여러 개 있는 시스템에서 기본값입니다. 이러한 스레드는 사용 가능한 메모리 또는 컴파일 요청 수에 관계없이 생성됩니다. 스레드는 유휴 상태일 때(거의 모든 시간) 메모리를 사용하므로 리소스를 비효율적으로 사용합니다. 이 문제를 해결하기 위해 시작 시 각 유형의 컴파일러 스레드를 하나씩만 시작하도록 구현이 변경되었습니다. 추가 스레드를 시작하고 사용하지 않는 스레드를 종료하는 것은 동적으로 처리됩니다.

                                          핵심 라이브러리 성능 향상) 

                                          • JEP 193: Variable Handles[19] - 표준을 정의한다는 것은 개체 필드 및 배열 요소, 메모리 정렬의 세부적인 제어를 위한 표준 펜스 작업 세트, 참조된 개체의 강력한 연결성을 유지하기 위한 표준 연결성 펜스 작업에 대한 다양한 java.util.concurrent.atomic 및 sun.misc.Unsafe 작업의 동급 요소를 호출하는 것을 의미합니다.

                                          • JEP 269: Convenience Factory Methods for Collections[20] - 소량의 요소를 사용하여 컬렉션 및 맵 인스턴스를 편리하게 만들 수 있게 해주는 라이브러리 API를 정의합니다. 컬렉션 인터페이스에서 간결하고 수정할 수 없는 컬렉션 인스턴스를 만드는 고정 팩터리 메서드입니다. 이러한 인스턴스는 본질적으로 더 효율적입니다. API는 조밀하게 표시되고 래퍼 클래스가 없는 컬렉션을 만듭니다.

                                          • JEP 285: Spin-Wait Hints[21] - Java에서 스핀 루프에 있음을 런타임 시스템에 암시할 수 있게 해주는 API를 제공합니다. 특정 하드웨어 플랫폼은 스레드가 바쁜 대기(busy-wait) 상태라고 소프트웨어가 알려주면 이점을 얻을 수 있습니다.

                                          • JEP 321: HTTP Client(Standard) [22]- HTTP/2 및 WebSocket을 구현하고 레거시 HttpURLConnection API를 대체할 수 있는 새로운 HTTP 클라이언트 API를 제공합니다.