JDK 7和JDK 8中大行读取速度较慢的原因
我之前發(fā)布了博客文章“使用JDK 7和JDK 8讀取慢速行”,并且在該問題上有一些有用的評論來描述該問題。 這篇文章提供了更多解釋,說明為何該文章中演示的文件讀取(并由Ant的LineContainsRegExp使用 )在Java 7和Java 8中比在Java 6中這么慢。
X Wang的帖子JDK 6和JDK 7中的substring()方法描述了如何在JDK 6和JDK 7之間更改String.substring() 。Wang在該帖子中寫道,JDK 6 substring() “創(chuàng)建了一個新字符串,但字符串的值仍指向堆中相同的[backing char]數(shù)組。” 他與JDK 7方法形成對比,“在JDK 7中,substring()方法實際上在堆中創(chuàng)建了一個新數(shù)組。”
Wang的文章對于理解Java 6和Java 7之間String.substring()的區(qū)別非常有用。這篇文章的評論也很有見地。 這些評論包括我很感激的觀點 ,“我會說'不同'而不是'改善'。” 也有關(guān)于JDK 7如何避免 JDK 6中可能發(fā)生的潛在內(nèi)存泄漏的解釋 。
StackOverflow線程Java 7字符串–子字符串的復(fù)雜性解釋了更改的動機,并引用了JDK-4513622錯誤:(str)保留字段的子字符串會阻止對象的GC 。 該錯誤指出:“ [發(fā)生OutOfMemory錯誤,因為如果調(diào)用者在對象中存儲字段的子字符串,則對象不會被垃圾回收。” 該錯誤包含演示此錯誤發(fā)生的示例代碼。 我在這里修改了該代碼:
/*** Minimally adapted from Bug JDK-4513622.** {@link http://bugs.java.com/view_bug.do?bug_id=4513622}*/ public class TestGC {private String largeString = new String(new byte[100000]);private String getString(){return this.largeString.substring(0,2);}public static void main(String[] args){java.util.ArrayList<String> list = new java.util.ArrayList<String>();for (int i = 0; i < 1000000; i++){final TestGC gc = new TestGC();list.add(gc.getString());}} }下一個屏幕快照展示了用Java 6(jdk1.6是可執(zhí)行Java啟動程序路徑的一部分)和Java 8(主機上的默認(rèn)版本)執(zhí)行的最后一個代碼段(從Bug JDK-4513622改編而成)。 如屏幕快照所示,在Java 6中運行代碼時拋出OutOfMemoryError ,而在Java 8中運行時不拋出OutOfMemoryError 。
換句話說,當(dāng)對冗長的Java字符串執(zhí)行String.substring時,Java 7中的更改修復(fù)了潛在的內(nèi)存泄漏,但以性能影響為代價。 這意味著使用String.substring (包括Ant的LineContainsRegExp)來處理很長的行的任何實現(xiàn)都可能需要更改以不同的方式實現(xiàn),或者在從Java 6遷移到Java 7及更高版本時處理很長的行時應(yīng)避免使用。
一旦知道了問題(在這種情況下更改String.substring實現(xiàn)),就可以更輕松地在線查找有關(guān)正在發(fā)生的事情的文檔(感謝提供了使這些資源易于查找的注釋)。 JDK-4513622的重復(fù)錯誤包含提供額外詳細(xì)信息的內(nèi)容。 這些錯誤是JDK-4637640:由于String.substring()實現(xiàn)而導(dǎo)致的內(nèi)存泄漏和JDK-6294060:使用substring()導(dǎo)致了內(nèi)存泄漏 。 其他相關(guān)的在線資源包括Java 7中對String.substring的更改 (其中包括對String.intern()的引用-有更好的方法 ), Java 6與Java 7:當(dāng)實現(xiàn)很重要時 ,以及受到高度評價的(超過350條注釋) Reddit線程TIL Oracle更改了Java 7 Update 6中的內(nèi)部String表示,從而將子字符串方法的運行時間從常量更改為N。
用Java 1.7.0_06進行的更改為String內(nèi)部表示的文章很好地回顧了此更改,并總結(jié)了原始問題,修復(fù)程序以及與該修復(fù)程序相關(guān)的新問題:
現(xiàn)在您可以忘記上面描述的內(nèi)存泄漏,并且永遠不再使用新的String(String)構(gòu)造函數(shù)。 作為缺點,您現(xiàn)在必須記住String.substring現(xiàn)在具有線性復(fù)雜度,而不是恒定的復(fù)雜度。
翻譯自: https://www.javacodegeeks.com/2015/01/reason-for-slower-reading-of-large-lines-in-jdk-7-and-jdk-8.html
總結(jié)
以上是生活随笔為你收集整理的JDK 7和JDK 8中大行读取速度较慢的原因的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 甜茶为什么叫甜茶 叫甜茶的原因
- 下一篇: Spring Stateless Sta