日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

new arraylist内存_如何避免内部类中的内存泄漏

發(fā)布時(shí)間:2024/7/19 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 new arraylist内存_如何避免内部类中的内存泄漏 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

我先假設(shè)讀者已經(jīng)熟悉在Java代碼中使用嵌套類(lèi)的基礎(chǔ)知識(shí)。在本文里,我將展示嵌套類(lèi)的陷阱,內(nèi)部類(lèi)在JVM中引起內(nèi)存泄漏和內(nèi)存不足錯(cuò)誤的地方。之所以會(huì)發(fā)生這種類(lèi)型的內(nèi)存泄漏,是因?yàn)閮?nèi)部類(lèi)必須始終能夠訪(fǎng)問(wèn)其外部類(lèi)。從簡(jiǎn)單的嵌套過(guò)程到內(nèi)存不足錯(cuò)誤(并可能關(guān)閉JVM)是一個(gè)過(guò)程。我們一步步看他是如何產(chǎn)生的。

步驟1:內(nèi)部類(lèi)引用其外部類(lèi)

內(nèi)部類(lèi)的任何實(shí)例都包含對(duì)其外部類(lèi)的隱式引用。例如,考慮以下帶有嵌套的EnclosedClass非靜態(tài)成員類(lèi)的EnclosingClass聲明:

public class EnclosingClass

{

public class EnclosedClass

{

}

}

為了更好地理解這種連接,我們可以將上面的源代碼(javac EnclosingClass.java)編譯為EnclosingClass.class和EnclosingClass $ EnclosedClass.class,然后檢查后者的類(lèi)文件。

JDK包含用于反匯編類(lèi)文件的javap(Java打印)工具。在命令行上,使javap帶有EnclosingClass $ EnclosedClass,如下所示:

javap EnclosingClass$EnclosedClass

我們可以觀(guān)察到以下輸出,該輸出揭示了一個(gè)隱含的 final的 EnclosingClass this $ 0字段,該字段包含對(duì)EnclosingClass的引用:

Compiled from "EnclosingClass.java"

public class EnclosingClass$EnclosedClass {

final EnclosingClass this$0;

public EnclosingClass$EnclosedClass(EnclosingClass);

}

步驟2:構(gòu)造函數(shù)獲取封閉的類(lèi)引用

上面的輸出顯示了帶有EnclosingClass參數(shù)的構(gòu)造函數(shù)。使用-v(詳細(xì))選項(xiàng)執(zhí)行javap,可以觀(guān)察到構(gòu)造函數(shù)在this $ 0字段中保存了EnclosingClass對(duì)象引用:

final EnclosingClass this$0;

descriptor: LEnclosingClass;

flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC

public EnclosingClass$EnclosedClass(EnclosingClass);

descriptor: (LEnclosingClass;)V

flags: (0x0001) ACC_PUBLIC

Code:

stack=2, locals=2, args_size=2

0: aload_0

1: aload_1

2: putfield #1 // Field this$0:LEnclosingClass;

5: aload_0

6: invokespecial #2 // Method java/lang/Object."":()V

9: return

LineNumberTable:

line 3: 0

步驟3:聲明一個(gè)新方法

接下來(lái),我們另一個(gè)類(lèi)中聲明一個(gè)方法,實(shí)例化EnclosingClass,然后實(shí)例化EnclosedClass。例如:

EnclosingClass ec = newEnclosingClass();

ec.newEnclosedClass();

下面的javap輸出顯示了此源代碼的字節(jié)碼轉(zhuǎn)換。第18行顯示對(duì)EnclosingClass $ EnclosedClass(EnclosingClass)的調(diào)用。

0: new #2 // class EnclosingClass

3: dup

4: invokespecial #3 // Method EnclosingClass."":()V

7: astore_1

8: new #4 // class EnclosingClass$EnclosedClass

11: dup

12: aload_1

13: dup

14: invokestatic #5 // Method java/util/Objects.requireNonNull:(Ljava/lang/Object;)Ljava/lang/Object;

17: pop

18: invokespecial #6 // Method EnclosingClass$EnclosedClass."":(LEnclosingClass;)V

21: pop

22: return

內(nèi)存泄漏的解剖

在以上示例中,根據(jù)應(yīng)用程序代碼,可能會(huì)耗盡內(nèi)存并收到內(nèi)存不足錯(cuò)誤,從而導(dǎo)致JVM終止。下面的清單演示了這種情況。

import java.util.ArrayList;

class EnclosingClass

{

private int[] data;

public EnclosingClass(int size)

{

data = new int[size];

}

class EnclosedClass

{

}

EnclosedClass getEnclosedClassObject()

{

return new EnclosedClass();

}

}

public class MemoryLeak

{

public static void main(String[] args)

{

ArrayList al = new ArrayList<>();

int counter = 0;

while (true)

{

al.add(new EnclosingClass(100000).getEnclosedClassObject());

System.out.println(counter++);

}

}

}

EnclosingClass聲明一個(gè)引用整數(shù)數(shù)組的私有數(shù)據(jù)字段。數(shù)組的大小傳遞給此類(lèi)的構(gòu)造函數(shù),并實(shí)例化該數(shù)組。

EnclosingClass還聲明EnclosedClass,一個(gè)嵌套的非靜態(tài)成員類(lèi),以及一個(gè)實(shí)例化EnclosedClass的方法,并返回此實(shí)例。

MemoryLeak的main()方法首先創(chuàng)建一個(gè)java.util.ArrayList來(lái)存儲(chǔ)EnclosingClass.EnclosedClass對(duì)象?,F(xiàn)在,觀(guān)察內(nèi)存泄漏是如何發(fā)生的。

將計(jì)數(shù)器初始化為0后,main()進(jìn)入無(wú)限while循環(huán),該循環(huán)重復(fù)實(shí)例化EnclosedClass并將其添加到數(shù)組列表中。然后打印(或遞增)計(jì)數(shù)器。

每個(gè)存儲(chǔ)的EnclosedClass對(duì)象都維護(hù)對(duì)其外部對(duì)象的引用,該對(duì)象引用100,000個(gè)32位整數(shù)(或400,000字節(jié))的數(shù)組。在對(duì)內(nèi)部對(duì)象進(jìn)行垃圾收集之前,無(wú)法對(duì)外部對(duì)象進(jìn)行垃圾收集。最終,該應(yīng)用程序?qū)⒑谋M內(nèi)存。

javac MemoryLeak.java

java MemoryLeak

我們將觀(guān)察到如下輸出(當(dāng)然在不同的機(jī)器上,最后的數(shù)字可能不一樣):

7639

7640

7641

7642

7643

7644

7645

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

at EnclosingClass.(MemoryLeak.java:9)

at MemoryLeak.main(MemoryLeak.java:30)

往期精選

CHOICENESS

是兄弟,就來(lái)“kan”

總結(jié)

以上是生活随笔為你收集整理的new arraylist内存_如何避免内部类中的内存泄漏的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。