溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Java中導(dǎo)致內(nèi)存泄漏原因是什么

發(fā)布時(shí)間:2021-11-24 16:13:45 來(lái)源:億速云 閱讀:432 作者:iii 欄目:大數(shù)據(jù)

這篇文章主要講解了“Java中導(dǎo)致內(nèi)存泄漏原因是什么”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“Java中導(dǎo)致內(nèi)存泄漏原因是什么”吧!

一、何為內(nèi)存泄漏

    內(nèi)存泄漏指的是在應(yīng)用程序運(yùn)行周期中內(nèi)存占用持續(xù)性增長(zhǎng)。然而Java的內(nèi)存泄漏更準(zhǔn)確地描述為: 排除外部壓力干擾情況下,在JVM一個(gè)全垃圾回收(Full GC)周期內(nèi),內(nèi)存未能恢復(fù)到初始化內(nèi)存大小并且在多個(gè)全垃圾回收之后內(nèi)存仍持續(xù)性增長(zhǎng),視為內(nèi)存泄漏。

二、為何內(nèi)存泄漏

    Jvm引入垃圾回收機(jī)制,當(dāng)初垃圾回收機(jī)制設(shè)計(jì)的目的是為了解決C、C++編程語(yǔ)言上的需要手動(dòng)釋放內(nèi)存的缺陷(準(zhǔn)確地來(lái)說(shuō)這并不算缺陷,只能說(shuō)是手動(dòng)釋放比較麻煩)??偨Y(jié)GC的運(yùn)行過(guò)程,當(dāng)vm棧對(duì)vm堆中的引用失效之后,GC就會(huì)將vm堆中的此對(duì)象納入回收范圍,只要堆對(duì)象引用一直存在著,GC就不會(huì)進(jìn)行回收。因此當(dāng)對(duì)象使用完畢之后并未打斷引用,就會(huì)導(dǎo)致內(nèi)存泄漏。然而引用為何未被打斷,請(qǐng)看下文《三、 導(dǎo)致內(nèi)存泄漏原因》

三、導(dǎo)致內(nèi)存泄漏原因

    內(nèi)存泄漏的根本原因是引用未被打斷。根據(jù)我個(gè)人經(jīng)驗(yàn),總結(jié)引用未被打斷的原因有以下幾種,如有錯(cuò)漏,敬請(qǐng)諒解

3.1、句柄未關(guān)閉

            句柄,是引用windows操作系統(tǒng)的概念,Linux上稱(chēng)為文件描述符,對(duì)Linux來(lái)說(shuō)Everything Is File(所有東西都是文件)。此處設(shè)計(jì)到句柄的操作類(lèi)有 InputSteam,OuputStream,Socket,Connection...等及其子類(lèi)或者實(shí)現(xiàn)類(lèi)。個(gè)人認(rèn)為,Java中所有實(shí)現(xiàn)了Closable接口的類(lèi)都會(huì)屬于句柄類(lèi)。所有句柄類(lèi)在使用過(guò)后必須要進(jìn)行關(guān)閉,否則將導(dǎo)致句柄泄漏從而引起內(nèi)存泄漏。

        Closabe接口代碼:

        Java中導(dǎo)致內(nèi)存泄漏原因是什么

        Closable接口實(shí)現(xiàn)類(lèi):

        Java中導(dǎo)致內(nèi)存泄漏原因是什么

        舉個(gè)例子: InputStream/FileInputStream

        Java中導(dǎo)致內(nèi)存泄漏原因是什么

        無(wú)內(nèi)存泄漏運(yùn)行代碼結(jié)果:句柄數(shù)200     

     Java中導(dǎo)致內(nèi)存泄漏原因是什么

        有內(nèi)存泄漏運(yùn)行代碼結(jié)果:句柄數(shù)201

       Java中導(dǎo)致內(nèi)存泄漏原因是什么

        原因在于 InputStream實(shí)現(xiàn)了Closable接口,在使用時(shí)未關(guān)閉。因此會(huì)一直占用此句柄,導(dǎo)致內(nèi)存泄漏。

        另外有人問(wèn)線程是否屬于句柄,我在這里告訴你,線程不算句柄,但是啟動(dòng)一個(gè)線程將會(huì)引入大約7個(gè)句柄。請(qǐng)看3.2線程測(cè)試結(jié)果。

3.2、線程未停止

3.2.1、線程,在Java中有獨(dú)立的線程實(shí)現(xiàn),實(shí)現(xiàn)線程有2種方式,第一種是實(shí)現(xiàn)runable接口,第二種是繼承Thread類(lèi)。當(dāng)且僅當(dāng)JVM中正在運(yùn)行的線程數(shù)>0時(shí),JVM會(huì)持續(xù)運(yùn)行。

            3.2.2、線程停止有3種方式

                    3.2.2.1、線程自然結(jié)束,讓線程完成工作之后自然結(jié)束(自然老死)

                    3.2.2.2、調(diào)用線程interrupt方法,另外一個(gè)線程去調(diào)用正在運(yùn)行的線程interrupt方法(被殺)

                    3.2.2.3、調(diào)用線程stop方法,另外一個(gè)線程去調(diào)用正在運(yùn)行的線程stop方法(被殺,此方法已過(guò)期)

                    顯而易見(jiàn),使用線程自然結(jié)束的方式最為和諧。自然結(jié)束代碼如下:

                   Java中導(dǎo)致內(nèi)存泄漏原因是什么

                    另線程持續(xù)運(yùn)行代碼:

                   Java中導(dǎo)致內(nèi)存泄漏原因是什么

                線程未釋放內(nèi)存泄漏代碼:

                Java中導(dǎo)致內(nèi)存泄漏原因是什么

                無(wú)內(nèi)存泄漏運(yùn)行代碼結(jié)果:運(yùn)行之后所有線程結(jié)束,JVM也關(guān)閉了。

             Java中導(dǎo)致內(nèi)存泄漏原因是什么

               有內(nèi)存泄漏運(yùn)行代碼結(jié)果:線程不斷創(chuàng)建,已創(chuàng)建的線程持續(xù)運(yùn)行,內(nèi)存不會(huì)釋放

              Java中導(dǎo)致內(nèi)存泄漏原因是什么

            JVM默認(rèn)啟動(dòng)使用17個(gè)線程,200個(gè)句柄,本例中啟動(dòng)了1000個(gè)線程,線程數(shù)增加到1017個(gè),句柄數(shù)增加到7202個(gè),大約每創(chuàng)建一個(gè)句柄將會(huì)占用7個(gè)句柄,消耗1M內(nèi)存。

3.3、異常未捕捉

Java中引入異常處理概念,可以捕捉各種各樣的異常。適當(dāng)使用異常將有助于提高系統(tǒng)穩(wěn)定性能。

            在3.1描述中,使用了代碼Try...catch...finally 此塊代碼的目的是保證能夠調(diào)用到close方法,避免內(nèi)存泄漏。

            按照良好的編程習(xí)慣,當(dāng)一塊代碼未知運(yùn)行結(jié)果和可能有未知異常時(shí),建議使用 Try...catch...finally語(yǔ)句,避免程序拋出未知異常導(dǎo)致部分資源未被釋放。

            繼續(xù)以3.1為例:

            Java中導(dǎo)致內(nèi)存泄漏原因是什么

              無(wú)內(nèi)存泄漏運(yùn)行代碼結(jié)果:句柄數(shù)200     

         Java中導(dǎo)致內(nèi)存泄漏原因是什么

            有內(nèi)存泄漏運(yùn)行代碼結(jié)果:句柄數(shù)201

           Java中導(dǎo)致內(nèi)存泄漏原因是什么

3.4、使用靜態(tài)集合存儲(chǔ)

                集合作為JVM內(nèi)部的快速存儲(chǔ)方案,使用起來(lái)確實(shí)方便,然而在定義存儲(chǔ)時(shí)使用不當(dāng)也將導(dǎo)致內(nèi)存泄漏,原因就是引用一直存在著。

                Java中導(dǎo)致內(nèi)存泄漏原因是什么

                結(jié)果是顯而易見(jiàn)的!!!

感謝各位的閱讀,以上就是“Java中導(dǎo)致內(nèi)存泄漏原因是什么”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)Java中導(dǎo)致內(nèi)存泄漏原因是什么這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI