<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Java 內(nèi)部類有坑,100 % 內(nèi)存泄露!

          共 4967字,需瀏覽 10分鐘

           ·

          2022-12-20 01:47

          今天給大家分享一種,Java內(nèi)部類使用不當(dāng)導(dǎo)致的內(nèi)存泄露問(wèn)題,最終導(dǎo)致內(nèi)存溢出!希望能夠幫助到大家!



          1

          簡(jiǎn)介


          說(shuō)明


          本文介紹 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í)無(wú)法回收這個(gè)外部類(即使外部類已經(jīng)沒有其他地方在使用了)。


          解決方案


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

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



          2

          為什么要持有外部類


          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)部類就無(wú)法持有外部類和其非靜態(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ò):


          771911f0f0c43fad4c648721ad3b2eda.webp



          3

          實(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è)字段來(lái)保存的。


          89e3c09ce84b768ea5670023c16b2e8a.webp



          4

          實(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)部類不再持有外部類了。


          02d95d1206f65a9804dd19c794ccd560.webp



          5

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

          ?

          簡(jiǎn)介


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


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


          代碼


                
                  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)存溢出了。


          ba0f5a01752becda0f270d7967f06271.webp


          我換了一臺(tái) mac 電腦,4000 多就內(nèi)存溢出了。



          6

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

          ?

          簡(jiǎn)介


          內(nèi)部類改為靜態(tài)的之后,它所引用的對(duì)象或?qū)傩砸脖仨毷庆o態(tài)的,所以靜態(tài)內(nèi)部類無(wú)法獲得外部對(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)了四十多萬(wàn)次都沒有內(nèi)存溢出。


          1ea7db8d721544a7c9bd4c3ce5ddf2ce.webp


          來(lái)源:knife.blog.csdn.net/article/details/121108201


          瀏覽 82
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产视频情| 国产野外在线播放 | 日日夜夜大香蕉 | 欧美xxx亚洲 | 亚洲AV成人无码一区二区三区 |