欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java內(nèi)部類持有外部類導(dǎo)致內(nèi)存泄露的原因與解決方案詳解

 更新時(shí)間:2022年11月23日 11:33:46   作者:IT利刃出鞘  
這篇文章主要為大家詳細(xì)介紹了Java因?yàn)閮?nèi)部類持有外部類導(dǎo)致內(nèi)存泄露的原因以及其解決方案,文中的示例代碼講解詳細(xì),希望對(duì)大家有所幫助

簡(jiǎn)介

說明

本文介紹Java內(nèi)部類持有外部類導(dǎo)致內(nèi)存泄露的原因以及其解決方案。

為什么內(nèi)部類持有外部類會(huì)導(dǎo)致內(nèi)存泄露?

非靜態(tài)內(nèi)部類會(huì)持有外部類,如果有地方引用了這個(gè)非靜態(tài)內(nèi)部類,會(huì)導(dǎo)致外部類也被引用,垃圾回收時(shí)無法回收這個(gè)外部類(即使外部類已經(jīng)沒有其他地方在使用了)。

解決方案

1.不要讓其他的地方持有這個(gè)非靜態(tài)內(nèi)部類的引用,直接在這個(gè)非靜態(tài)內(nèi)部類執(zhí)行業(yè)務(wù)。

2.將非靜態(tài)內(nèi)部類改為靜態(tài)內(nèi)部類。

內(nèi)部類改為靜態(tài)的之后,它所引用的對(duì)象或?qū)傩砸脖仨毷庆o態(tài)的,所以靜態(tài)內(nèi)部類無法獲得外部對(duì)象的引用,只能從 JVM 的 Method Area(方法區(qū))獲取到static類型的引用。

相關(guān)網(wǎng)址

匿名內(nèi)部類的內(nèi)存泄露:Java的匿名內(nèi)部類導(dǎo)致內(nèi)存泄露--原因/解決方案

為什么要持有外部類

Java 語(yǔ)言中,非靜態(tài)內(nèi)部類的主要作用有兩個(gè):

當(dāng)內(nèi)部類只在外部類中使用時(shí),匿名內(nèi)部類可以讓外部不知道它的存在,從而減少了代碼的維護(hù)工作。

當(dāng)內(nèi)部類持有外部類時(shí),它就可以直接使用外部類中的變量了,這樣可以很方便的完成調(diào)用,如下代碼所示:

package org.example.a;
 
class Outer{
    private String outerName = "Tony";
 
    class Inner{
        private String name;
 
        public Inner() {
            this.name = outerName;
        }
    }
 
    Inner createInner() {
        return new Inner();
    }
}
 
public class Demo {
    public static void main(String[] args) {
        Outer.Inner inner = new Outer().createInner();
        System.out.println(inner);
    }
}

但是,靜態(tài)內(nèi)部類就無法持有外部類和其非靜態(tài)字段了。比如下邊這樣就會(huì)報(bào)錯(cuò)

package org.example.a;
 
class Outer{
    private String outerName = "Tony";
 
    static class Inner{
        private String name;
 
        public Inner() {
            this.name = outerName;
        }
    }
 
    Inner createInner() {
        return new Inner();
    }
}
 
public class Demo {
    public static void main(String[] args) {
        Outer.Inner inner = new Outer().createInner();
        System.out.println(inner);
    }
}

報(bào)錯(cuò): 

實(shí)例:持有外部類

代碼

package org.example.a;
 
class Outer{
    class Inner {
 
    }
 
    Inner createInner() {
        return new Inner();
    }
}
 
public class Demo {
    public static void main(String[] args) {
        Outer.Inner inner = new Outer().createInner();
        System.out.println(inner);
    }
}

斷點(diǎn)調(diào)試

可以看到:內(nèi)部類持有外部類的對(duì)象的引用,是以“this$0”這個(gè)字段來保存的。  

實(shí)例:不持有外部類

代碼

package org.example.a;
 
class Outer{
    static class Inner {
 
    }
 
    Inner createInner() {
        return new Inner();
    }
}
 
public class Demo {
    public static void main(String[] args) {
        Outer.Inner inner = new Outer().createInner();
        System.out.println(inner);
    }
}

斷點(diǎn)調(diào)試

可以發(fā)現(xiàn):內(nèi)部類不再持有外部類了。

實(shí)例:內(nèi)存泄露

簡(jiǎn)介

若內(nèi)部類持有外部類的引用,對(duì)內(nèi)部類的使用很多時(shí),會(huì)導(dǎo)致外部類數(shù)目很多。此時(shí),就算是外部類的數(shù)據(jù)沒有被用到,外部類的數(shù)據(jù)所占空間也不會(huì)被釋放。

本處在外部類存放大量的數(shù)據(jù)來模擬。

代碼

package org.example.a;
 
import java.util.ArrayList;
import java.util.List;
 
class Outer{
    private int[] data;
 
    public Outer(int size) {
        this.data = new int[size];
    }
 
    class Innner{
 
    }
 
    Innner createInner() {
        return new Innner();
    }
}
 
public class Demo {
    public static void main(String[] args) {
        List<Object> list = new ArrayList<>();
        int counter = 0;
        while (true) {
            list.add(new Outer(100000).createInner());
            System.out.println(counter++);
        }
    }
}

測(cè)試

可以看到:運(yùn)行了八千多次的時(shí)候就內(nèi)存溢出了。

不會(huì)內(nèi)存泄露的方案

簡(jiǎn)介

內(nèi)部類改為靜態(tài)的之后,它所引用的對(duì)象或?qū)傩砸脖仨毷庆o態(tài)的,所以靜態(tài)內(nèi)部類無法獲得外部對(duì)象的引用,只能從 JVM 的 Method Area(方法區(qū))獲取到static類型的引用。

代碼 

package org.example.a;
 
import java.util.ArrayList;
import java.util.List;
 
class Outer{
    private int[] data;
 
    public Outer(int size) {
        this.data = new int[size];
    }
 
    static class Inner {
 
    }
 
    Inner createInner() {
        return new Inner();
    }
}
 
public class Demo {
    public static void main(String[] args) {
        List<Object> list = new ArrayList<>();
        int counter = 0;
        while (true) {
            list.add(new Outer(100000).createInner());
            System.out.println(counter++);
        }
    }
}

測(cè)試

可以發(fā)現(xiàn):循環(huán)了四十多萬次都沒有內(nèi)存溢出。

以上就是Java內(nèi)部類持有外部類導(dǎo)致內(nèi)存泄露的原因與解決方案詳解的詳細(xì)內(nèi)容,更多關(guān)于Java內(nèi)存泄露的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java如何多線程批量更新10萬級(jí)的數(shù)據(jù)

    java如何多線程批量更新10萬級(jí)的數(shù)據(jù)

    在處理大數(shù)據(jù)量的批量更新時(shí),直接使用mybatis的updateBatch可能導(dǎo)致效率低下甚至OOM,通過每次處理5000條數(shù)據(jù)的方式雖然安全但效率低,更優(yōu)的解決方案是使用多線程處理,將數(shù)據(jù)分批并多線程執(zhí)行,有效提高了處理速度并保證了系統(tǒng)穩(wěn)定性
    2024-10-10
  • Mybatis傳入List實(shí)現(xiàn)批量更新的示例代碼

    Mybatis傳入List實(shí)現(xiàn)批量更新的示例代碼

    這篇文章主要介紹了Mybatis傳入List實(shí)現(xiàn)批量更新的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • springboot返回html和jsp的方法示例

    springboot返回html和jsp的方法示例

    這篇文章主要介紹了springboot返回html和jsp的方法示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Spring Boot 與 Kotlin 使用Redis數(shù)據(jù)庫(kù)的配置方法

    Spring Boot 與 Kotlin 使用Redis數(shù)據(jù)庫(kù)的配置方法

    Redis是目前業(yè)界使用最廣泛的內(nèi)存數(shù)據(jù)存儲(chǔ)。下面通過本文給大家介紹Spring Boot 與 Kotlin 使用Redis數(shù)據(jù)庫(kù)的配置方法,感興趣的朋友一起看看吧
    2018-01-01
  • Java 將文件轉(zhuǎn)為字節(jié)數(shù)組知識(shí)總結(jié)及實(shí)例詳解

    Java 將文件轉(zhuǎn)為字節(jié)數(shù)組知識(shí)總結(jié)及實(shí)例詳解

    這篇文章主要介紹了Java 將文件轉(zhuǎn)為字節(jié)數(shù)組實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2016-12-12
  • Java并發(fā)編程示例(十):線程組

    Java并發(fā)編程示例(十):線程組

    這篇文章主要介紹了Java并發(fā)編程示例(十):線程組,Java提供了ThreadGroup類來控制一個(gè)線程組,一個(gè)線程組可以通過線程對(duì)象來創(chuàng)建,也可以由其他線程組來創(chuàng)建,生成一個(gè)樹形結(jié)構(gòu)的線程,需要的朋友可以參考下
    2014-12-12
  • Eclipse 出現(xiàn)A configuration with this name already exists問題解決方法

    Eclipse 出現(xiàn)A configuration with this name already exists問題解決方

    這篇文章主要介紹了Eclipse 出現(xiàn)A configuration with this name already exists問題解決方法的相關(guān)資料,需要的朋友可以參考下
    2016-11-11
  • JavaSwing實(shí)現(xiàn)小型學(xué)生管理系統(tǒng)

    JavaSwing實(shí)現(xiàn)小型學(xué)生管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了JavaSwing實(shí)現(xiàn)小型學(xué)生管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • springboot zuul實(shí)現(xiàn)網(wǎng)關(guān)的代碼

    springboot zuul實(shí)現(xiàn)網(wǎng)關(guān)的代碼

    這篇文章主要介紹了springboot zuul實(shí)現(xiàn)網(wǎng)關(guān)的代碼,在為服務(wù)架構(gòu)體系里,網(wǎng)關(guān)是非常重要的環(huán)節(jié),他實(shí)現(xiàn)了很多功能,具體哪些功能大家跟隨小編一起通過本文學(xué)習(xí)吧
    2018-10-10
  • 使用Java的Lucene搜索工具對(duì)檢索結(jié)果進(jìn)行分組和分頁(yè)

    使用Java的Lucene搜索工具對(duì)檢索結(jié)果進(jìn)行分組和分頁(yè)

    這篇文章主要介紹了使用Java的搜索工具Lucene對(duì)檢索結(jié)果進(jìn)行分組和分頁(yè)的方法,Luence是Java環(huán)境中的一個(gè)全文檢索引擎工具包,需要的朋友可以參考下
    2016-03-03

最新評(píng)論