深入理解Java虛擬機器 JVM記憶體洩漏

2021-08-21 16:36:29 字數 1574 閱讀 1477

jvm記憶體洩漏

記憶體洩漏就是存在一些物件沒有被**,這些物件是可達的,但是這些物件是無用的,那麼這些物件就存在記憶體洩漏,即不會被gc**但是卻占用記憶體。

記憶體溢位主要分為以下幾種:  

1.靜態集合類引起記憶體洩漏:像hashmap、vector等的使用最容易出現記憶體洩露,這些靜態變數的生命週期和應用程式一致,他們所引用的所有的物件object也不能被釋放,因為他們也將一直被vector等引用著  

static vector v = new vector(10);

for (int i = 1; i<100; i++)

上面**中,迴圈申請object 物件,並將所申請的物件放入乙個vector 中,如果僅僅釋放引用本身(o=null),那麼vector 仍然引用該物件,所以這個物件對gc來說是不可**的。因此,如果物件加入到vector 後,還必須從vector 中刪除,最簡單的方法就是將vector物件設定為null。

2.當集合裡面的物件屬性被修改後,再呼叫remove()方法時不起作用  

public static void main(string args)

}3.***: 通常乙個應用當中會用到很多***,呼叫乙個控制項的諸如add***listener()等方法來增加***,但往往在釋放物件的時候卻沒有記住去刪除這些***,從而增加了記憶體洩漏的機會  

4.各種連線:比如資料庫連線(datasourse.getconnection()),網路連線(socket)和io連線,除非其顯式的呼叫了其close()方法將其連線關閉,否則是不會自動被gc **的。對於resultset 和statement 物件可以不進行顯式**,但connection 一定要顯式**,因為connection 在任何時候都無法自動**,而connection一旦**,resultset 和statement 物件就會立即為null。但是如果使用連線池,情況就不一樣了,除了要顯式地關閉連線,還必須顯式地關閉resultset statement 物件(關閉其中乙個,另外乙個也會關閉),否則就會造成大量的statement 物件無法釋放,從而引起記憶體洩漏。這種情況下一般都會在try裡面去的連線,在finally裡面釋放連線。  

5.內部類和外部模組的引用:內部類的引用是比較容易遺忘的一種,而且一旦沒釋放可能導致一系列的後繼類物件沒有釋放。此外還要小心外部模組不經意的引用,例如a模組,呼叫了b 模組的乙個方法如: ```public void registermsg(object b);```

這種呼叫就要非常小心了,傳入了乙個物件,很可能模組b就保持了對該物件的引用,這時候就需要注意模組b 是否提供相應的操作去除引用。

6.單例模式:不正確使用單例模式是引起記憶體洩漏的乙個常見問題,單例物件在初始化後將在jvm的整個生命週期中存在(以靜態變數的方式),如果單例物件持有外部的引用,那麼這個物件將不能被jvm正常**,導致記憶體洩漏

class a

....

}//b類採用單例模式

class b

public static b getinstance()

public void seta(a a)

//getter...

} b採用singleton模式,它持有乙個a物件的引用,而這個a類的物件將不能被**

深入理解Java虛擬機器

1.class檔案是一組以8位位元組為基礎單位的二進位製流,各個資料專案嚴格按照順序緊湊地排列在class檔案中,中間沒有新增任何分隔符,這使得整個class檔案中儲存的內容幾乎全部是程式執行的必要資料,沒有空隙存在。當遇上占用8位位元組以上的資料時,按照高位在前的方式分割成若干個8位進行儲存 大端...

深入理解JVM虛擬機器 鎖優化

jvm中使用到的鎖優化技術主要包括 自旋鎖和適應性自旋鎖 鎖消除 鎖粗化 輕量級鎖 偏向鎖 1.自旋鎖和自適應鎖 當乙個執行緒執行耗時小的一小段同步 另乙個執行緒可以不放棄處理器的執行時間,等待看看持有鎖的執行緒是否很快就會釋放鎖,為了使執行緒等待,可以讓執行緒執行忙迴圈 自旋 自適應自旋是指自旋的...

淺入理解JVM虛擬機器

1.類載入過程 驗證 準備 解析 初始化 驗證階段 判斷.class檔案符合規範標準 準備階段 給類以及靜態變數分配記憶體並給初始值 0 解析階段 維護哥哥字段,方法類的記憶體指標或偏移量 初始化階段 變數賦值 真實的值 執行 什麼時候乙個類會進行初始化階段?1.new乙個例項化物件時 2.包含ma...