파란하늘의 지식창고
Published 2022. 3. 24. 19:39
JDK 18 New Features Study/Java
반응형

JDK의 버전별 변경 사항은 이곳을 참고하세요.

JDK 12 ~ 17 사이 추가된 language specification feature는 이곳을 참고하세요.


Spec

Java SE 18 Platform JSR 393에 정의된 바와 같이 JSR 393 구현이 목표

실제 Spec은 Final Release Specification 문서를 참고해야 함

Final Release Specification Feature Summary

전체 JEP Feature 목록은 OpenJDK의 JDK18 문서로 확인할 수 있다.

Component Feature
core-libs/java.nio.charsets UTF-8 by Default
core/libs/java.net Simple Web Server
tools/javadoc(tool) Code snippets in Java API Documentation
core-libs/java.lang:reflect Reimplement Core Reflection with Method Handles
specification/language Pattern Matching for switch (Second Preview)
core-libs/java.lang Deprecate Finalization for Removal

JEP 400: UTF-8 by Default

표준 Java API의 default charset이 UTF-8로 지정된다.

JEP 408: Simple Web Server

static file만 제공하는 최소한의 web server를 command-line tool로 시작할 수 있게 제공한다.

CGI 또는 servlet과 유사한 기능을 사용할 수 없다.

실 서비스가 아닌 교육 환경에서 prototyping, 임시 코딩 및 테스트 목적에 유용하다.

단순하게 다음과 유사한 형태로 실행하면 된다.

jwebserver -p 9000

JEP 413: Code Snippets in Java API Documentation

API 문서에 예제 소스 코드 포함을 단순화하기 위해  JavaDoc의 표준 Doclet에 @snippet 태그를 도입한다.

API 문서 작성 시 문서 주석에 소스 코드 조각을 포함하는 경우 다음과 같은 형태로 사용하였었다.

<pre>{@code
	lines of source code
}</pre>

pre 태그 @code 사용은 코드 조각에 html 마크업을 포함할 수 없어 일부 텍스트의 강조 표시를 할 수 없고 코드 조각의 유효성을 확인하거나 또는 코드 조각 자체의 주석을 추가하는 등의 더 다양한 기능을 사용하기 어려웠다.

콘텐츠의 종류를 암시적 또는 명시적으로 지정하고 적절한 방식으로 유효성을 검사하고 표시할 수 있도록 하는 메타데이터가 포함된 새 태그로 @snippet이 제공된다.

아래는 다양한 사용 예이다.

inline snippet의 경우 다음과 같다.

/**
 * The following code shows how to use {@code Optional.isPresent}:
 * {@snippet :
 * if (v.isPresent()) {
 *     System.out.println("v: " + v.get());
 * }
 * }
 */

external snippet의 사용의 경우 다음과 같다.

/**
 * The following code shows how to use {@code Optional.isPresent}:
 * {@snippet file="ShowOptional.java" region="example"}
 */


public class ShowOptional {
    void show(Optional<String> v) {
        // @start region="example"
        if (v.isPresent()) {
            System.out.println("v: " + v.get());
        }
        // @end
    }
}

이외에도 hybrid snippet, markup tag, region, highlighting, 표시될 문구 수정, text link, 다른 종류의 file 호출과 같이 다양한 설정을 지원한다.

JEP 416: Reimplement Core Reflection with Method Handles

java.lang.invoke method 처리 위에 java.lang.reflect.Method, Constructor 및 Field가 재 구현되었다.

이는 java.lang.reflect와 java.lang.invoke API에 대해 유지관리 및 개발 비용을 줄여주게 된다.

reflection API를 변경하는 것은 아니며 구현이 변경된 것이다.

JEP 420: Pattern Matching for switch (Second Preview)

switch 구문에 대한 Pattern Matching이 두 번째 미리 보기 기능으로 제공된다.

이전 preview에서 switch 문법에서 label의 type check로 분기 처리가 가능해졌다.

label이 String인지 Integer인지 와 같이 특정 Domain을 기준으로 Pattern Matching이 가능해졌는데 여기에 추가로 constant label에 대한 pattern matching이 추가되었다.

switch(o) {
    case -1, 1 -> ...               // Special cases 
    case Integer i && i > 0 -> ...  // Positive integer cases
    case Integer i -> ...           // All the remaining integers
    default -> 
}

여기에 더불어 새로 추가된 문법인 sealed, permits를 통한 확장 class에 대한 type check에 대한 처리가 보강되었다.

sealed interface I<T> permits A, B {}
final class A<X> implements I<String> {}
final class B<Y> implements I<Y> {}

static int testGenericSealedExhaustive(I<Integer> i) {
    return switch (i) {
        // Exhaustive as no A case possible!  
        case B<Integer> bi -> 42;
    }
}

위와 같이 A, B를 허용하는 interface I에 대해 switch 구문의 type check가 들어가는 경우 B만 체크하고 있기 때문에 A가 필요하다는 문법 강조가 표시되게 된다.

JEP 421: Deprecate Finalization for Removal

기존의 경우 try catch의 final 구문을 통해 resouce close 처리를 하였다.

FileInputStream  input  = null;
FileOutputStream output = null;
try {
    input  = new FileInputStream(file1);
    output = new FileOutputStream(file2);
    ... copy bytes from input to output ...
    output.close();  output = null;
    input.close();   input  = null;
} finally {
    if (output != null) output.close();
    if (input  != null) input.close();
}

이 코드는 copy 시 예외가 발생하면 output.close()를 수행하고 exception이 발생하면 final에서 output.close()가 실행된다.

이러한 Finalization은 Java 1.0에 도입된 구문인데 이는 근본적으로 몇 가지 중요한 결함이 있다.

  • 예측할 수 없는 대기시간 - object에 연결할 수 없게 되는 순간과 close가 호출되는 순간 사이에 임의의 긴 시간이 걸릴 수 있다. GC는 종료자가 호출된다는 보장을 제공하지 않는다.
  • 제약 없는 behavior -  finalizer code는 모든 작업을 수행할 수 있다. 특히 완료되는 object에 대한 참조를 저장할 수 있으므로 object를 부활시키고 다시 한번 연결할 수 있다.
  • 항상 활성화됨 - finalizer는 명시적인 등록 메커니즘이 없다. finalizer가 있는 class는 필요 여부에 관계없이 class의 모든 instance에 대한 finalization을 가능하게 한다. 해당 object에 더 이상 필요하지 않은 경우에도 object의 finalizer는 취소할 수 없다.
  • 지정되지 않은 threading - finalizer는 지정되지 않은 thread에서 임의의 순서로 실행된다. threading이나 순서를 제어할 수 없다.

위의 결함은 다음과 같은 문제를 발생시킨다.

  • 보안 취약성
  • 성능
  • 신뢰할 수 없는 실행
  • 어려운 프로그래밍 모델

따라서 이에 대해 대체할 수 있는 try-with-resources 구문, Cleaner 같은 대체 기술을 사용해야 한다.

finalizer를 통한 close 처리는 오랜 기간 사용되어 왔으므로 제거를 하기 위해서는 오랜 전환 기간이 예상된다.

따라서 향후 버전에서는 종료자를 사용하는 경우 런타임에 경고를 발생하고, 기본적으로 종료를 비활성화하고 --finalization=enabled와 같은 옵션을 제공할 예정이다.

 

반응형
profile

파란하늘의 지식창고

@Bluesky_

도움이 되었다면 광고를 클릭해주세요