What is new in Java 8-13

Myeon·2020년 11월 17일
1
post-thumbnail

java8이 2014년, 3년만에 출시되었다.

오라클 인수 후 첫번째 버전으로, java9부터는 6개월마다 릴리즈를 발표하겠다고 선언(발전을 위해)하면서 특정 버전만 장기간 지원(Long-term support; LTS)한다고 밝혔다.

현재 java11이 첫번째 LTS버전이다.

java7

간단하게 살펴보면 java7에서는 아래 기능이 변화하였다. (우리가 지금 그냥 당연하게 사용하는 것들)

  1. 다이아몬드 연산자(<l;>) 사용

  2. Generics 사용성 개선

  3. 리소스 자동 해제

  4. Garbage Collector 기능 개선 - GCG1

  5. Switch문 문자열 지원

java8

JAVA8에서는 조금 큰 변화가 있었다고 할 수 있는데, 다들 알고있는 람다식이 이 버전에 포함된다.

  1. 람다 표현식(lambda expression) : 함수형 프로그래밍

    1-1. 메소드 참조(Method Reference)

  2. 스트림 API(stream API) : 데이터의 추상화

  3. java.time 패키지 : Joda-Time을 이용한 새로운 날짜와 시간 API

  4. 나즈혼(Nashorn) : 자바스크립트의 새로운 엔진

    • Serial/SerialOld GC는 Java 8부터 Deprecated

1. lambda expression

  (매개변수, ...) -> { 실행문 ... }    
new Thread(new Runnable() {
         public void run() {
            System.out.println("전통적인 방식의 일회용 스레드 생성");
         }
      }).start();
new Thread()->{
         System.out.println("람다 표현식을 사용한 일회용 스레드 생성");
      }).start();
  간단히 말해 메소드를 하나의 식으로 표현한 것

  식별자 없이 실행할 수 있는 함수 표현식(익명함수 라고도 부른다.)



  메소드를 이렇게 람다 표현식으로 표현하면 클래스를 만들고 객체를 생성하지 않아도 메소드를 사용할 수 있음.

  이러한 람다 표현식은 기존의 불필요한 코드를 줄여주고, 작성된 코드의 가독성을 높이는 데 그 목적이 있다.

  

1.1 Method reference

  메소드 참조method reference는 이미 이름이 있는 메서드를 대상으로 한 람다식의 간략형이며, 메소드 참조를 나타내는 예약어로서 (::)를 사용

  메소드 참조의 예와 그에 대응하는 람다식은 아래. 왼쪽이 메소드 참조, 오른쪽이 람다식이다.

  

  String::valueOf     x -> String.valueOf(x)

  Object::toString    x -> x.toString()

  x::toString         () -> x.toString()

  ArrayList::new      () -> new ArrayList<>()

  List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);    

  //기존
  for (int number : numbers) {
     System.out.println(number);
  }   

  //메소드참조를 사용하여 작성하면,
  numbers.forEach(System.out::println); 

2. StreamAPI

  자바에서는 많은 양의 데이터를 저장하기 위해서 배열이나 컬렉션을 사용

  또한, 이렇게 저장된 데이터에 접근하기 위해서는 반복문이나 반복자(iterator)를 사용하여 매번 코드를 작성



  이러한 문제점을 극복하기 위해서 도입된 방법이 바로 스트림(stream) API

  컬렉션, 배열등의 저장 요소를 하나씩 참조하며 함수형 인터페이스(람다식)를 적용하며 반복적으로 처리할 수 있도록 해주는 기능

  

  Stream 은 하나의 source로부터 제공받은 요소들의 연속체. 그리고 stream은 집계 연산을 지원

  Stream 은 요소들의 연속체에 대한 인터페이스를 제공. 하지만 요소들을 실제로 보관하지 않고 계산하는데만 사용.

  Stream 은 SQL 과 함수형 프로그래밍 언어의 집계 연산을 제공. (filter, map, reduce, find, match, sorted, forEach 등)

  또한 Stream 은 병렬 처리도 가능
List<String> names = Arrays.asList("one", "two", "three", "four");
 
      // 기존의 코딩 방식
      long count = 0;
 
      for (String name : names) {
         if (name.contains("o")) {
            count++;
         }
      }
      System.out.println("Count : " + count); // 2
       
      // 스트림 이용한 방식
      count = 0;
      count = names.stream().filter(x -> x.contains("o")).count();
      System.out.println("Count : " + count); // 2

3. java.time 패키지

  기존에 있던 Date, Calendar 클래스는 여러 문제점이 있었음.

  이를 개선하기 위해 Joda-Time 라이브러리를 발전시킨 새로운 날짜와 시간 API인 java.time 패키지를 제공

  다양한 기능을 지원하는 다수의 하위 패키지를 포함

여러 기능들을 살펴보면 java8은 병렬처리에 적합한 구조로 진화했다고 한다.

Java8 의 주특징이 Lambda 와 Stream 을 중심의 함수형 프로그래밍 도구들이었다면, Java9 의 가장 특징적인 부분 중 하나는 모듈(Module) 의 등장이다.

Java9

  1. JShell

  2. Immutable List, Set, Map

  3. private 구현체 추가

  4. module system (Java Jigsaw project)

1. JShell

  이제 Java를 별도의 컴파일 과정이나 main 함수 작성을 위한 Project Structure 의 구성없이 작동시킬 수 있는 REPL(Read-Eval-Print-Loop) 도구인 JShell 이 제공된다.

2. Immutable List, Set, Map

  불변의 List, Set, Map 을 만들어 주는 편리한 신규 팩토리 메서드제공

  of : 비어있거나, 비어있지 않은 list,set,map을 만들어 준다.      
      List<String> immutableList = List.of("one", "two", "three", null);
      immutableList.add("four");
      null이거나, add/put을 하면 error 발생

3. private 구현체 추가

  java8에서 default method , static method를 제공했지만 특정 기능을 처리하는 내부method 일뿐인데도 외부에 공개되는 public method로 만들었어야 했다.

  Java9에서는 인터페이스 private 메서드를 제공한다. 이제 Interface 구현시에도 외부에 공개할 필요없는 method 를 생성함으로써 캡슐화를 유지할 수 있다.

  

4. module system

  SE 플랫폼과 JDK를 작은 컴퓨터 디바이스에 보다 쉽게 경량화(scalable down)할 수 있게 한다.

  Java SE 플랫폼의 전반적인 구현 부분과 특히 JDK 부분의 보안성과 유지관리성(maintainability)을 향상시킨다.

  애플리케이션의 성능을 높일 수 있게 하고 개발자들이 라이브러리와 애플리케이션 구성과 유지를 쉽게 만들어 준다.

  Jigsaw의 주요 목표는 한마디로 유연한 런타임 이미지를 만들 수 있도록 Java 플랫폼을 모듈화 하는 것

  포함된 package 의 컬렉션 각각에 대해 필요한 곳과 불필요한 곳을 적절히 정의하고 분류(jar와 다른 점)    
    module sample {
         exports com.myproject.module;
         requires commons;
      }
 
      module commons {
         requires java.base;
         requires java.xml;
      }

java10

  1. Local-variable type inference

  2. Application Class-Data Sharing

  3. Parallel Full GC for G1

1. Local-variable type inference

  var를 사용하여 생성할 변수의 타입을 추론할 수 있는 기능

  변수를 생성할 때, 앞쪽에 변수의 타입을 지정하고 뒤에서 생략하는 방식(<>)으로 java7에서 변경되었다면, 10에서는 var를 통해 지역변수에 대해서는 Type을 명시해주지 않아도 됨.
      //Java 6 or earlier jvm version
      List<String> list = new ArrayList<String>();
 
      //Java 7 or later jvm version
      List<String> list = new ArrayList<>();
 
      //Java 10
      var list = new ArrayList<String>();
      var stream = list.stream();

2. Application Class-Data Sharing

  Class-Data Sharing(CDS)는 Java 5에서 소개

  JVM 기동시의 성능을 향상하거나, 여러 대의 JVM이 하나의 물리 장비 또는 가상 장비에서 돌아가는 경우, 자원에 미치는 영향을 줄이기 위해 개발된 기능

  CDS는 JVM에서 공통으로 사용하는 클래스들을 공유하는 저장소에 위치시키고 이를 공유해서 사용하는 방식으로 제공 (.jsa 파일)

  

3. Parallel Full GC for G1

  Full GC를 병렬로 만들어, G1의 worst-case latency를 개선하기 위한 기능

  전체 Collection을 피하고자 jdk 9의 GC는 G1을 기본으로 하고 있지만, 빠르게 메모리를 회수할 수 없는 경우, 전체 GC가 하락하는 문제가 있었음.

  이전까지는 단일 쓰레드로 GC를 수행하였다면, java10 부터는 병렬로 Mark-Sweep-Compact를 수행

  

java11(첫번째 LTS버전)

  1. Local-Variable Syntax for Lambda Parameters

  2. HTTP Client (Standard)

  3. ZGC: A Scalable Low-Latency Garbage Collector (Experimental)

  4. Launch Single-File Source-Code Programs

1. Local-Variable Syntax for Lambda Parameters

  var를 람다 표현식을 쓰는 경우에, 전달되는 parameter들의 타입을 추론할 수 있는 기능 추가     
       list.stream()
      .map((@NotNull var s) -> s.toLowerCase()) //string으로 추론
      .collect(Collectors.toList());

2. HTTP Client (Standard)

  java.net.http 패키지로 표준화

  - Non-Blocking request and response 지원 (with CompletableFuture)

  - HTTP/2 지원

  - Factory method 형태로 지원

  

  HttpClient.newHttpClient();와 같은 형태로 일반적인 형태의 HttpClient를 제공받을 수도 있고,

  HttpClientBuilder를 통해서 HTTP 버전 및 Redirect 여부, Proxy, Authenticator 등을 설정하여 인스턴스를 생성할 수 있음.

  

3. ZGC: A Scalable Low-Latency Garbage Collector (Experimental)

  11에서 등장한 가비지 콜렉터



  - GC 일시 중지 시간은 10ms를 초과하지 않는다.

  - 작은 크기(수백 메가) ~ 매우 큰 크기(수 테라) 범위의 힙을 처리

  - G1에 비해 애플리케이션 처리량이 15%이상 감소하지 않는다.

  - JVM으로 구동되는 애플리케이션의 경우, GC가 동작할 때 애플리케이션이 멈추는 현상(Stop-The-World)을 줄이거나 없앰으로써 애플리케이션의 성능향상에 기여할 수 있습니다.



  ZGC의 주요 원리는 Load barrier와 Colored object pointer를 함께 사용. 이를 통해 Java의 애플리케이션 스레드가 동작하는 중간에, ZGC가 객체 재배치 같은 작업을 수행할 수 있게 해준다.

4. Launch Single-File Source-Code Programs

  single file 프로그램의 main method 실행시 javac를 사용하지 않고 바로 실행할 수 있도록 편의성 향상.

  javac+java를 수행하거나 java자체적으로 실행하여 코드를 컴파일하고 자동 실행할 수 있음. class파일 생성x

java12

  1. Shenandoah: A Low-Pause-Time Garbage Collector (Experimental)

  2. Default CDS Archives

  3. Abortable Mixed Collections for G1

  4. Promptly Return Unused Committed Memory from G1

1. Shenandoah: A Low-Pause-Time Garbage Collector (Experimental)

  Shenandoah라는 이름의 GC(Garbage Collector) 알고리즘이 새로 추가.

  실행 중인 Java 쓰레드와 동시에 GC를 실행하여 GC 중지 시간을 단축하는 알고리즘으로. 힙 크기와는 무관하게 동일한 중지 시간을 유지

  이 알고리즘은 처리량과 메모리 공간의 효율성보다는 응답성에 초점

  

2. Default CDS Archives

  JDK 빌드 프로세스를 개선하여 CDS(Class Data Sharing) 아카이브를 생성

  사용자가 직접 실행할 필요 없이, -Xshare:dump 옵션을 통해서 CDS를 사용할 수 있음.

  또한, JDK 11의 VM에는 -Xshare:auto가 기본적으로 사용되도록 설정되어 있기때문에 CDS의 이점을 사용할 수 있음.

  

3. Abortable Mixed Collections for G1

  GC(Garbage Collection) 중 하나인 G1이, 효율적으로 동작하도록 하기 위해 중단 가능한 Collection을 가지도록 변경

  GC가 발생할 경우, STW(Stop The World)라는 이름의 동작으로 불필요한 데이터들을 수집할 수 있는 시간을 가지는데, 정해진 시간 내에 불필요한 객체들을 수집하지 못할 경우, GC를 중단할 수 있음.



  GC 대상을 80%의 필수 대상(Mandatory)과 20%의 선택적 대상(Optional)으로 나눈 뒤, 우선적으로 필수적인 부분에서 수집을 진행.

  이후 남은 시간에 선택적 부분에서 수집을 진행하되, 남아있는 정지시간에 선택적 부분을 수집하지 못하리라 판단하면, 이를 다음 GC 시간의 선택적 부분으로 넘기게 됨.

4. Promptly Return Unused Committed Memory from G1

  G1의 개선건. GC가 활성화된 상태일때 Java의 힙 메모리를 운영체제에 반환하도록 하는 내용

  현재 G1은 Full GC가 일어나거나 Concurrent cycle이라는 상황에만 Java의 힙 메모리를 운영체제에 반환

  보통은 Concurrent cycle만 해당 반환작업을 일으킬 수 있는데, 외부에서 강제하지 않는 한 대부분의 경우에는 힙 메모리를 반환하지 않음. 이 문제에 대한 개선

  

java13

  1. Dynamic CDS Archives

  2. ZGC: Uncommit Unused Memory (Experimental)

  3. Reimplement the Legacy Socket API

  4. Switch Expressions (Second Preview)

  5. Text Blocks (Preview)

1. Dynamic CDS Archives

Java 애플리케이션 실행이 종료될 때 CDS가 동적으로 작동하도록 향상되었다.

사용성을 개선하고 Default CDS Archives에는 없는, 로드된 애플리케이션의 클래스와 라이브러리 클래스를 포함하도록 개선

애플리케이션의 첫 실행에서 자동 아카이브 생성을 수행. 이는 CDS/AppCDS의 사용을 자동화

2. ZGC: Uncommit Unused Memory (Experimental)

ZGC가 오랫동안 사용하지 않은 heap 메모리를 운영체제로 돌려주지 않는 문제가 있었는데, 이번에 수정됐다.

ZGC는 JDK11부터 실험적으로 도입된 GC

ZPage라는, page cache 내의 사용되지 않는 메모리 집합을 정해진 정책에 따라 커밋 해제하여 OS로 반환하되, 최소 힙 크기(-Xms) 아래로는 줄어들지 않도록 지정. (-Xms와 -Xmx가 동일한 경우, 이 기능이 암시적으로 비활성화)

새 옵션을 추가하지 않고 GC가 일어나는 빈도에 기초하여 메모리 해제 주기를 설정할 수도 있다.

3. Reimplement the Legacy Socket API

레거시 소켓 API를 재구현

SocketImpl은 레거시 SPI 메커니즘이며, 새로운 구현에서 해당하지 않은 경우에는 이전 구현을 모방하여 호환되도록 동작

Timeout(connect, accept, read)을 사용하는 소켓 연산자를, non-blocking 모드로 변경하고 소켓을 polling 하여 구현

PlainSocketImpl.getINputStream()으로 반환된 InputStream과 OutputStream이 각각 java.io.FileInputStream.과 java.io.FileOutputStream을 extend

*SPI(Service Provider Interface): 플러그인 형태로 제공하는 인터페이스. 인터페이스만 정의하고 각 구현은 가져다 사용하는 벤더에서 구현하도록 함. 예) Java Cryptography Extension_

4. Switch Expressions (Preview)

12에서도 Preview 였는데 13에서도 Preview.

Preview 이므로 --enable-preview 옵션을 줘야 사용할 수 있는 기능

Arrow labels : 대신 ->를 사용할 수 있다

static void howMany(int k) {
    switch (k) {
        case 1  -> System.out.println("one");
        case 2  -> System.out.println("two");
        default -> System.out.println("many");
    }
}

expression : switch가 expression으로 사용될 수 있다. 즉, 다음과 같이 변수 할당을 할 수 있다

T result = switch (arg) {
    case L1 -> e1;
    case L2 -> e2;
    default -> e3;
};

Yielding a value : yield 키워드가 추가

int result = switch (s) {
    case "Foo":
        yield 1;
    case "Bar":
        yield 2;
    default:
        System.out.println("Neither Foo nor Bar, hmmm...");
        yield 0;
};

switch 표현식 내부에서 생성된 특정 값을 반환
JDK12에서 나왔던 break value; 표현식이 yield value;로 대체
return value;가 제어권이 함수 호출자나 생성자에게 있었다면, yield value;는 스위치 표현식에게 제어권을 전달

5. Text Blocks (Preview)

JDK15 preview

다른 언어에서도 등장하는 Text block이 Java에도 추가된다. 기존에 여러 줄의 텍스트를 사용할 때, +와 new line으로 연결해주었다면 이 제안에서는 """을 통해 multi line으로 텍스트를 입력할 수 있도록 제안한다.

Java에서도 1차원 문자 시퀀스가 아니라 2차원 텍스트 블록을 사용할 수 있다.

SQL example (as-is)

String query = "SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`\n" +
               "WHERE `CITY` = 'INDIANAPOLIS'\n" +
               "ORDER BY `EMP_ID`, `LAST_NAME`;\n";

SQL example (to-be)

String query = """
               SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`
               WHERE `CITY` = 'INDIANAPOLIS'
               ORDER BY `EMP_ID`, `LAST_NAME`;
               """;

1개의 댓글

comment-user-thumbnail
2021년 2월 11일

잘 보고 가요:_)

답글 달기