<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    JDK9為何要將String的底層實現由char[]改成了byte[]?

    VSole2022-05-17 15:50:28

    如果你不是 Java8 的釘子戶,你應該早就發現了:String 類的源碼已經由 char[] 優化為了 byte[] 來存儲字符串內容,為什么要這樣做呢?

    開門見山地說,從 char[] 到 byte[],最主要的目的是為了節省字符串占用的內存 。內存占用減少帶來的另外一個好處,就是 GC 次數也會減少。

    為什么要優化 String 節省內存空間

    我們使用 jmap -histo:live pid | head -n 10 命令就可以查看到堆內對象示例的統計信息、查看 ClassLoader 的信息以及 finalizer 隊列。

    以我正在運行著的編程喵喵項目實例(基于 Java 8)來說,結果是這樣的:

    其中 String 對象有 17638 個,占用了 423312 個字節的內存,排在第三位。


    由于 Java 8 的 String 內部實現仍然是 char[],所以我們可以看到內存占用排在第 1 位的就是 char 數組。


    char[] 對象有 17673 個,占用了 1621352 個字節的內存,排在第一位。


    那也就是說優化 String 節省內存空間是非常有必要的,如果是去優化一個使用頻率沒有 String 這么高的類庫,就顯得非常的雞肋。


    byte[] 為什么就能節省內存空間呢?



    眾所周知,char 類型的數據在 JVM 中是占用兩個字節的,并且使用的是 UTF-8 編碼,其值范圍在 '\u0000'(0)和 '\uffff'(65,535)(包含)之間。


    也就是說,使用 char[] 來表示 String 就導致了即使 String 中的字符只用一個字節就能表示,也得占用兩個字節。


    而實際開發中,單字節的字符使用頻率仍然要高于雙字節的。


    當然了,僅僅將 char[] 優化為 byte[] 是不夠的,還要配合 Latin-1 的編碼方式,該編碼方式是用單個字節來表示字符的,這樣就比 UTF-8 編碼節省了更多的空間。


    換句話說,對于:

    String name = "jack";  
    


    這樣的,使用 Latin-1 編碼,占用 4 個字節就夠了。


    但對于:

    String name = "小明";  
    


    這種,木的辦法,只能使用 UTF16 來編碼。


    針對 JDK 9 的 String 源碼里,為了區別編碼方式,追加了一個 coder 字段來區分。

    /**  
     * The identifier of the encoding used to encode the bytes in  
     * {@code value}. The supported values in this implementation are  
     *  
     * LATIN1  
     * UTF16  
     *  
     * @implNote This field is trusted by the VM, and is a subject to  
     * constant folding if String instance is constant. Overwriting this  
     * field after construction will cause problems.  
     */  
    private final byte coder;  
    


    Java 會根據字符串的內容自動設置為相應的編碼,要么 Latin-1 要么 UTF16。


    也就是說,從 char[] 到 byte[],中文是兩個字節,純英文是一個字節,在此之前呢,中文是兩個字節,英文也是兩個字節 。


    為什么用 UTF-16 而不用 UTF-8 呢?



    在 UTF-8 中,0-127 號的字符用 1 個字節來表示,使用和 ASCII 相同的編碼。


    只有 128 號及以上的字符才用 2 個、3 個或者 4 個字節來表示:

    • 如果只有一個字節,那么最高的比特位為 0。
    • 如果有多個字節,那么第一個字節從最高位開始,連續有幾個比特位的值為 1,就使用幾個字節編碼,剩下的字節均以 10 開頭。


    具體的表現形式為:

    • 0xxxxxxx:一個字節
    • 110xxxxx 10xxxxxx:兩個字節編碼形式(開始兩個 1);- 1110xxxx 10xxxxxx 10xxxxxx:三字節編碼形式(開始三個 1)
    • 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx:四字節編碼形式(開始四個 1)


    也就是說,UTF-8 是變長的,那對于 String 這種有隨機訪問方法的類來說,就很不方便。


    所謂的隨機訪問,就是 charAt、subString 這種方法,隨便指定一個數字,String 要能給出結果。


    如果字符串中的每個字符占用的內存是不定長的,那么進行隨機訪問的時候,就需要從頭開始數每個字符的長度,才能找到你想要的字符。


    那有小伙伴可能會問,UTF-16 也是變長的呢?一個字符還可能占用 4 個字節呢?


    的確,UTF-16 使用 2 個或者 4 個字節來存儲字符:

    • 對于 Unicode 編號范圍在 0 ~ FFFF 之間的字符,UTF-16 使用兩個字節存儲。
    • 對于 Unicode 編號范圍在 10000 ~ 10FFFF 之間的字符,UTF-16 使用四個字節存儲,具體來說就是:將字符編號的所有比特位分成兩部分,較高的一些比特位用一個值介于 D800~DBFF 之間的雙字節存儲,較低的一些比特位(剩下的比特位)用一個值介于 DC00~DFFF 之間的雙字節存儲。


    但是在 Java 中,一個字符(char)就是 2 個字節,占 4 個字節的字符,在 Java 里也是用兩個 char 來存儲的。


    而 String 的各種操作,都是以 Java 的字符(char)為單位的,charAt 是取得第幾個char,subString 取的也是第幾個到第幾個 char 組成的子串,甚至 length 返回的都是 char 的個數。


    所以 UTF-16 在 Java 的世界里,就可以視為一個定長的編碼。

    -End-


    最近有一些小伙伴,讓我幫忙找一些 面試題 資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來,可以說是程序員面試必備!所有資料都整理到網盤了,歡迎下載!



    點擊?卡片,關注后回復【面試題】即可獲取

    在看點這里好文分享給更多人↓↓

    stringchar
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    無意中看到ch1ng師傅的文章覺得很有趣,不得不感嘆師傅太厲害了,但我一看那長篇的函數總覺得會有更騷的東西,所幸還真的有,借此機會就發出來一探究竟,同時也不得不感慨下RFC文檔的妙處,當然本文針對的技術也僅僅只是在流量層面上waf的繞過。Pre很神奇對吧,當然這不是終點,接下來我們就來一探究竟。前置這里簡單說一下師傅的思路部署與處理上傳war的servlet是?
    RCE回顯技術在20年突然火爆全網,這里學習跟進一下。
    可以使用 '|"|}|) 等特殊字符進行檢測,除了正常的參數提交外,注入的位置也可能存在于 HTTP header 中,比如 X-Forwarded-For、User-Agent、Referer、Cookie 中。不同數據庫的報錯內容:
    在最近的研究和分析工作中,我們發現通過Google搜索實現的惡意廣告活動有所增加,目前我們也在跟蹤和分析其中相關的威脅行為者,并對他們在繞過安全檢測并實現攻擊鏈時所使用的技術進行了深入研究。
    1 介紹XSS 是網絡中最常見的漏洞,再配合其它的攻擊手段往往能輕易敲開服務器的大門。在各大漏洞平臺中,XSS 漏洞也是數量最多的。傳播記錄描述了數據從 source 到 sink 的變化過程,傳播記錄的完整性直接影響 XSS 的檢測結果。眾所周知,觸發 XSS 漏洞的字符串往往是來自于不同 source 的字符的組合,如果不能完整記錄數據變化的過程或做不到字符級別的描述,那將會產生大量的漏報。做好以下這些 API 的記錄就可以最大程度保證傳播記錄的完整性。
    研究人員發現越來越多的釣魚攻擊開始使用去中心化的IPFS網絡。
    介紹Runtime 是一系列采用 C++ 語言編寫的功能方法,它實現了大量 JavaScript 運行期間需要的 native 功能。本文分析 Runtime_StringToArray 方法的源碼和重要數據結構,講解 Runtime_StringToArray 方法的觸發條件。
    現在只對常讀和星標的公眾號才展示大圖推送,建議大家把瀟湘信安“設為星標”,否則可能看不到了!0x00 前言對國外某地產公司的一次測試,測試過程中每一步都有阻礙,不像以往的一帆風順,對其中涉及的一些點進行一個簡單的記錄,碼較厚,見諒。
    Thymeleaf SSTI漏洞分析
    2021-11-11 12:56:34
    要了解SSTI漏洞,首先要對模板引擎有所了解。下面是模板引擎的幾個相關概念。 模板引擎(這里特指用于Web開發的模板引擎)是為了使用戶界面與業務數據(內容)分離而產生的,它可以生成特定格式的文檔,用于網站的模板引擎就會生成一個標準的文檔。 模板引擎的本質是將模板文件和數據通過模板引擎生成最終的HTML代碼。 模板引擎不屬于特定技術領域,它是跨領域跨平臺的概念。 模板引擎的出現是為了解決前后端分離
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类