JavaRush /Java Blog /Random-TW /從 8 到 13:Java 版本的完整概述。第2部分

從 8 到 13:Java 版本的完整概述。第2部分

在 Random-TW 群組發布
本文是我對 Java 版本 8-13 的創新回顧的第二部分。第一部分在這裡。閒話少說,我們繼續看:2018 年 9 月 25 日,新版 JDK 發行:

爪哇11

從 8 到 13:Java 版本的完整概述。 第 2 - 1 部分

var(以 lambda 為單位)

從現在開始,我們可以在編寫 lambda 表達式(隱式類型 lambda 表達式)時指定 lambda 參數的類型或省略它們:
Function<String, String> append = (var string) -> string + " Text";
String appendedString = append.apply("Some");
System.out.println(appendedString);
您也可以為 lambda 參數新增註釋,而無需編寫完整的變數類型名稱:
Function<String, String> append = (@NonNull var string) -> string + " Text";

Z(ZGC)

ZGC是一個新的垃圾收集器,不起作用。它分配新記憶體但從不重新啟動它。ZGC 承諾以高吞吐量和低延遲管理大量記憶體(ZGC 僅在 64 位元平台上可用)。參考著色 - ZGC 使用 64 位元指標以及稱為指標著色的技術。彩色指標儲存有關堆上物件的附加資訊。當記憶體變得碎片化時,這有助於避免 GC 需要為新分配尋找空間時效能下降。使用 ZGC 的垃圾收集包括以下步驟:
  1. 世界站:我們尋找到達堆上物件的起點(例如局部變數或靜態欄位);
  2. 從根連結開始的物件圖的交集。我們標記我們到達的每個物件(ZGC 遍歷物件圖並檢查彩色標記,標記可用物件);
  3. 處理一些邊緣情況,例如薄弱環節;
  4. 移動活動對象,釋放大面積的堆以加速分配。
  5. 當移動階段開始時,ZGC 將堆拆分為頁面並一次處理一頁;
  6. ZGC 完成任何根部的運動,然後進行其餘的運動。
這個話題非常複雜且令人困惑。詳細的討論需要單獨的文章,所以我就放在這裡:

埃普西隆氣相層析儀

Epsilon 是一個垃圾收集器,它處理記憶體分配,但不實現任何真正的記憶體回收機制。一旦可用的 Java 堆耗盡,JVM 將關閉。也就是說,如果您開始在無限數組中創建物件而不使用此垃圾收集器綁定到引用,則應用程式將因OutOfMemoryError崩潰(如果使用任何其他錯誤,則不會崩潰,因為它將清理沒有引用的對象) 。為什麼需要它?原因如下:
  1. 性能測試。
  2. 記憶體壓力測試。
  3. 測試虛擬機器介面。
  4. 工作時間極短。
  5. 最後下降延遲改進。
  6. 最後一滴吞吐量的改進。
有用的連結: 其他創新:
  1. ByteArrayOutputStream有一個方法void writeBytes(byte [])將參數中的所有位元組寫入OutputStream.
  2. FileReaderFileWriter獲得了新的建構函數,允許您指定字元集。
  3. Path抓住了兩個新方法,從字串參數of(String, String [])返迴路徑或字串序列,組合起來形成路徑字串,並且:從 URI 返迴路徑。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

六個月過去了,我們看到了 Java 發展的下一階段。所以,是時候拿出知識的鏟子來挖掘了。 從 8 到 13:Java 版本的完整概述。 第 2 - 2 部分

更新G1

G1 進行了以下改進:
  1. 回收未使用的已分配內存

    在 Java 堆記憶體中,存在未使用記憶體(或換句話說,不活動記憶體)這樣的東西。在 Java 12 中,他們決定要解決這個問題,現在:

    • G1 在完整 GC 或平行循環期間從堆返回記憶體;G1 嘗試阻止 Full GC,並根據堆分配啟動並行循環。我們必須強制 G1 從堆中返回記憶體。

    此改進側重於效能,在 G1 未使用時自動將記憶體從堆返回到作業系統。

  2. 超過暫停時間時中止混合收集

    G1使用分析引擎來選擇垃圾收集所需的工作量。它在定義集合並開始清理後不間斷地收集活動物件。這會導致垃圾收集器超出其暫停時間目標。實際上,這個問題透過改進就解決了,因為如果完成下一步所需的時間超出合理限度,則可以中斷此步驟。

微基準測試

Java 12 引入了微基準測試,以便可以使用現有基準輕鬆測試 JVM 效能。這對於任何想要使用 JVM 本身的人來說都非常有用。新增的測試是使用 Java Microbenchmark Harness (JMH) 創建的。這些測試允許對 JVM 進行持續的效能測試。JEP 230 建議引入大約 100 個測試,並隨著 Java 新版本的發布而引入新的測試。下面是新增的測試的範例

謝南多厄

這是一種垃圾收集 (GC) 演算法,其目標是保證低反應時間(下限為 10-500 毫秒)。這可以減少在執行 Java 執行緒的同時進行清理工作時的 GC 暫停時間。在 Shenandoah 中,暫停時間與堆大小無關。這意味著無論堆的大小如何,暫停時間都是相同的。這是一項實驗性功能,不包含在 OpenJDK 的標準 (Oracle) 版本中。

改進開關

Java 12 改進了用於模式匹配的 Switch 表達式。引入了新語法 L → 。以下是新開關的要點清單
  1. 新語法不再需要使用break語句來防止錯誤。
  2. Switch 表達式不再失敗。
  3. 此外,我們可以在單一標籤中定義多個常數。
  4. switch 表達式中現在需要 default case。
  5. break 在 Switch 表達式中用於從暫存器本身傳回值(實際上,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用於以緊湊形式格式化十進制數。這種緊湊形式的一個例子是 1M 而不是 1,000,000。因此,只需要兩個 2 而不是 9 個字元。

  4. 還有一種新的 enumNumberFormatStyle它有兩個值——LONG 和 SHORT。

  5. InputStream 得到的方法是 skipNBytes(long n):從輸入流中跳過第n個位元組。

有趣的 Java 12 連結:

爪哇13

世界不是靜止的,它在移動,它在發展,就像 Java - 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)轉換為對應的 Unicode 值。

改進開關

Switch 表達式是在 Java 12 中引入的,並在 13 中對其進行了改進。在12中你使用break定義回傳值。13中,回傳值被yield取代。現在,我們在 Java 12 部分中的 switch 表達式可以重寫為:
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 實例經常載​​入相同的類,因此浪費了大量資源。例如字串、連結列表、整數。好吧,或者同一應用程式的類,所有這些都是資源。如果我們只執行一次所有必要的步驟,然後將重新設計的類別放入可以載入到多個 JVM 記憶體中的檔案中,這可以顯著節省記憶體空間並減少應用程式啟動時間。實際上,CDS 使得創建這樣的存檔成為可能。Java 9 只允許將系統類別加入到檔案中。Java 10 - 在檔案中包含應用程式類別。 此類檔案的創建包括:
  • 建立應用程式載入的類別清單;
  • 用我們找到的類別建立一個急需的檔案。
Java 13 中的創新改進了 CDS,以便它可以在應用程式終止時建立存檔。這意味著上述兩個步驟現在將合而為一。更重要的一點是:只有在應用程式運行時載入的類別才會加入到檔案中。換句話說,那些仍包含在 application.jar 中但由於某種原因未載入的類別將不會添加到檔案中。

更新套接字API

Socket API(java.net.Socket 和 java.net.ServerSocket)本質上是 Java 自誕生以來不可或缺的一部分,但套接字在過去二十年中從未更新過。它們是用 C 和 Java 編寫的,非常非常龐大且難以維護。但 Java 13 決定對整個問題進行自己的調整並替換了基本實作。現在,提供者介面已替換為NioSocketImpl ,而不是 PlainSocketImpl這個新的編碼實作是基於與java.nio相同的後端基礎設施。本質上,該類別使用 java.util.concurrent 緩衝區快取和鎖定機制(基於段)而不是同步方法。它不再需要本機程式碼,從而更容易移植到不同的平台。儘管如此,我們還是有辦法恢復使用PlainSocketImpl,但從現在開始預設使用NioSocketImpl

ZGC 的記憶體返回

我們記得,Z 垃圾收集器是在 Java 11 中引入的,作為一種低延遲垃圾收集機制,因此 GC 暫停永遠不會超過 10 毫秒。但同時,與其他虛擬 GC 熱點(例如 Shenandoah 和 G1)不同,它可以將未使用的動態記憶體傳回給作業系統。此修改將 J 功能新增至 ZGC。因此,我們減少了記憶體佔用並提高了效能,並且 ZGC 現在預設將未提交的記憶體傳回給作業系統,直到達到指定的最小堆大小。還有一件事:ZGC 現在支援的最大堆大小為 16 TB。此前,4TB 是限制。 其他創新:
  1. javax.security- 新增了一個屬性jdk.sasl.disabledMechanisms來停用 SASL 機制。
  2. java.nio- 新增了一種方法FileSystems.newFileSystem (Path, Map <String,?>)- 分別建立新檔案。
  3. 類別java.nio現在具有絕對(而不是相對)getset- 方法。它們與抽象基底類別一樣,包含用於檢索部分緩衝區的Buffer方法。slice()
  4. 新增了javax.xml.parsers用於實例化 DOM 和 SAX 工廠的方法(具有命名空間支援)。
  5. Unicode 支援已更新至版本 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 13 函數,而這些函數在 Java 8 JVM 中根本不可用。這就是我今天的全部內容,尊重那些讀到這裡的人)) 從 8 到 13:Java 版本的完整概述。 第 2 - 5 部分
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION