JavaRush /Java Blog /Random-KO /8부터 13까지: Java 버전의 전체 개요입니다. 2 부

8부터 13까지: Java 버전의 전체 개요입니다. 2 부

Random-KO 그룹에 게시되었습니다
이 기사는 Java 버전 8-13의 혁신에 대한 리뷰의 두 번째 부분입니다. 첫 번째 부분은 여기에 있습니다 . 더 이상 고민하지 말고 새로운 JDK가 출시된 2018년 9월 25일로 넘어가겠습니다.

자바 11

8부터 13까지: Java 버전의 전체 개요입니다.  파트 2 - 1

var(람다)

이제부터 람다 식(암시적으로 형식화된 람다 식)을 작성할 때 람다 매개 변수의 유형을 지정하거나 생략할 수 있습니다.
Function<String, String> append = (var string) -> string + " Text";
String appendedString = append.apply("Some");
System.out.println(appendedString);
전체 변수 유형 이름을 작성할 필요 없이 람다 매개변수에 주석을 추가할 수도 있습니다.
Function<String, String> append = (@NonNull var string) -> string + " Text";

지(ZGC)

ZGC는 작동하지 않는 새로운 가비지 수집기입니다. 새 메모리를 할당하지만 다시 시작하지는 않습니다. ZGC는 높은 처리량과 낮은 대기 시간으로 대용량 메모리를 관리할 것을 약속합니다(ZGC는 64비트 플랫폼에서만 사용할 수 있습니다). 참조 색상 지정 - ZGC는 포인터 색상 지정이라는 기술과 함께 64비트 포인터를 사용합니다. 컬러 포인터는 힙의 개체에 대한 추가 정보를 저장합니다. 메모리가 조각화되면 GC가 새 할당을 위한 공간을 찾아야 할 때 성능 저하를 방지하는 데 도움이 됩니다. ZGC를 사용한 가비지 수집은 다음 단계로 구성됩니다.
  1. 세계 정지: 힙에 있는 객체(예: 지역 변수 또는 정적 필드)에 도달하기 위한 시작점을 찾습니다.
  2. 루트 링크에서 시작하는 객체 그래프의 교차점. 우리는 도달한 각 개체를 표시합니다(ZGC는 개체 그래프를 살펴보고 색상이 지정된 마커를 검사하여 사용 가능한 개체를 표시합니다).
  3. 약한 링크와 같은 일부 극단적인 경우를 처리합니다.
  4. 살아있는 개체를 이동하여 힙의 넓은 영역을 확보하여 할당 속도를 높입니다.
  5. 이동 단계가 시작되면 ZGC는 힙을 페이지로 분할하고 한 번에 한 페이지씩 작업합니다.
  6. ZGC는 모든 뿌리의 이동을 완료하고 나머지 이동이 발생합니다.
이 주제는 매우 복잡하고 혼란스럽습니다. 자세한 논의는 별도의 글이 필요하므로 여기에 남겨두겠습니다.

엡실론 GC

Epsilon은 메모리 할당을 처리하지만 실제 메모리 복구 메커니즘을 구현하지 않는 가비지 수집기입니다. 사용 가능한 Java 힙이 모두 소모되면 JVM이 종료됩니다. 즉, 이 가비지 컬렉터를 사용하여 참조에 바인딩하지 않고 무한 배열에 객체 생성을 시작하면 응용 프로그램이 OutOfMemoryError 로 충돌합니다 (다른 경우에는 참조 없이 객체를 정리하므로 충돌하지 않습니다). . 왜 필요한가요? 이유는 다음과 같습니다.
  1. 성능 시험.
  2. 메모리 압력 테스트.
  3. VM 인터페이스를 테스트합니다.
  4. 매우 짧은 작업입니다.
  5. 마지막 드롭 대기 시간이 개선되었습니다.
  6. 마지막 드롭 처리량이 향상되었습니다.
유용한 링크: 기타 혁신:
  1. ByteArrayOutputStreamvoid writeBytes(byte [])인수의 모든 바이트 를 OutputStream.
  2. FileReaderFileWriterCharset을 지정할 수 있는 새로운 생성자를 얻었습니다 .
  3. Path두 개의 새로운 메소드를 가져와서 문자열 인수에서 경로 또는 결합 시 경로 문자열을 형성하는 문자열 시퀀스를 of(String, String [])반환 하고 :는 URI에서 Path를 반환합니다.Pathof(URI)
  4. Pattern— 주어진 입력 문자열이 주어진 패턴과 일치하는지 확인하는 메서드를 받았습니다 asMatchPredicate()(예를 들어 스트림의 데이터를 필터링할 수 있도록 정규식을 사용하여 조건자를 생성할 수 있는지 여부).
  5. String나는 다음과 같은 유용한 방법을 많이 선택했습니다.
    • String strip(): 문자열의 시작과 끝에서 모든 공백이 제거된 이 문자열인 문자열을 반환합니다(trim()과 유사하지만 공백을 다르게 정의합니다).
    • String stripLeading(): 이 문자열인 문자열을 반환하고 문자열에서 선행 공백을 제거합니다.
    • String stripTrailing(): 이 문자열인 문자열을 반환하고 문자열 끝의 공백을 제거합니다.
    • Stream lines(): 이 문자열에서 추출되어 줄 구분 기호로 구분되어 Stream에서 우리를 반환합니다 .String
    • String repeat(int): 이 문자열을 여러 번 반복하여 연결한 문자열을 반환합니다.
    • boolean isBlank(): 문자열이 비어 있거나 공백만 포함되어 있으면 true를 반환하고, 그렇지 않으면 false를 반환합니다.
  6. Thread— destroy() 및 stop(Throwable) 메소드가 제거되었습니다.
  7. Files여러 가지 새로운 방법이 생겼습니다.
    • String readString(Path): UTF-8 인코딩을 사용하여 바이트에서 문자로 디코딩하는 동안 파일의 모든 데이터를 문자열로 읽습니다.
    • String readString(Path, Charset): 위의 방법과 동일하지만 지정된 Charset을 사용하여 바이트에서 문자로 디코딩이 발생한다는 차이점이 있습니다.
    • Path writeString (Path, CharSequence, OpenOption []): 파일에 일련의 문자를 씁니다. 문자는 UTF-8 인코딩을 사용하여 바이트로 인코딩됩니다.
    • Path writeString(Path, CharSequence,Charset, OpenOption []): 위와 같은 방법으로, Charset에 지정된 인코딩을 사용하여 문자만 바이트로 인코딩합니다.
이는 가장 흥미로운 API 혁신이었습니다(저의 소견으로는). 자세한 검토를 위한 몇 가지 자료는 다음과 같습니다.

자바 12

6개월이 지나면 Java 진화의 다음 단계가 보입니다. 이제 지식의 삽을 꺼내서 파헤쳐 볼 시간입니다. 8부터 13까지: Java 버전의 전체 개요입니다.  파트 2 - 2

G1 업데이트

G1에는 다음과 같은 개선 사항이 적용되었습니다.
  1. 사용하지 않은 할당 메모리 회수

    Java 힙 메모리에는 사용되지 않은 메모리(즉, 비활성 메모리)가 있습니다. Java 12에서는 이 문제를 해결하기로 결정했습니다.

    • G1은 전체 GC 또는 병렬 루프 중에 힙에서 메모리를 반환합니다. G1은 전체 GC를 방지하려고 시도하고 힙 할당을 기반으로 병렬 루프를 시작합니다. G1이 힙에서 메모리를 반환하도록 강제해야 합니다.

    이 개선 사항은 G1을 사용하지 않을 때 힙에서 OS로 메모리를 자동으로 반환하여 성능에 중점을 둡니다.

  2. 일시정지 시간 초과 시 혼합 컬렉션 중단

    G1은 분석 엔진을 사용하여 가비지 수집에 필요한 작업량을 선택합니다. 세트를 정의하고 정리를 시작한 후 중단 없이 실시간 객체를 수집합니다. 이로 인해 가비지 수집기가 일시 중지 시간 목표를 초과하게 됩니다. 실제로 이 문제는 개선을 통해 해결되었습니다. 다음 단계를 완료하는 데 필요한 시간이 합리적인 한계를 벗어나면 이 단계가 중단될 수 있기 때문입니다.

마이크로벤치마크

Java 12에서는 기존 벤치마크를 사용하여 JVM 성능을 쉽게 테스트할 수 있도록 마이크로벤치마킹 테스트를 도입했습니다. 이는 JVM 자체에서 작업하려는 모든 사람에게 매우 유용합니다. 추가된 테스트는 JMH(Java Microbenchmark Harness)를 사용하여 생성됩니다. 이러한 테스트를 통해 JVM에 대한 지속적인 성능 테스트가 가능합니다. JEP 230은 약 100개의 테스트 도입을 제안하며, 새 버전의 Java가 출시됨에 따라 새로운 테스트도 도입됩니다. 다음은 추가되는 테스트의 예 입니다 .

셰넌도어

이는 낮은 응답 시간(하한은 10-500ms)을 보장하는 것이 목표인 가비지 수집(GC) 알고리즘입니다. 이는 Java 스레드 실행과 동시에 정리 작업을 수행할 때 GC 일시 중지 시간을 줄여줍니다. 셰넌도어에서 일시정지 시간은 힙 크기와 무관합니다. 즉, 일시 중지 시간은 힙 크기에 관계없이 동일합니다. 이는 실험적인 기능 이며 OpenJDK의 표준(Oracle) 빌드에는 포함되지 않습니다.

스위치 개선

Java 12에서는 패턴 일치를 위한 Switch 표현식이 개선되었습니다. 새로운 구문 L →이 도입되었습니다. 다음은 새로운 스위치의 핵심 사항 목록입니다 .
  1. 새로운 구문에서는 오류를 방지하기 위해 break 문이 필요하지 않습니다.
  2. 스위치 표현식이 더 이상 실패하지 않습니다.
  3. 또한 단일 레이블에 여러 상수를 정의할 수 있습니다.
  4. 이제 스위치 표현식에 기본 케이스가 필요합니다.
  5. break는 레지스터 자체에서 값을 반환하기 위해 Switch 표현식에서 사용됩니다(실제로 스위치는 값을 반환할 수 있습니다).
이를 예로 들어 보겠습니다.
var result = switch (someDay) {
  case "M", "W", "F" -> "MWF";
  case "T", "TH", "S" -> "TTS";
  default -> {
      if(someDay.isEmpty())
            break "Please insert a valid day.";
      else
            break "Looks like a Sunday.";
  }
};
Java 13에서 표현식을 전환하는 확실한 가이드 기타 새로운 기능:
  1. String:

    transform(Function f)- 제공된 함수를 문자열에 적용합니다. 결과는 문자열이 아닐 수도 있습니다.
    indent(int x)— 문자열에 x 공백을 추가합니다. 매개변수가 음수이면 이 개수의 선행 공백이 제거됩니다(가능한 경우).

  2. Files- 와 같은 메소드를 사용하여 mismatch()두 파일의 내용에서 일치하지 않는 첫 번째 바이트의 위치를 ​​찾아 반환하거나 불일치가 없으면 -1L을 반환합니다.

  3. CompactNumberFormat간단한 형식으로 십진수 형식을 지정하는 새로운 클래스가 나타났습니다 . 이 압축 형식의 예는 1,000,000 대신 1M입니다. 따라서 9자 대신 2, 2만 필요합니다.

  4. LONG과 SHORT라는 두 가지 값을 갖는 새로운 도 있습니다 .enumNumberFormatStyle

  5. InputStream 방법을 얻었습니다 skipNBytes(long n) . 입력 스트림에서 n번째 바이트를 건너뜁니다.

흥미로운 Java 12 링크:

자바 13

세상은 자바(Java 13)처럼 가만히 있지 않고 움직이고 발전합니다. 8부터 13까지: Java 버전의 전체 개요입니다.  파트 2 - 3

텍스트 블록

Java는 문자열 정의와 관련하여 항상 약간의 어려움을 겪었습니다. 공백, 줄 바꿈, 따옴표 등으로 줄을 정의해야 하는 경우 이로 인해 약간의 어려움이 발생하므로 특수 문자를 사용해야 했습니다. 예를 들어 줄 바꿈을 위해 \n을 사용하거나 줄 일부를 이스케이프 처리해야 했습니다. 그 자체. 이렇게 하면 코드의 가독성이 크게 떨어지고 해당 줄을 작성할 때 시간이 더 걸립니다. 이는 JSON, XML, HTML 등을 표시하는 문자열을 작성할 때 특히 두드러집니다. 결과적으로 작은 Json을 작성하려면 다음과 같이 표시됩니다.
String JSON_STRING = "{\r\n" + "\"name\" : \"someName\",\r\n" + "\"site\" : \"https://www.someSite.com/\"\r\n" + "}";
그런 다음 Java 13이 등장하여 텍스트(텍스트 블록이라고 함) 앞뒤에 삼중 큰따옴표 형태로 솔루션을 제공합니다. 이 혁신을 사용한 이전 json 예제를 살펴보겠습니다.
String TEXT_BLOCK_JSON = """
{
    "name" : "someName",
    "site" : "https://www.someSite.com/"
}
""";
훨씬 더 간단하고 명확해졌죠? String이러한 블록을 관리하기 위해 세 가지 새로운 방법 도 각각 추가되었습니다.
  • stripIndent(): 문자열에서 임의의 공백을 제거합니다. 이는 여러 줄 문자열을 읽고 명시적 선언에서 발생하는 것과 동일한 종류의 무작위 공백 제외를 적용하려는 경우에 유용합니다(기본적으로 무작위 공백을 제거하기 위해 컴파일러를 시뮬레이션함).
  • formatted(Object... args ): 와 유사 format(String format, Object... arg)하지만 텍스트 블록용입니다.
  • translateEscapes(): 해당 유니코드 값으로 변환된 이스케이프 시퀀스(예: \r)가 포함된 문자열을 반환합니다.

스위치 개선

Switch 표현식은 Java 12에서 도입되었으며 13에서는 이를 개선합니다. 12에서는 break를 사용하여 반환 값을 정의합니다. 13에서는 반환 값이 Yield로 대체되었습니다. 이제 Java 12 섹션에 있던 스위치 표현식을 다음과 같이 다시 작성할 수 있습니다.
var result = switch (someDay) {
  case "M", "W", "F" -> "MWF";
  case "T", "TH", "S" -> "TTS";
  default -> {
      if(someDay.isEmpty())
          yield "Please insert a valid day.";
      else
          yield "Looks like a Sunday.";
  }
};
이미 Java에 익숙한 우리 프로그래머들에게는 break를 받아들이는 것이 정상이었지만 그럼에도 불구하고 그것은 꽤 이상했습니다. Break True가 나에게 말하려는 것은 무엇입니까? 새로운(비교적 새로운) Yield 키워드는 더욱 명확해졌으며 향후 값이 반환되는 다른 위치에 나타날 수도 있습니다. 이 주제에 깊은 관심이 있는 분들은 다음 자료를 숙지하시기 바랍니다.

동적 CDS 아카이브

CDS - 클래스 데이터 공유. 일반적으로 사용되는 클래스 세트를 나중에 여러 JVM 인스턴스에서 로드할 수 있는 아카이브로 패키징할 수 있습니다. 왜 이것이 필요합니까? 사실 클래스를 로드하는 과정에서 JVM은 클래스 읽기, 내부 구조에 클래스 저장, 읽기 클래스의 정확성 확인, 종속 클래스 검색 및 로드 등 리소스를 많이 사용하는 작업을 많이 수행합니다. ., 이 모든 작업이 완료된 후에야 수업을 진행할 수 있습니다. JVM 인스턴스가 종종 동일한 클래스를 로드할 수 있기 때문에 많은 리소스가 낭비되는 것은 당연합니다. 예를 들어 문자열, LinckedList, 정수입니다. 글쎄, 또는 동일한 애플리케이션의 클래스는 모두 리소스입니다. 필요한 모든 단계를 한 번만 수행한 다음 재설계된 클래스를 여러 JVM의 메모리에 로드할 수 있는 아카이브에 배치하면 메모리 공간이 크게 절약되고 애플리케이션 시작 시간이 단축될 수 있습니다. 실제로 CDS를 사용하면 이러한 아카이브를 생성할 수 있습니다. Java 9에서는 시스템 클래스만 아카이브에 추가할 수 있었습니다. Java 10 - 아카이브에 애플리케이션 클래스를 포함합니다. 이러한 아카이브 생성은 다음으로 구성됩니다.
  • 애플리케이션에 의해 로드된 클래스 목록을 생성합니다.
  • 우리가 찾은 클래스로 꼭 필요한 아카이브를 만드는 것입니다.
Java 13의 혁신은 애플리케이션이 종료될 때 아카이브를 생성할 수 있도록 CDS를 개선합니다. 이는 위의 두 단계가 이제 하나로 결합된다는 의미입니다. 그리고 한 가지 더 중요한 점은 애플리케이션이 실행되는 동안 로드된 클래스만 아카이브에 추가된다는 것입니다. 즉, 여전히 application.jar에 포함되어 있지만 어떤 이유로 로드되지 않은 클래스는 아카이브에 추가되지 않습니다.

소켓 API 업데이트

소켓 API( java.net.Socket 및 java.net.ServerSocket )는 처음부터 본질적으로 Java의 필수적인 부분이지만 지난 20년 동안 소켓은 업데이트된 적이 없습니다. C와 Java로 작성되었으며 매우 부피가 크고 유지 관리가 어려웠습니다. 그러나 Java 13은 이 모든 문제를 자체적으로 조정하기로 결정하고 기본 구현을 대체했습니다. 이제 PlainSocketImpl 대신 공급자 인터페이스가 NioSocketImpl 로 대체됩니다 . 이 새로운 코딩된 구현은 java.nio 와 동일한 백엔드 인프라를 기반으로 합니다 . 기본적으로 클래스는 동기화된 메소드보다는 java.util.concurrent 버퍼 캐시 및 잠금 메커니즘(세그먼트 기반)을 사용합니다. 더 이상 네이티브 코드가 필요하지 않으므로 다른 플랫폼으로 쉽게 이식할 수 있습니다. 그래도 PlainSocketImpl을 다시 사용하는 방법이 있지만 이제부터는 NioSocketImpl이 기본적으로 사용됩니다 .

ZGC에 대한 메모리 반환

우리가 기억하는 것처럼 Z 가비지 수집기는 GC 일시 중지가 10ms를 초과하지 않도록 대기 시간이 짧은 가비지 수집 메커니즘으로 Java 11에 도입되었습니다. 그러나 동시에 Shenandoah 및 G1과 같은 다른 가상 GC 핫스팟과 달리 사용되지 않은 동적 메모리를 OS에 반환할 수 있습니다. 이 수정으로 이 J 기능이 ZGC에 추가되었습니다. 따라서 향상된 성능과 함께 메모리 공간이 줄어들고 ZGC는 이제 지정된 최소 힙 크기에 도달할 때까지 기본적으로 커밋되지 않은 메모리를 운영 체제에 반환합니다. 한 가지 더: 이제 ZGC의 최대 지원 힙 크기는 16TB입니다. 이전에는 4TB가 제한이었습니다. 기타 혁신:
  1. javax.securityjdk.sasl.disabledMechanisms- SASL 메커니즘을 비활성화하는 속성을 추가했습니다 .
  2. java.nioFileSystems.newFileSystem (Path, Map <String,?>)- 각각 새 파일을 생성하는 방법이 추가되었습니다 .
  3. 이제 클래스 java.nio에는 절대(상대가 아닌) getset-메소드가 있습니다. 기본 추상 클래스와 마찬가지로 버퍼의 일부를 검색하는 Buffer메서드를 포함합니다 .slice()
  4. DOM 및 SAX 팩토리를 인스턴스화하기 위한 메서드가 추가되었습니다 javax.xml.parsers(네임스페이스 지원 포함).
  5. 유니코드 지원이 버전 12.1로 업데이트되었습니다.
Java 13에 대한 흥미로운 링크:

결과

Java 14에서 발표된 혁신을 검토할 수 있지만 곧 빛을 보게 될 것이기 때문에 JDK 14는 2020년 3월 17일에 출시될 예정이므로 출시 직후 별도로 전체 검토를 수행하는 것이 가장 좋습니다. . 또한 Python 2-3과 같이 릴리스 사이에 긴 공백이 있는 다른 프로그래밍 언어에서는 호환성이 없다는 사실에 주목하고 싶습니다. 즉, 코드가 Python 2로 작성된 경우 3으로 변환하려면 열심히 노력해야 합니다. Java는 이전 버전과의 호환성이 매우 뛰어나기 때문에 이 점에서 특별합니다. 이는 Java 5 또는 8 프로그램이 Java 8-13 가상 머신에서 실행되도록 보장된다는 것을 의미합니다. 단, 현재로서는 걱정할 필요가 없는 몇 가지 예외가 있습니다. 예를 들어, 애플리케이션이 Java 8 JVM에서 사용할 수 없는 Java 13 기능을 사용하는 경우에는 이것이 반대 방향으로 작동하지 않는다는 것이 분명합니다. 오늘은 여기까지입니다. 지금까지 읽어주신 분들께 존경을 표합니다.)) 8부터 13까지: Java 버전의 전체 개요입니다.  파트 2 - 5
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION