자바 10은 23년의 역사에서 가장 빠른 자바 버전입니다. 자바는 성장과 진화가 느리다는 비판을 받아왔지만, 자바 10은 이 개념을 완전히 뒤엎었습니다. 자바 10은 미래 지향적인 변화가 많이 이루어진 릴리스로, 그 범위와 영향력은 분명하지 않지만 멀리 미치는 것입니다. 이 기사에서는 자바 10 릴리스에 추가된 다양한 기능에 대해 논의할 것입니다. 그 전에, 자바 릴리스 모델에 도입된 몇 가지 변경 사항을 알아보겠습니다.
장기 지원 모델
2017년부터 오라클과 자바 커뮤니티는 자바를 위해 새로운 6개월 주기를 도입했습니다. Oracle Java SE 제품에 대해 장기 지원(LTS) 모델로 전환되었습니다. 이것은 무엇을 의미합니까? 제품의 LTS 버전은 오라클로부터 우수한 지원을 받게 되며, 3년마다 목표로 하고 있습니다. 각 자바 릴리스는 하나 또는 두 가지 주요 기능을 기반으로 구성되며, 이러한 기능들이 릴리스를 주도합니다. 어떠한 장애물이 있으면 릴리스는 연기되고 시장에 출시가 늦어집니다. 자바 9의 주요 기능인 프로젝트 지그소는 릴리스 일정을 몇 차례 밀어냈고, 릴리스가 1.5년 이상 지연되었습니다. 6개월 주기 릴리스는 릴리스 기차를 따를 것입니다. 릴리스 기차는 매 6개월마다 일정이 있습니다. 선택된 기능들은 기차에 탑승하게 되며, 그렇지 않은 경우 다음 예정된 기차를 기다리게 됩니다.
오라클 JDK 대 오픈 JDK
개발자 친화적인 환경을 위해 오라클 및 자바 커뮤니티는 이제 오픈 JDK 이진 파일을 주요 JDK로 전환하고 있습니다. 이는 이전에 JDK 이진 파일이 오라클에 의해 소유되고 라이선스가 부여되었던 시절에 비해 큰 안도감을 제공합니다. 그때는 JDK 이진 파일의 재배포에 관한 다양한 제한이 있었습니다. 오라클은 그들의 JDK를 계속해서 생산할 것이지만, 장기 지원 릴리스만 대상으로 할 것입니다. 이는 더 많은 클라우드 및 컨테이너 친화적인 방향으로의 이동입니다. 오픈 JDK 이진 파일은 컨테이너의 일부로 배포될 수 있기 때문입니다. 이것이 의미하는 바는 무엇인가요? 오픈 JDK 이진 파일은 매 6개월마다 릴리스될 것이고, 오라클 JDK 이진 파일은 3년마다 릴리스될 것입니다 (LTS 버전). 어떤 JDK 이진 파일이 채택될 것인가요? 대규모 기관들은 버전 간 이동에 시간이 걸립니다; 그들은 가능한 한 버전에 집착합니다. Java 6의 산업 채택은 Java 7보다 더 많았고, 그 후 산업은 점차 Java 8로 이동하고 있습니다. 제 의견으로는, LTS 버전이 기업들에 의해 가장 선호될 것입니다. 그러나 그것이 오라클 JDK의 LTS 버전인지 오픈 JDK인지는 아직 알 수 없습니다. 부분적으로 클라우드 공간에서 많은 일이 벌어지고 있기 때문입니다. Java 9 및 10은 비-LTS 릴리스입니다. 2018년 9월에 예정된 Java 11은 LTS 릴리스가 될 것입니다.
Java 10 기능
Java 10에서 제공되는 기능들을 간단히 살펴보겠습니다.
시간 기반 릴리스 주기의 채택으로 인해 Oracle은 Java SE 플랫폼 및 JDK의 버전 문자열 체계 및 관련 버전 정보를 현재 및 향후 시간 기반 릴리스 모델에 맞게 변경했습니다. 새로운 버전 번호의 패턴은: $FEATURE.$INTERIM.$UPDATE.$PATCH
$FEATURE: 카운터는 6개월마다 증가하며 기능 릴리스 버전을 기반으로 합니다. 예: JDK 10, JDK 11. $INTERIM: 카운터는 호환되는 버그 수정 및 향상 사항이 포함된 비기능 릴리스에 대해 증가합니다. 그러나 호환되지 않는 변경 사항은 없습니다. 일반적으로 이 값은 0이며 6개월 동안 중간 릴리스가 없을 것으로 예상됩니다. 이는 릴리스 모델의 미래 개정을 위해 유지됩니다. $UPDATE: 카운터는 보안 문제, 회귀 및 새로운 기능의 버그를 수정하는 호환되는 업데이트 릴리스에 대해 증가합니다. 이것은 기능 릴리스 후 1개월 후에 업데이트되며 그 후로는 매 3개월마다 업데이트됩니다. 2018년 4월 릴리스는 JDK 10.0.1이며 7월 릴리스는 JDK 10.0.2이며 이와 같이 계속됩니다. $PATCH: 카운터는 심각한 문제를 해결하기 위한 긴급 릴리스에 대해 증가합니다. 새로운 API가 이러한 카운터 값을 프로그래밍 방식으로 가져올 수 있습니다. 이제 Java 런처를 살펴보겠습니다;
Version version = Runtime.version();
version.feature();
version.interim();
version.update();
version.patch();
이제 Java 런처를 살펴보겠습니다. 이것은 버전 정보를 반환합니다:
$ java -version
java version "10" 2018-03-20
Java(TM) SE Runtime Environment 18.3 (build 10+46)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10+46, mixed mode)
버전 번호 형식은 “10”입니다. 다른 카운터가 0이 아닌 경우가 없기 때문입니다. 릴리스 날짜가 추가되었습니다. 18.3은 2018년 3월의 빌드 10+46을 나타냅니다. 가상의 JDK 10.0.1 빌드 93의 경우 빌드는 10.0.1+939가 될 것입니다. ### 로컬 변수 유형 추론 (JEP 286)
Local-Variable Type Inference는 개발자들에게 Java 10에서 가장 큰 새로운 기능입니다. 이것은 초기화된 지역 변수의 선언에 타입 추론을 추가합니다. 지역 타입 추론은 다음 시나리오에서만 사용할 수 있습니다:
- 초기화 프로그램이 있는 지역 변수에 대해 제한됩니다
- 향상된 for 루프 또는 인덱스의 색인
- for 루프에 선언된 로컬
사용 방법을 살펴보겠습니다:
var numbers = List.of(1, 2, 3, 4, 5); // inferred value ArrayList
// 향상된 For 루프의 인덱스
for (var number : numbers) {
System.out.println(number);
}
// 루프에서 선언된 지역 변수
for (var i = 0; i < numbers.size(); i++) {
System.out.println(numbers.get(i));
}
자세한 내용은 java 10 지역 변수 타입 추론에서 확인할 수 있습니다.13. ### 실험적인 Java 기반 JIT 컴파일러 (JEP 317)
이 기능은 Java 기반의 JIT 컴파일러인 Graal을 Linux/x64 플랫폼에서 실험적 JIT 컴파일러로 사용할 수 있게 합니다. 이것은 Java 10 기능 목록 중 가장 미래 지향적인 포함입니다. Graal은 Java 9에서 소개되었습니다. 이는 우리가 사용해 온 JIT 컴파일러에 대한 대안입니다. 이는 JVM의 플러그인이며, JIT 컴파일러가 JVM에 묶이지 않고 동적으로 플러그인을 연결하고 다른 JVMCI(Java-Level JVM Compiler Interface) 호환 플러그인으로 대체할 수 있음을 의미합니다. 또한 Java 세계에서 Ahead of Time (AOT) 컴파일레이션을 지원하며 polyglot 언어 해석도 지원합니다. “Java 바이트 코드를 머신 코드로 변환하기 위한 Java 기반의 Just in Time Compiler”라고 표현되어 있습니다. 헷갈리시나요? 만약 JVM이 Java로 작성되었다면, JVM을 실행하기 위해 JVM이 필요하지 않을까요? JVM은 AOT로 컴파일될 수 있으며 그 후에 JIT 컴파일러는 라이브 코드 최적화를 통해 성능을 향상시키기 위해 JVM 내에서 사용될 수 있습니다. Graal은 Java에서 JIT 컴파일러를 처음부터 완전히 다시 작성한 것입니다. 이전 JIT 컴파일러는 c++로 작성되었습니다. 이는 어떤 프로그래밍 언어의 최종 진화 단계 중 하나로 간주됩니다. Graal로 전환하려면 다음 JVM 매개변수를 사용할 수 있습니다:
-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler
Graal에 대해 더 자세히 알아보려면 Chris Seaton의 프레젠테이션에서 확인할 수 있습니다.
이 기능은 시작 풋프린트를 향상시키며 기존의 Class-Data Sharing (“CDS”) 기능을 확장하여 응용 프로그램 클래스를 공유 아카이브에 배치할 수 있게 합니다. JVM은 시작할 때 몇 가지 예비 단계를 수행하는데, 이 중 하나는 메모리에 클래스를 로드하는 것입니다. 여러 JAR 파일에 여러 클래스가 포함된 경우 첫 번째 요청의 지연이 명백하게 나타납니다. 이는 부팅 시간이 중요한 서버리스 아키텍처에서 문제가 됩니다. 응용 프로그램 시작 시간을 단축하려면 응용 프로그램 클래스 데이터 공유를 사용할 수 있습니다. 아이디어는 다양한 Java 프로세스 간에 공통 클래스 메타데이터를 공유하여 풋프린트를 줄이는 것입니다. 이를 다음 3단계로 달성할 수 있습니다: 아카이브할 클래스 결정: Java 런처를 사용하여 아카이브할 파일 목록을 생성하려면 다음 매개변수를 사용하십시오:
$java -Xshare:off -XX:+UseAppCDS -XX:DumpLoadedClassList=hello.lst -cp hello.jar HelloWorld
AppCDS 아카이브 생성: Java 런처를 사용하여 응용 프로그램 CDS에 사용할 파일 목록의 아카이브를 생성하려면 다음 매개변수를 사용하십시오:
$java -Xshare:dump -XX:+UseAppCDS -XX:SharedClassListFile=hello.lst -XX:SharedArchiveFile=hello.jsa -cp hello.jar
AppCDS 아카이브 사용: Java 런처를 다음 매개변수로 사용하여 응용 프로그램 CDS를 사용하십시오.
$java -Xshare:on -XX:+UseAppCDS -XX:SharedArchiveFile=hello.jsa -cp hello.jar HelloWorld
G1 가비지 컬렉터는 JDK 9에서 기본값으로 설정되었습니다. G1 가비지 컬렉터는 전체 가비지 컬렉션을 피합니다. 그러나 수집을 위한 동시 스레드가 메모리를 충분히 빠르게 회복하지 못할 때 사용자 경험이 영향을 받습니다. 이 변경으로 인해 전체 GC가 병렬로 수행되므로 G1 최악의 경우 지연 시간이 개선됩니다. G1 컬렉터의 마크-스위프트-컴팩트 알고리즘이 병렬로 수행되며 동시 수집 스레드가 메모리를 충분히 빠르게 회복할 수 없을 때 트리거됩니다.25. ### Garbage-Collector Interface (JEP 304)
이 JEP는 미래지향적인 변경 사항입니다. 이는 공통 가비지 컬렉터 인터페이스를 도입하여 다양한 가비지 컬렉터의 코드 격리를 개선합니다. 이 변경으로 인해 내부 GC 코드의 모듈성이 향상되며 기존 코드를 변경하지 않고 새로운 GC를 추가하는 데 도움이 될 것입니다. 또한 이전 GC의 제거나 housekeeping에도 도움이 될 것입니다.26. ### Additional Unicode Language-Tag Extensions (JEP 314)
이 기능은 java.util.Locale 및 관련 API를 향상시켜 BCP 47 언어 태그의 추가 유니코드 확장을 구현합니다. Java SE 9에서 지원되는 BCP 47 U 언어 태그 확장은 “ca”와 “nu”입니다. 이 JEP는 다음과 같은 추가 확장을 지원할 것입니다:
- cu (통화 유형)
- fw (주의 첫 번째 날)
- rg (지역 재정의)
- tz (시간대)
이러한 추가 확장 기능을 지원하기 위해 다양한 API가 변경되어 U 또는 추가 확장에 기반한 정보를 제공하도록 수정되었습니다.
java.text.DateFormat::get*Instance
java.text.DateFormatSymbols::getInstance
java.text.DecimalFormatSymbols::getInstance
java.text.NumberFormat::get*Instance
java.time.format.DateTimeFormatter::localizedBy
java.time.format.DateTimeFormatterBuilder::getLocalizedDateTimePattern
java.time.format.DecimalStyle::of
java.time.temporal.WeekFields::of
java.util.Calendar::{getFirstDayOfWeek,getMinimalDaysInWeek}
java.util.Currency::getInstance
java.util.Locale::getDisplayName
java.util.spi.LocaleNameProvider
OpenJDK를 촉진하고 커뮤니티 사용자에게 더 매력적으로 만들기 위해이 기능은 JDK에 기본 루트 인증 기관 (CA) 인증서 세트를 제공합니다. 이것은 Oracle 및 Open JDK 바이너리가 기능적으로 동일하다는 것을 의미하기도 합니다. TLS와 같은 중요한 보안 구성 요소는 앞으로 OpenJDK 빌드에서 기본적으로 작동할 것입니다.30. ### Thread-Local Handshakes (JEP 312)
이것은 성능을 향상시키기 위한 내부 JVM 기능입니다. 핸드셰이크 작업은 스레드가 안전 지점 상태에 있는 동안 각 JavaThread에 대해 실행되는 콜백입니다. 콜백은 해당 스레드 자체 또는 VM 스레드에 의해 스레드를 차단 상태로 유지하면서 실행됩니다. 이 기능은 전역 VM 안전 지점을 수행하지 않고 스레드에 콜백을 실행하는 방법을 제공합니다. 개별 스레드를 중지하고 모든 스레드 또는 아무것도 중지하지 않는 것만이 아니라 가능하고 저렴하게 만듭니다.31. ### 대체 메모리 장치에 대한 힙 할당 (JEP 316)
이것은 JDK에서 javah 도구를 제거하는 정리 작업입니다. 이 도구 기능은 JDK 8의 일부로 javac
에 추가되어 컴파일 시에 네이티브 헤더 파일을 작성할 수 있게 하여 javah
를 사용하지 않도록 만듭니다.
여러 해 동안 JDK 코드베이스를 위한 다양한 Mercurial 저장소가 존재해 왔습니다. 다양한 저장소는 어떤 이점을 제공하기는 하지만 다양한 운영적인 단점도 있었습니다. 이 변경의 일환으로 JDK Forest의 다양한 저장소가 개발을 단순화하고 효율화하기 위해 하나의 저장소로 통합됩니다.
Java 10은 API를 추가하고 제거했습니다 (오타가 아닙니다). Java 9에서는 향후 릴리스에서 제거될 API를 표시하는 향상된 사용 중지 기능을 도입했습니다. 제거된 API: 제거된 API는 여기에서 찾을 수 있습니다. 추가된 API: Java 10에는 73개의 새로운 API가 추가되었습니다. 추가된 API와 비교는 여기에서 찾을 수 있습니다. 몇 가지 추가 사항을 살펴보겠습니다:
- 리스트, 맵 및 세트 인터페이스에는 정적 copyOf(Collection) 메서드가 추가되었습니다. 이 메서드는 주어진 엔트리를 포함하는 수정할 수 없는 리스트, 맵 또는 세트를 반환합니다. 리스트의 경우, 주어진 리스트가 후속으로 수정되면 반환된 리스트는 해당 수정을 반영하지 않습니다.
- Optional 및 해당 기본형 변형은 메서드 orElseThrow()을 추가했습니다. 이 메서드는 get()과 정확히 동일하지만, 자바 문서에서는 get()보다 이 메서드를 선호하는 대체 메서드라고 명시하고 있습니다.
- Collectors 클래스에는 수정할 수 없는 컬렉션(Set, List, Map)을 수집하는 다양한 메서드가 추가되었습니다.
List actors = new ArrayList<>();
actors.add("Jack Nicholson");
actors.add("Marlon Brando");
System.out.println(actors); // prints [Jack Nicholson, Marlon Brando]
// 새로 추가된 API - List에서 수정할 수 없는 리스트를 생성합니다.
List copyOfActors = List.copyOf(actors);
System.out.println(copyOfActors); // prints [Jack Nicholson, Marlon Brando]
// copyOfActors.add("Robert De Niro");는
을 생성합니다.
actors.add("Robert De Niro");
System.out.println(actors);// prints [Jack Nicholson, Marlon Brando, Robert De Niro]
System.out.println(copyOfActors); // prints [Jack Nicholson, Marlon Brando]
String str = "";
Optional name = Optional.ofNullable(str);
// 새로 추가된 API - get() 메서드보다 선호되는 옵션입니다.
name.orElseThrow(); // same as name.get()
// 새로 추가된 API - Collectors.toUnmodifiableList
List collect = actors.stream().collect(Collectors.toUnmodifiableList());
// collect.add("Tom Hanks"); 을 생성합니다.
을 생성합니다.
결론
이 기사에서는 Java 10의 다양한 새로운 기능 추가를 살펴보았습니다. 만약 여기에서 빠뜨린 중요한 내용이 있다면, 댓글을 통해 알려주시기 바랍니다. 예상대로 전체 코드는 GitHub에서 확인하실 수 있습니다. 여기.
Source:
https://www.digitalocean.com/community/tutorials/java-10-features