最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺談Java內(nèi)存泄露

 更新時(shí)間:2019年05月23日 14:15:16   作者:純潔的微笑  
內(nèi)存泄漏(Memory Leak)是指程序中己動態(tài)分配的堆內(nèi)存由于某種原因程序未釋放或無法釋放,造成系統(tǒng)內(nèi)存的浪費(fèi),導(dǎo)致程序運(yùn)行速度減慢甚至系統(tǒng)崩潰等嚴(yán)重后果。下面我們來一起了解如何解決

納尼,Java 不是自動管理內(nèi)存嗎?怎么可能會出現(xiàn)內(nèi)存泄泄泄泄泄泄漏!

Java 最牛逼的一個特性就是垃圾回收機(jī)制,不用像 C++ 需要手動管理內(nèi)存,所以作為 Java 程序員很幸福,只管 New New New 即可,反正 Java 會自動回收過期的對象。。。

那么 Java 都自動管理內(nèi)存了,那怎么會出現(xiàn)內(nèi)存泄漏,難道 Jvm 有 bug? 不要急,且聽我慢慢道來。。

怎么判斷可以被回收

先了解一下 Jvm 是怎么判斷一個對象可以被回收。一般有兩種方式,一種是引用計(jì)數(shù)法,一種是可達(dá)性分析。

引用計(jì)數(shù)法:每個對象有一個引用計(jì)數(shù)屬性,新增一個引用時(shí)計(jì)數(shù)加1,引用釋放時(shí)計(jì)數(shù)減1,計(jì)數(shù)為0時(shí)可以回收。

這個辦法看起來挺簡單的,但是如果出現(xiàn) A 引用了 B,B 又引用了 A,這時(shí)候就算他們都不再使用了,但因?yàn)橄嗷ヒ?計(jì)算器=1 永遠(yuǎn)無法被回收。

此方法簡單,無法解決對象相互循環(huán)引用的問題。

可達(dá)性分析(Reachability Analysis):從 GC Roots 開始向下搜索,搜索所走過的路徑稱為引用鏈。當(dāng)一個對象到 GC Roots 沒有任何引用鏈相連時(shí),則證明此對象是不可用的,那么虛擬機(jī)就判斷是可回收對象。

可達(dá)性分析可以解決循環(huán)引用的問題。

那么 gc roots 對象是哪些呢

  • 虛擬機(jī)棧中引用的對象
  • 方法區(qū)中類靜態(tài)屬性引用的對象
  • 方法區(qū)中常量引用的對象
  • 本地方法棧中JNI[即一般說的Native]引用的對象

目前主流的虛擬機(jī)中大多使用可達(dá)性分析的方式來判定對象是否可被 GC 回收。

什么情況下會出現(xiàn)內(nèi)存泄漏

既然可達(dá)性分析好像已經(jīng)很牛逼的樣子了,怎么可能還會出現(xiàn)內(nèi)存泄漏呢,那我們再來看一下內(nèi)存泄漏的定義。

內(nèi)存泄露就是指一個不再被程序使用的對象或變量一直被占據(jù)在內(nèi)存中。

有可能此對象已經(jīng)不使用了,但是還有其它對象保持著此對象的引用,就會導(dǎo)致 GC 不能回收此對象,這種情況下就會出現(xiàn)內(nèi)存泄漏。

寫一個程序讓出現(xiàn)內(nèi)存泄漏

①長生命周期的對象持有短生命周期對象的引用就很可能發(fā)生內(nèi)存泄露,盡管短生命周期對象已經(jīng)不再需要,但是因?yàn)殚L生命周期對象持有它的引用而導(dǎo)致不能被回收。

public class Simple {
 Object object;
 public void method1(){
 object = new Object();
 //...其他代碼
 }
}

這里的 object 實(shí)例,其實(shí)我們期望它只作用于 method1() 方法中,且其他地方不會再用到它,但是,當(dāng)method1()方法執(zhí)行完成后,object 對象所分配的內(nèi)存不會馬上被認(rèn)為是可以被釋放的對象,只有在 Simple 類創(chuàng)建的對象被釋放后才會被釋放,嚴(yán)格的說,這就是一種內(nèi)存泄露。

解決方法就是將 object 作為 method1() 方法中的局部變量。

public class Simple {
 Object object;
 public void method1(){
 object = new Object();
 //...其他代碼
 object = null;
 }
}

當(dāng)然大家有可能會想就這一個方法也不會有多大影響,但如果在某些項(xiàng)目中,一個方法在一分鐘之內(nèi)調(diào)用上萬次的時(shí)候,就會出現(xiàn)很明顯的內(nèi)存泄漏現(xiàn)象。

②集合中的內(nèi)存泄漏,比如 HashMap、ArrayList 等,這些對象經(jīng)常會發(fā)生內(nèi)存泄露。比如當(dāng)它們被聲明為靜態(tài)對象時(shí),它們的生命周期會跟應(yīng)用程序的生命周期一樣長,很容易造成內(nèi)存不足。

下面給出了一個關(guān)于集合內(nèi)存泄露的例子。

Vector v=new Vector(10);
for (int i=1;i<100; i++)
{
 Object o=new Object();
 v.add(o);
 o=null;
}
//此時(shí),所有的Object對象都沒有被釋放,因?yàn)樽兞縱引用這些對象。

在這個例子中,我們循環(huán)申請 Object 對象,并將所申請的對象放入一個 Vector 中,如果我們僅僅釋放引用本身,那么 Vector 仍然引用該對象,所以這個對象對 GC 來說是不可回收的。

因此,如果對象加入到 Vector 后,還必須從 Vector 中刪除,最簡單的方法就是將 Vector 對象設(shè)置為 null。

以上兩種是最常見的內(nèi)存泄漏案例。當(dāng)然還有一些內(nèi)存泄漏的例子,這里就不再一一例舉了,感興趣的同學(xué)可以在網(wǎng)上找找資料。

內(nèi)存泄漏和內(nèi)存溢出

很多同學(xué)總是搞不清楚,內(nèi)存泄漏和內(nèi)存溢出的區(qū)別,它倆是兩個完全不同的概念, 它們之間存在一些關(guān)聯(lián)。

內(nèi)存溢出 out of memory,是指程序在申請內(nèi)存時(shí),沒有足夠的內(nèi)存空間供其使用,出現(xiàn) out of memory;

內(nèi)存泄露 memory leak,是指程序在申請內(nèi)存后,無法釋放已申請的內(nèi)存空間,一次內(nèi)存泄露危害可以忽略,但內(nèi)存泄露堆積后果很嚴(yán)重,無論多少內(nèi)存,遲早會被占光。

所以內(nèi)存泄漏可能會導(dǎo)致內(nèi)存溢出,但內(nèi)存溢出并不完全都是因?yàn)閮?nèi)存泄漏,也有可能使用了太多的大對象導(dǎo)致。

如何檢測內(nèi)存泄漏

最后一個重要的問題,就是如何檢測 Java 的內(nèi)存泄漏。目前,我們通常使用一些工具來檢查 Java 程序的內(nèi)存泄漏問題。

市場上已有幾種專業(yè)檢查 Java 內(nèi)存泄漏的工具,它們的基本工作原理大同小異,都是通過監(jiān)測 Java 程序運(yùn)行時(shí),所有對象的申請、釋放等動作,將內(nèi)存管理的所有信息進(jìn)行統(tǒng)計(jì)、分析、可視化。開發(fā)人員將根據(jù)這些信息判斷程序是否有內(nèi)存泄漏問題。

這些工具包括 Plumbr 、Eclipse Memory Analyzer、JProbe Profiler、JVisualVM 等。

最后

以上內(nèi)容其實(shí)是我曾經(jīng)經(jīng)常面試的內(nèi)容之一,通過一系列的問題考察 Java 程序員對 Jvm 的理解。

比如我通常會問面試者,Java 中存在內(nèi)存泄漏嗎?大部分人都會回答存在,接著我會問如果讓你寫一個程序讓內(nèi)存泄漏,你會怎么寫?大部分程序員就回答不上來了。

如果面試者可以回答上面的問題,我會接著和面試者聊聊,內(nèi)存泄漏和內(nèi)存溢出他們之間是否存在聯(lián)系 、以及在日常工作中如何避免寫出內(nèi)存泄漏的代碼 、如果生產(chǎn)出現(xiàn) Jvm 相關(guān)問題時(shí),排查問題的思路和步驟等等。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java?DelayQueue實(shí)現(xiàn)任務(wù)延時(shí)示例講解

    Java?DelayQueue實(shí)現(xiàn)任務(wù)延時(shí)示例講解

    DelayQueue是一個無界的BlockingQueue的實(shí)現(xiàn)類,用于放置實(shí)現(xiàn)了Delayed接口的對象,其中的對象只能在其到期時(shí)才能從隊(duì)列中取走。本文就來利用DelayQueue實(shí)現(xiàn)延時(shí)任務(wù),感興趣的可以了解一下
    2022-09-09
  • Java 中 Date 與 Calendar 之間的編輯與轉(zhuǎn)換實(shí)例詳解

    Java 中 Date 與 Calendar 之間的編輯與轉(zhuǎn)換實(shí)例詳解

    這篇文章主要介紹了Java 中 Date 與 Calendar 之間的編輯與轉(zhuǎn)換 ,非常不錯,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-07-07
  • Java?File類的概述及常用方法使用詳解

    Java?File類的概述及常用方法使用詳解

    Java?File類的功能非常強(qiáng)大,下面這篇文章主要給大家介紹了關(guān)于Java中File類的概述及常用方法使用,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-09-09
  • java多線程編程之管道通信詳解

    java多線程編程之管道通信詳解

    這篇文章主要為大家詳細(xì)介紹了java多線程編程之線程間的通信,探討使用管道進(jìn)行通信,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • 解決SpringMVC獲取請求參數(shù)亂碼問題

    解決SpringMVC獲取請求參數(shù)亂碼問題

    在使用SpringMVC和thymeleaf進(jìn)行請求參數(shù)處理時(shí),可能會遇到亂碼問題,對于GET方法亂碼,可通過修改Tomcat的server.xml文件,添加URIEncoding="UTF-8"解決,而POST方法亂碼,則需在web.xml配置SpringMVC提供的過濾器
    2024-11-11
  • spring aop底層源碼執(zhí)行邏輯剖析(源碼解析)

    spring aop底層源碼執(zhí)行邏輯剖析(源碼解析)

    這篇文章主要介紹了spring aop底層源碼執(zhí)行邏輯剖析,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2024-08-08
  • 詳解Servlet 3.0/3.1 中的異步處理

    詳解Servlet 3.0/3.1 中的異步處理

    這篇文章主要介紹了詳解Servlet 3.0/3.1 中的異步處理,實(shí)例分析了servlet 3.0異步處理的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2017-04-04
  • RabbitMQ簡單隊(duì)列實(shí)例及原理解析

    RabbitMQ簡單隊(duì)列實(shí)例及原理解析

    這篇文章主要介紹了RabbitMQ簡單隊(duì)列實(shí)例及原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • mybatis基本實(shí)例詳解

    mybatis基本實(shí)例詳解

    這篇文章主要介紹了mybatis基本實(shí)例詳解以及mybatis自由模糊查詢,代碼簡單易懂,非常不錯,具有參考借鑒價(jià)值,需要的朋友可以參考下
    2017-03-03
  • 簡單了解JAVA內(nèi)存區(qū)域效果知識

    簡單了解JAVA內(nèi)存區(qū)域效果知識

    這篇文章主要介紹了簡單了解JAVA內(nèi)存區(qū)域效果知識,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10

最新評論

莲花县| 姚安县| 渝中区| 岳普湖县| 绥棱县| 诸暨市| 富锦市| 公主岭市| 康乐县| 雷山县| 紫金县| 施甸县| 革吉县| 佛教| 延安市| 成都市| 禹城市| 紫金县| 东辽县| 嘉义县| 沁水县| 六盘水市| 罗山县| 临安市| 通化市| 贺兰县| 黄陵县| 旌德县| 喜德县| 苏尼特左旗| 印江| 华亭县| 大姚县| 静安区| 贵州省| 丹阳市| 陵川县| 闽侯县| 布拖县| 桃园市| 乐昌市|