Java即將引入新對象類型來解決內存使用問題

前言:

2022年Java將有什麼新的特性和改進,我相信很多Java開發者都想知道。結合Java語言架構師佈萊恩·格茨Brian Goetz)最近的一些分享, 

一、Valhalla

佈萊恩·格茨在去年底發表瞭一篇名為State of Valhalla的文章,裡面信息量非常大,裡面提到早在2014年Java項目組就啟動瞭一個名叫Valhalla的項目,這個項目將為JVM平臺帶來更加靈活的、扁平化的數據類型。在2021年該項目將有進一步的動作,值對象(value objects)原始類(primitive classes)專用泛型(specialized generics)即將引入JVM平臺。今天先來聊聊這個值對象是個啥。

我們知道什麼是“值”,什麼是“對象”,但是什麼是“值對象”呢?不光你們懵逼,我也懵逼,來一起研究研究。

二、Java類型系統的不足

Java類型系統由內置的10種類型組成,這10種類型無法直接表達復雜的數據結構,例如字符串、三維坐標、空間向量等等,但是開發者可以用這10種類型來為業務實體建模,Java的類型體系是非常有用的。

但是Java類型仍然存在“缺陷”, 同一個類的兩個對象包含完全相同的屬性,但是它們的內存尋址是不一樣的。

所以從某種意義上說,他們有自己的身份標識。

但是對於原始類型就不一樣瞭,如果一個int類型的變量值為7,另一個變量也為7,區分它們有意義嗎?這個7還是那個7?顯然是無意義的。

讓我們再來舉一個現實中的例子,兩件相同尺寸、材質的紅色衣服肯定是兩件不同的衣服,但是它們的材質肯定是一種材質,顏色肯定是一種顏色,不會有傻子認為這是兩種材質、兩種顏色。這裡面的尺寸可以通過Java中的原始類型去描述,但是材質和顏色不行(雖然顏色可以用十六進制表示),在這個場景裡,尺寸、材質、顏色都應該被認為是一種原始屬性,不應該具有標識,現在的Java顯然不能直接滿足這一點。

這個痛點促使瞭Valhalla項目的誕生。

三、對象頭

為瞭理解Valhalla引入的 Value Class 概念能夠給我們帶來瞭什麼,我們需要看看JVM是如何將對象保存在內存中的。

對象頭對類的對象非常重要,決定哪個線程可以訪問對象、垃圾收集器標記、對象hash;更重要的還有對象的類型指針,它能夠在運行時動態訪問對象的類,並從其類到該對象的詳細信息,比如繼承多態、反射。

但是凡事都有兩面性,Java對象內存占用的大小取決於它所包含的信息的總和,對象頭在 64 位系統上至少需要 16 個字節,在 32 位系統上至少需要 8 個字節(當然JVM可以通過配置項去設置如何保存對象頭)。很多對象不需要多線程,也不需要什麼對象標識,就像上面提到的衣服的顏色,隻有顏色的值才是我們關心的事。這種冗餘的內存占用讓Java為人詬病。

四、Value Class

對於許多對象來說,它屬性值的相等性是我們關心的,其它類信息沒什麼用,而且隻為保存值和對這些值進行操作而編寫的類在所有類中所占的比例非常大。Valhalla項目為這樣的場景引入瞭一個新的類類型:Value Class。目前還隻是JEP草案,但是已經初具形態:

value class Substring implements CharSequence {
    private String str;
    private int start;
    private int end;
    public Substring(String str, int start, int end) {
        checkBounds(start, end, str.length());
        this.str = str;
        this.start = start;
        this.end = end;
    }
    public int length() {
        return end - start;
    }
    public char charAt(int i) {
        checkBounds(0, i, length());
        return str.charAt(start + i);
    }
    public Substring subSequence(int s, int e) {
        checkBounds(s, e, length());
        return new Substring(str, start + s, start + e);
    }
    public String toString() {
        return str.substring(start, end);
    }
    private static void checkBounds(int start, int end, int length) {
        if (start < 0 || end < start || length < end)
            throw new IndexOutOfBoundsException();
    }
}

Value Class和我們常見的類差不多,但是它可能具有下面一些特性(這些依然在討論中):

  • 值對象是沒有身份的對象,通常情況下我們用==運算符檢查身份,然而這裡==可能和equals()不再有區別。
  • 值類本身和它的所有字段默認都是final的。
  • 該類不能直接或間接地實現java.lang.IdentityObject(有身份標識類的新超類)。這意味著超類要麼是無狀態抽象類,要麼Object是無狀態抽象類。
  • 值類都是java.lang.ValueObject的隱式實現。
  • 沒有構造super函數調用構造函數。將在不執行任何超類初始化代碼的情況下創建實例。
  • 無法在值類中使用synchronized關鍵字。
  • (可能)該類沒有聲明finalize()方法。
  • (可能)構造函數不使用this來設置構造函數主體中的字段,或者可能在所有字段都明確內存分配之後。

其它的操作和普通的類應該差別不大,但是要註意的是,JDK標準庫中的一些原有類如果被認定為Value Class需要做兼容性處理。

value要成為保留字還是關鍵字?

這不是全部:

Value Class對Java類對象頭進行瞭閹割,有利於降低Java的內存消耗,但這僅僅是Valhalla計劃的一小部分。對於這一部分過於超前的內容,胖哥寫起來其實是很有困難的,構思瞭好幾天。從場景出發來瞭解一門編程語言的特性設計是非常有利於從根本提高自己的。如果你想瞭解更多關於Valhalla的東西,可以關註我,我會繼續分享相關的知識。

到此這篇關於Java即將引入新對象類型來解決內存使用問題的文章就介紹到這瞭,更多相關Java 內存問題內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: