亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java中由substring方法引發(fā)的內(nèi)存泄漏詳解

 更新時間:2017年12月26日 13:49:01   作者:土肥圓的猿  
這篇文章主要介紹了Java中由substring方法引發(fā)的內(nèi)存泄漏詳解,涉及substring方法引發(fā)的內(nèi)存泄漏簡介,substring的作用和實現(xiàn)原理等相關(guān)內(nèi)容,具有一定借鑒價值,需要的朋友可以參考下

內(nèi)存溢出(out of memory ) :通俗的說就是內(nèi)存不夠用了,比如在一個無限循環(huán)中不斷創(chuàng)建一個大的對象,很快就會引發(fā)內(nèi)存溢出。

內(nèi)存泄漏(leak of memory) :是指為一個對象分配內(nèi)存之后,在對象已經(jīng)不在使用時未及時的釋放,導(dǎo)致一直占據(jù)內(nèi)存單元,使實際可用內(nèi)存減少,就好像內(nèi)存泄漏了一樣。

由substring方法引發(fā)的內(nèi)存泄漏

substring(int beginIndex, int endndex )是String類的一個方法,但是這個方法在JDK6和JDK7中的實現(xiàn)是完全不同的(雖然它們都達到了同樣的效果)。了解它們實現(xiàn)細節(jié)上的差異,能夠更好的幫助你使用它們,因為在JDK1.6中不當(dāng)使用substring會導(dǎo)致嚴重的內(nèi)存泄漏問題。

1、substring的作用

substring(int beginIndex, int endIndex)方法返回一個子字符串,從父字符串的beginIndex開始,結(jié)束于endindex-1。父字符串的下標(biāo)從0開始,子字符串包含beginIndex而不包含endIndex

String x= "abcdef";
x= str.substring(1,3);
System.out.println(x);

上述程序的輸出是“bc”

2、實現(xiàn)原理

String類是不可變變,當(dāng)上述第二句中x被重新賦值的時候,它會指向一個新的字符串對象。然而,沒有準(zhǔn)確說明的或者代表堆中發(fā)生的實際情況,當(dāng)substring被調(diào)用的時候真正發(fā)生的才是這兩者的差別。

JDK6中的substring實現(xiàn)

String對象被當(dāng)作一個char數(shù)組來存儲,在String類中有3個域:char[] value、int offset、int count,分別用來存儲真實的字符數(shù)組,數(shù)組的起始位置,String的字符數(shù)。由這3個變量就可以決定一個字符串。當(dāng)substring方法被調(diào)用的時候,它會創(chuàng)建一個新的字符串,但是上述的char數(shù)組value仍然會使用原來父數(shù)組的那個value。父數(shù)組和子數(shù)組的唯一差別就是count和offset的值不一樣。

看一下JDK6中substring的實現(xiàn)源碼:

public String substring(int beginIndex, int endIndex) {
 if (beginIndex < 0) {
 throw new StringIndexOutOfBoundsException(beginIndex);
 }
 if (endIndex > count) {
 throw new StringIndexOutOfBoundsException(endIndex);
 }
 if (beginIndex > endIndex) {
 throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
 }
 return ((beginIndex == 0) && (endIndex == count)) ? this :
 new String(offset + beginIndex, endIndex - beginIndex, value); //使用的是和父字符串同一個char數(shù)組value
 }
String(int offset, int count, char value[]) {
 this.value = value;
 this.offset = offset;
 this.count = count;
 }
String str = "abcdefghijklmnopqrst";
String sub = str.substring(1, 3);
str = null;

這段簡單的程序有兩個字符串變量str、sub。sub字符串是由父字符串str截取得到的,假如上述這段程序在JDK1.6中運行,我們知道數(shù)組的內(nèi)存空間分配是在堆上進行的,那么sub和str的內(nèi)部char數(shù)組value是公用了同一個,也就是上述有字符a~字符t組成的char數(shù)組,str和sub唯一的差別就是在數(shù)組中其實beginIndex和字符長度count的不同。在第三句,我們使str引用為空,本意是釋放str占用的空間,但是這個時候,GC是無法回收這個大的char數(shù)組的,因為還在被sub字符串內(nèi)部引用著,雖然sub只截取這個大數(shù)組的一小部分。當(dāng)str是一個非常大字符串的時候,這種浪費是非常明顯的,甚至?xí)硇阅軉栴},解決這個問題可以是通過以下的方法:

利用的就是字符串的拼接技術(shù),它會創(chuàng)建一個新的字符串,這個新的字符串會使用一個新的內(nèi)部char數(shù)組存儲自己實際需要的字符,這樣父數(shù)組的char數(shù)組就不會被其他引用,令str=null,在下一次GC回收的時候會回收整個str占用的空間。但是這樣書寫很明顯是不好看的,所以在JDK7中,substring 被重新實現(xiàn)了。

JDK7中的substring實現(xiàn)

在JDK7中改進了substring的實現(xiàn),它實際是為截取的子字符串在堆中創(chuàng)建了一個新的char數(shù)組用于保存子字符串的字符。

查看JDK7中String類的substring方法的實現(xiàn)源碼:

public String substring(int beginIndex, int endIndex) {
 if (beginIndex < 0) {
 throw new StringIndexOutOfBoundsException(beginIndex);
 }
 if (endIndex > value.length) {
 throw new StringIndexOutOfBoundsException(endIndex);
 }
 int subLen = endIndex - beginIndex;
 if (subLen < 0) {
 throw new StringIndexOutOfBoundsException(subLen);
 }
 return ((beginIndex == 0) && (endIndex == value.length)) ? this
 : new String(value, beginIndex, subLen);
 }
public String(char value[], int offset, int count) {
 if (offset < 0) {
 throw new StringIndexOutOfBoundsException(offset);
 }
 if (count < 0) {
 throw new StringIndexOutOfBoundsException(count);
 }
 // Note: offset or count might be near -1>>>1.
 if (offset > value.length - count) {
 throw new StringIndexOutOfBoundsException(offset + count);
 }
 this.value = Arrays.copyOfRange(value, offset, offset+count);
 }

Arrays類的copyOfRange方法:

public static char[] copyOfRange(char[] original, int from, int to) {
 int newLength = to - from;
 if (newLength < 0)
  throw new IllegalArgumentException(from + " > " + to);
 char[] copy = new char[newLength]; //是創(chuàng)建了一個新的char數(shù)組
 System.arraycopy(original, from, copy, 0,
    Math.min(original.length - from, newLength));
 return copy;
 }

可以發(fā)現(xiàn)是去為子字符串創(chuàng)建了一個新的char數(shù)組去存儲子字符串中的字符。這樣子字符串和父字符串也就沒有什么必然的聯(lián)系了,當(dāng)父字符串的引用失效的時候,GC就會適時的回收父字符串占用的內(nèi)存空間。

總結(jié)

以上就是本文關(guān)于Java中由substring方法引發(fā)的內(nèi)存泄漏詳解的全部內(nèi)容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!

相關(guān)文章

  • Spring框架web項目實戰(zhàn)全代碼分享

    Spring框架web項目實戰(zhàn)全代碼分享

    這篇文章主要介紹了Spring框架web項目實戰(zhàn)全代碼分享,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11
  • SpringBoot接口正確接收時間參數(shù)的幾種方式

    SpringBoot接口正確接收時間參數(shù)的幾種方式

    這篇文章主要給大家介紹了關(guān)于SpringBoot接口正確接收時間參數(shù)的相關(guān)資料,文中通過代碼示例介紹的非常詳細,對大家學(xué)習(xí)或者使用springboot具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-09-09
  • Spring?BeanDefinition父子關(guān)系示例解析

    Spring?BeanDefinition父子關(guān)系示例解析

    這篇文章主要為大家介紹了Spring?BeanDefinition父子關(guān)系示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-08-08
  • java面向?qū)ο缶幊填惖膬?nèi)聚性分析

    java面向?qū)ο缶幊填惖膬?nèi)聚性分析

    高內(nèi)聚、低耦合是軟件設(shè)計中非常關(guān)鍵的概念。在面向?qū)ο蟪绦蛟O(shè)計中類的劃分時,類的內(nèi)聚性越高,其封裝性越好,越容易復(fù)用
    2021-10-10
  • Java File類的簡單使用教程(創(chuàng)建、刪除、遍歷與判斷是否存在等)

    Java File類的簡單使用教程(創(chuàng)建、刪除、遍歷與判斷是否存在等)

    這篇文章主要給大家介紹了關(guān)于Java File類的簡單使用(創(chuàng)建、刪除、遍歷與判斷是否存在等)的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • 一個簡易的Java多頁面隊列爬蟲程序

    一個簡易的Java多頁面隊列爬蟲程序

    這篇文章主要為大家詳細介紹了一個多頁面的java爬蟲,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-08-08
  • Java實現(xiàn)快速冪算法詳解

    Java實現(xiàn)快速冪算法詳解

    快速冪是用來解決求冪運算的高效方式。此算法偶爾會出現(xiàn)在筆試以及面試中,特意花時間研究了下這題,感興趣的小伙伴快跟隨小編一起學(xué)習(xí)一下
    2022-10-10
  • Java利用三目運算符比較三個數(shù)字的大小

    Java利用三目運算符比較三個數(shù)字的大小

    今天小編就為大家分享一篇關(guān)于Java利用三目運算符比較三個數(shù)字的大小,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • Python實現(xiàn)filter函數(shù)實現(xiàn)字符串切分

    Python實現(xiàn)filter函數(shù)實現(xiàn)字符串切分

    這篇文章主要介紹了Python實現(xiàn)filter函數(shù)實現(xiàn)字符串切分,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-03-03
  • MyBatis綁定錯誤提示BindingException:Invalid bound statement (not found)的解決方法

    MyBatis綁定錯誤提示BindingException:Invalid bound statement (not f

    這篇文章主要介紹了MyBatis綁定錯誤提示BindingException:Invalid bound statement (not found)的解決辦法,非常不錯,具有參考借鑒價值,需要的的朋友參考下吧
    2017-01-01

最新評論