<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)存泄露!

          共 7235字,需瀏覽 15分鐘

           ·

          2022-12-22 01:54

          ????關注后回復 “進群” ,拉你進程序員交流群????


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



          1

          簡介


          說明


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


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


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


          解決方案


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

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



          2

          為什么要持有外部類


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


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

          • 當內(nèi)部類持有外部類時,它就可以直接使用外部類中的變量了,這樣可以很方便的完成調(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)字段了。


          比如下邊這樣就會報錯:


          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);
              }
          }


          報錯:




          3

          實例:持有外部類


          代碼


          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ào)試


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




          4

          實例:不持有外部類

           

          代碼


          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ào)試


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




          5

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

           

          簡介


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


          本處在外部類存放大量的數(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++);
                  }
              }
          }


          測試


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



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



          6

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

           

          簡介


          內(nèi)部類改為靜態(tài)的之后,它所引用的對象或?qū)傩砸脖仨毷庆o態(tài)的,所以靜態(tài)內(nèi)部類無法獲得外部對象的引用,只能從 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++);
                  }
              }
          }


          測試


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



          來源:knife.blog.csdn.net/article/details/121108201

          -End-

          最近有一些小伙伴,讓我?guī)兔φ乙恍?nbsp;面試題 資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來,可以說是程序員面試必備!所有資料都整理到網(wǎng)盤了,歡迎下載!

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

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

          瀏覽 19
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <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>
                  国产精品成人娱乐网 | 色婷婷综合网站 | 草逼小视频 | 男女插逼网站 | 国产乱婬A∨片免费观看 |