您好,登錄后才能下訂單哦!
這篇文章主要講解了“Java中導致內存泄漏原因是什么”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Java中導致內存泄漏原因是什么”吧!
內存泄漏指的是在應用程序運行周期中內存占用持續性增長。然而Java的內存泄漏更準確地描述為: 排除外部壓力干擾情況下,在JVM一個全垃圾回收(Full GC)周期內,內存未能恢復到初始化內存大小并且在多個全垃圾回收之后內存仍持續性增長,視為內存泄漏。
Jvm引入垃圾回收機制,當初垃圾回收機制設計的目的是為了解決C、C++編程語言上的需要手動釋放內存的缺陷(準確地來說這并不算缺陷,只能說是手動釋放比較麻煩)。總結GC的運行過程,當vm棧對vm堆中的引用失效之后,GC就會將vm堆中的此對象納入回收范圍,只要堆對象引用一直存在著,GC就不會進行回收。因此當對象使用完畢之后并未打斷引用,就會導致內存泄漏。然而引用為何未被打斷,請看下文《三、 導致內存泄漏原因》
內存泄漏的根本原因是引用未被打斷。根據我個人經驗,總結引用未被打斷的原因有以下幾種,如有錯漏,敬請諒解
句柄,是引用windows操作系統的概念,Linux上稱為文件描述符,對Linux來說Everything Is File(所有東西都是文件)。此處設計到句柄的操作類有 InputSteam,OuputStream,Socket,Connection...等及其子類或者實現類。個人認為,Java中所有實現了Closable接口的類都會屬于句柄類。所有句柄類在使用過后必須要進行關閉,否則將導致句柄泄漏從而引起內存泄漏。
Closabe接口代碼:
Closable接口實現類:
舉個例子: InputStream/FileInputStream
無內存泄漏運行代碼結果:句柄數200
有內存泄漏運行代碼結果:句柄數201
原因在于 InputStream實現了Closable接口,在使用時未關閉。因此會一直占用此句柄,導致內存泄漏。
另外有人問線程是否屬于句柄,我在這里告訴你,線程不算句柄,但是啟動一個線程將會引入大約7個句柄。請看3.2線程測試結果。
3.2.1、線程,在Java中有獨立的線程實現,實現線程有2種方式,第一種是實現runable接口,第二種是繼承Thread類。當且僅當JVM中正在運行的線程數>0時,JVM會持續運行。
3.2.2、線程停止有3種方式
3.2.2.1、線程自然結束,讓線程完成工作之后自然結束(自然老死)
3.2.2.2、調用線程interrupt方法,另外一個線程去調用正在運行的線程interrupt方法(被殺)
3.2.2.3、調用線程stop方法,另外一個線程去調用正在運行的線程stop方法(被殺,此方法已過期)
顯而易見,使用線程自然結束的方式最為和諧。自然結束代碼如下:
另線程持續運行代碼:
線程未釋放內存泄漏代碼:
無內存泄漏運行代碼結果:運行之后所有線程結束,JVM也關閉了。
有內存泄漏運行代碼結果:線程不斷創建,已創建的線程持續運行,內存不會釋放
JVM默認啟動使用17個線程,200個句柄,本例中啟動了1000個線程,線程數增加到1017個,句柄數增加到7202個,大約每創建一個句柄將會占用7個句柄,消耗1M內存。
Java中引入異常處理概念,可以捕捉各種各樣的異常。適當使用異常將有助于提高系統穩定性能。
在3.1描述中,使用了代碼Try...catch...finally 此塊代碼的目的是保證能夠調用到close方法,避免內存泄漏。
按照良好的編程習慣,當一塊代碼未知運行結果和可能有未知異常時,建議使用 Try...catch...finally語句,避免程序拋出未知異常導致部分資源未被釋放。
繼續以3.1為例:
無內存泄漏運行代碼結果:句柄數200
有內存泄漏運行代碼結果:句柄數201
集合作為JVM內部的快速存儲方案,使用起來確實方便,然而在定義存儲時使用不當也將導致內存泄漏,原因就是引用一直存在著。
結果是顯而易見的!!!
感謝各位的閱讀,以上就是“Java中導致內存泄漏原因是什么”的內容了,經過本文的學習后,相信大家對Java中導致內存泄漏原因是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。