成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JAVA GC垃圾回收(及一次內(nèi)存泄漏處理)

RaoMeng / 3389人閱讀

摘要:垃圾回收及一次內(nèi)存泄漏處理內(nèi)存分布上圖展示了的架構(gòu)圖,本篇我們主要關(guān)注,運行時數(shù)據(jù)區(qū)。但是垃圾回收并不能百分百保證不會出現(xiàn)內(nèi)存泄漏,所以了解垃圾回收,對于我們遇到內(nèi)存泄漏時能更加清晰的分析原因,也能幫助我們寫出更加安全,可靠的程序。

[toc]

JAVA GC垃圾回收(及一次內(nèi)存泄漏處理)

JVM內(nèi)存分布

上圖展示了JVM的架構(gòu)圖,本篇我們主要關(guān)注,運行時數(shù)據(jù)區(qū)。GC垃圾回收發(fā)生在這個區(qū)的堆上。

Java使用了垃圾回收機制,極大的減輕了程序員的工作,是程序員能夠更加焦距在業(yè)務(wù)上。
但是垃圾回收并不能百分百保證不會出現(xiàn)內(nèi)存泄漏,所以了解垃圾回收,對于我們遇到內(nèi)存泄漏時能更加清晰的分析原因,也能幫助我們寫出更加安全,可靠的程序。

方法區(qū) Method Area

類加載器加載類之后,把類的信息存儲到方法區(qū)(即加載類時需要加載的信息,包括版本、域、方法、接口等信息)。所以方法區(qū)是存儲類級別的數(shù)據(jù),包括靜態(tài)變量。
每個jvm實例只有一個方法區(qū),這里會被jvm下的線程共享,so方法區(qū)是線程不安全的。

常量池是方法區(qū)的一部分,string對象的引用就存儲在這里。

 String s1 = "abc";//這里“abc”就存儲在常量池 s1在棧區(qū)指向方法區(qū)的一個內(nèi)存地址

下面看一個面試題來理解一下:

String s=new String("xyz")
//創(chuàng)建了幾個String Object?
兩個:
    "xyz"創(chuàng)建一個對象
    new String()創(chuàng)建一個
一個:
 “xyz”在其他程序中已經(jīng)創(chuàng)建,并且還沒有死亡,
 那么本次只會創(chuàng)建一對象new String()
 
堆區(qū) heap Area

垃圾回收主要集中在這個內(nèi)存區(qū)。

堆區(qū)存放對象的實例變量以及數(shù)組將被存儲在這里。
堆區(qū)和方法區(qū)一樣在JVM的實例中只有一個,會被JVM下的線程共享,所以堆區(qū)是線程不全的。

堆區(qū)分為:新生代和老年代(方法區(qū)是持久代)
新生代分為三個區(qū):
eden(伊甸園 新的對象最先在這里產(chǎn)生),to survivor, from survivor
在后面討論GC的時候,再詳細說明這一塊的工作過程。

棧區(qū) Stack Area

stack Area也可以叫虛擬機棧
棧區(qū)是線程安全的,每個線程都會創(chuàng)建自己私有的棧區(qū)。
在每個線程運行的時候會多帶帶創(chuàng)建一個運行時棧,棧區(qū)會分為三個實體:

局部變量:存儲方法中的局部變量

操作數(shù)棧:即執(zhí)行的指令,a+b:a入棧+入棧b入棧出棧計算結(jié)果

幀數(shù)據(jù): 方法所有符號都保存在這里。異常情況下catch塊的信息將會被保存在楨數(shù)據(jù)中。

程序計數(shù)器

程序計數(shù)器也稱pc寄存器。從寄存器的概念上我們就可以了解到空間很小但是很重要。
程序計數(shù)器是一個比較小的內(nèi)存區(qū)域,用于指示當(dāng)前線程所執(zhí)行的字節(jié)碼執(zhí)行到第幾行,可以理解為當(dāng)前線程的行號指示器(字節(jié)碼的哦)字節(jié)碼解釋器在工作時,會通過改變這個計數(shù)器的值來取下一條指令。

本地方法棧 native method stack

還記得在看源碼的時候看到有些方法被聲明為navite嗎?
navite的聲明方法為本地方法,一般是C語言實現(xiàn)。
本地方法棧在作用,運行機制、異常類型等方面都與虛擬機相同,唯一的區(qū)別是:虛擬機棧是執(zhí)行Java方法,而本地方法棧使用執(zhí)行navite方法的。在很多虛擬機(hotspot)會將本地方法棧與虛擬機棧放在一起使用。

直接內(nèi)存

內(nèi)存一部分被jvm管理,一部分沒有被jvm管理,沒有的那部分就是直接內(nèi)存。

Object o = new Object()的jvm分布

Object o 表示一個本地引用,存儲在jvm棧的本地變量表里,表示一個reference類型數(shù)據(jù),
new Object():作為實例對象存儲在對堆中。
類的信息(即加載類時需要加載的信息、包括版本、file、方法、接口等信息)存儲在方法區(qū)。

三個代(新生、老年、持久代)

堆內(nèi)存 = 新生代 + 老年代

新生代(年輕代 yong :so s1 eden)

對象被創(chuàng)建之后會被存儲在新生代(新生代空間足夠,否則會放在老年代,如果老年代內(nèi)存滿了,則會拋出 out of memory異常)
新生代分為3個區(qū):eden,to survivor, from survivor
servivor永遠有一個是沒有被使用的(空閑的),因為新生代的垃圾回收算法使用的是復(fù)制算法,所以永遠有一個survivor是沒有被使用的。
復(fù)制算法過程:

當(dāng)新生代需要垃圾回收的時候, 把eden和其中一個survivor存活的對象復(fù)制到另一個survivor,然后進行清理,之后在使用存放存活的對象的survivor和eden,下次再按照本次的復(fù)制算法進行復(fù)制。

新生代的三個區(qū)的默認空間比例是(由于絕大多數(shù)對象都是短命的,所以eden相比survivor會比較大):
eden: from: to = 8:1 :1

老年代(old)

如果新生代的對象經(jīng)過了幾次新生代gc(一般是15次)還沒有被回收,那么新生代的對象會被移到老年代。
老年代存儲的對象比年輕代多得多,而且很多都是大對象,老年代的清理算法采用的是標(biāo)記清除法: 當(dāng)老年代進行內(nèi)存清理額時候,先標(biāo)記出需要被清理的空間,然后統(tǒng)一進行清理(清除的時候會使程序停止)。

持久代(永久代 perm)

按照內(nèi)存存儲的數(shù)據(jù)的生命周期,方法區(qū)也被稱為持久代。表示此空間很少被回收,但是不表示不會被回收。
持久代的回收有兩種:

常量池中的常量,常量如果沒有被引用則可以被回收

無用的類信息(同時滿足以下條件):
2.1. 類的所有實例都已經(jīng)被回收了
2.2. 加載類的ClassLoader已經(jīng)被回收
2.3. 類對象的class對象沒有被引用(即沒有通過反射引用該類的地方)

GC算法 GC是在清除那些對象?

通過一下兩個算法,我們可以看到那些引用計數(shù)器為0或著不具有可達性的對象會被清除回收。

引用計數(shù)法

在對象中記錄一個引用計數(shù)器,如果對象被引用則計數(shù)器加一,如果引用被釋放則計數(shù)器減一。當(dāng)引用計數(shù)器為0的是否則對象被回收,但是這個算法有一個問題如果,兩個對象相互引用,則一直都不會被回收,導(dǎo)致內(nèi)存泄漏

內(nèi)存泄漏:是指程序中已動態(tài)分配的堆內(nèi)存由于某種原因程序未釋放或無法釋放,造成系統(tǒng)內(nèi)存的浪費,導(dǎo)致程序運行速度減慢甚至系統(tǒng)崩潰等嚴重后果

內(nèi)存溢出:通俗的說就是系統(tǒng)內(nèi)存不夠,導(dǎo)致程序崩潰,一般內(nèi)存泄漏很嚴重會導(dǎo)致內(nèi)存溢出。

    /**
    *引用計數(shù)器算法導(dǎo)致內(nèi)存泄漏示例
    * @author: xuelongjiang 
    **/
    
    public class countDemo{
    
    public static void main(String [] args){
        
        DemoObject object1 = new DemoObject();//(1) object1引用計數(shù)器 = 1
        DemoObject object2 = new DemoObject();//(2) obejct2 引用計數(shù)器 = 1
        object1.instance = object2;//(3) object2引用計數(shù)器 = 2
        object2.instance = object1;//(4) object1引用計數(shù) = 2
        object1 = null;//(5) object1引用計數(shù)器 = 1
        object2 = null // (6) obejct2引用計數(shù)器 = 1
       //到程序結(jié)束obejct1,object2的引用計數(shù)器都沒有被置為0 
    }
}

public class DemoObject{
    public Object instance = null;
}    

so hotspot虛擬機并沒有采用引用計數(shù)器算法。

可達性算法

現(xiàn)在我們來看可達性分析是如何避免上面循環(huán)引用導(dǎo)致內(nèi)存泄漏。

可達性算法核心是從GC Roots對象作為起始點,GC Roots可到達的則為存活對象,不可到達的則為需要清理的對象。

圖中的 Object10,object11,obejct4, object5 為不可達對象。

GC Roots的條件:

虛擬機棧的棧楨的局部變量表所引用的對象

本地方法棧的JNI所引用的對象

方法區(qū)的靜態(tài)變量和常量所引用的對象

從上圖可以看reference1(滿足上面條件3)、reference2(滿足條件1)、
reference3(滿足條件2)

reference1 引用 對象實例1
reference2 引用 對象實例2
reference3 引用 對象實例4(間接引用 實例對象6)

從上圖中可以看出實例1,2,4,6都具有GC Roots可達性也就是存活對象,不會被GC回收。而實例3,5雖然直接連通,但是由于沒有和GC Roots 連通不是可達對象。在可達性算法實例3、5是會被GC回收的。

回到引用計數(shù)器算法那個示例我們通過可達性分析,最終 object1,object2會被GC回收。

標(biāo)記-清除算法

標(biāo)記-清除算法分為兩步,第一步:標(biāo)記從GC Root 根的可達對象。 第二步:清除不可達對象,清除沒有被標(biāo)記的對象,此時會使程序停止運行,如果不停止程序,那么新產(chǎn)生的可達對象沒有被標(biāo)記則會被清除。

缺點:會產(chǎn)生不連續(xù)的內(nèi)存空間,并且會暫時停止程序。

復(fù)制算法

將內(nèi)存區(qū)分為兩部分:空閑區(qū)域和活動區(qū)域,首先標(biāo)記可達對象,標(biāo)記之后把可達對象復(fù)制到空閑區(qū),將空閑區(qū)變?yōu)榛顒訁^(qū),同時清除掉之前的活動區(qū),并且變?yōu)榭臻e區(qū)。
速度快但是耗費空間。

標(biāo)記-整理算法

標(biāo)記可達對象,清除不可達對象,整理內(nèi)存空間。

各代使用的算法

新生代采用 復(fù)制算法
老年代采用 標(biāo)記-整理算法

GC中的一些值解釋

YGC:年輕代的GC
FGC: 全范圍的GC

JVM的一些參數(shù)說明

-XmsxxM : -Xms64M 設(shè)置最小堆內(nèi)存為64MB
-Xmxxxm : -XMx128M 設(shè)置最大堆內(nèi)存128MB

如果以上參數(shù)設(shè)置的過于小會導(dǎo)致頻繁的發(fā)生GC,導(dǎo)致應(yīng)用的性能極大下降。如不必要使用默認就可以。
一般JVM調(diào)優(yōu)調(diào)整以上兩個參數(shù)就可以。
還可以設(shè)置的更加詳細:

-XX:NewSize :設(shè)置年輕代的大小
-XX:NewRatio : 設(shè)置年輕代和老年代的比值,如:3 表示年輕代與老年代的比值為1:3
-XX:SurvivorRatio :年輕代中eden區(qū)與兩個survivor區(qū)的比值
-XX:MaxPermSize : 設(shè)置持久代的大小

一次線上內(nèi)存泄漏解決

最新線上生產(chǎn)的項目發(fā)生了內(nèi)存泄漏,整個排查思路是這樣的:

事故背景

使用websocket(基于netty實現(xiàn))客戶端實時獲取其他網(wǎng)站的數(shù)據(jù),把返回的數(shù)據(jù)使用redis緩存起來。
websocket只在程序啟動的時候運行一次,之后定時任務(wù)(timer)接管websocket的ping,斷線重連。

事故原因

由于websocket的消息處理使用了redisClient,onReceive方法中調(diào)用redisClient。
redisClient的生命周期是整個應(yīng)用的生命周期是一致。

redisClient.opsForValue().set(symbol.get(), df.get()+" 美元");//redisClient引用了 symbol 和df 導(dǎo)致symbol,df沒有被釋放,并且他倆引用了其他的導(dǎo)致都沒有被釋放,發(fā)生了內(nèi)存泄漏
內(nèi)存泄漏代碼
@SpringBootApplication
@EnableScheduling
public class WalleInt2Application {

public static void main(String[] args) {
        SpringApplication.run(WalleInt2Application.class, args);
    }
    
    
    @Bean
    public TaskRunnerFcion taskRunnerFcion(){
        return new TaskRunnerFcion();
    }
}
/**
* 只在項目啟動的時候運行一次(run()方法)
 * @author xuelongjiang
 */
@Order(value = 1)
public class TaskRunnerFcion implements ApplicationRunner {


    private static Logger logger = LoggerFactory.getLogger(TaskRunnerFcion.class);

   /* @Autowired
    @Qualifier("redisClient")
    private StringRedisTemplate redisClient;*/


    @Autowired
    @Qualifier("fcionWebSocketServiceImpl")
    private  WebSocketService fcionWebSocketServiceImpl;



    String fcionUri = "wss://ws.fcoin.com/api/v2/ws";
    String fcion_ping = "{"cmd":"ping","args":[1532070885000]}";
    String fcion_getData = "{"id":"tickers","cmd":"sub","args":["all-tickers"]}";

    @Override
    public void run(ApplicationArguments args) throws Exception {
        logger.info("啟動fcion websocket客戶端............");
       // WebSocketService service = new FcionWebSocketServiceImpl(redisClient);
        WebSocketFcionClient client = new WebSocketFcionClient(fcionUri,fcionWebSocketServiceImpl,fcion_ping);
        client.start();
        client.addChannel(fcion_getData);
        logger.info("啟動fcion websocket客戶端  完成............");

    }
}
@Service
public class FcionWebSocketServiceImpl implements WebSocketService{

    private Logger log = LoggerFactory.getLogger(FcionWebSocketServiceImpl.class);


    private String get_rate_usedToCNY = "https://www.fcoin.com/api/common/get_rate?from=USD&to=CNY";

    @Autowired
    @Qualifier("redisClient")
    private StringRedisTemplate redisClient;

    public FcionWebSocketServiceImpl() {
    }

    public FcionWebSocketServiceImpl(StringRedisTemplate redisClient) {
        this.redisClient = redisClient;
    }


    @Override
    public void onReceive(String msg){

        log.info("WebSocket fcion Client 接收到消息:{} ",  msg);
        JSONObject jsonObject = JSONObject.parseObject(msg);
        String topic = jsonObject.getString("topic");
        if(topic != null &&topic.equals("all-tickers")){
            JSONArray jsonArray = jsonObject.getJSONArray("tickers");
            for(int i =0; i< jsonArray.size(); i++){

                JSONObject jsonObject1 = jsonArray.getJSONObject(i);
                Double usdPrice =jsonObject1.getJSONArray("ticker").getDouble(0);
                if(usdPrice == null){
                    continue;
                }
                BigDecimal b = new BigDecimal(usdPrice);
                df=b.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
                String symbol="fcion_"+jsonObject1.getString("symbol");
                log.info("{}當(dāng)前價格:{}", symbol, df+"美元");
                redisClient.opsForValue().set(symbol, df+" 美元");//redisClient相當(dāng)于單例模式?jīng)]有被釋放,導(dǎo)致器引用的symbol,df沒有被釋放,symbol引用JSONObject, df引用了BigDecimal導(dǎo)致都沒有被釋放,發(fā)生了內(nèi)存泄漏
            }
        }
    }
}

redisClient相當(dāng)于單例模式?jīng)]有被釋放,導(dǎo)致引用的symbol,df沒有被釋放,symbol引用JSONObject, df引用了BigDecimal導(dǎo)致都沒有被釋放,發(fā)生了內(nèi)存泄漏

修復(fù)后的代碼
@Service
public class FcionWebSocketServiceImpl implements WebSocketService{

    private Logger log = LoggerFactory.getLogger(FcionWebSocketServiceImpl.class);


    private String get_rate_usedToCNY = "https://www.fcoin.com/api/common/get_rate?from=USD&to=CNY";

    @Autowired
    @Qualifier("redisClient")
    private StringRedisTemplate redisClient;

    public FcionWebSocketServiceImpl() {
    }

    public FcionWebSocketServiceImpl(StringRedisTemplate redisClient) {
        this.redisClient = redisClient;
    }


    @Override
    public void onReceive(String msg){

        log.info("WebSocket fcion Client 接收到消息:{} ", msg);
        JSONObject jsonObject = JSONObject.parseObject(msg);
        String topic = jsonObject.getString("topic");
        if(topic != null &&topic.equals("all-tickers")){
            JSONArray jsonArray = jsonObject.getJSONArray("tickers");
            for(int i =0; i< jsonArray.size(); i++){

                JSONObject jsonObject1 = jsonArray.getJSONObject(i);
                Double usdPrice =jsonObject1.getJSONArray("ticker").getDouble(0);
                if(usdPrice == null){
                    continue;
                }
                BigDecimal b = new BigDecimal(usdPrice);
                WeakReference df = new WeakReference(b.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue());
                WeakReference symbol = new WeakReference("fcion_"+jsonObject1.getString("symbol"));
                log.info("{}當(dāng)前價格:{}", symbol, df+"美元");
                redisClient.opsForValue().set(symbol.get(), df.get()+" 美元");


            }
        }

    }
}

這里使用弱引用修飾 symbol,df,是之能夠被釋放,當(dāng)方法被回調(diào)完成執(zhí)行后,會被回收。

長對象引用短對象:

定位過程

快速定位內(nèi)存泄漏的命令:

jamp -histo:live pid

可以看到哪些類被使用的最多:


(上面使用的是阿里云的提供的服務(wù)器網(wǎng)頁版 其本質(zhì)也是執(zhí)行的上面的命令)

看到了 byte[]占用的內(nèi)存比較大,開始懷疑是不是使用netty的handler的channelRead0方法里導(dǎo)致的內(nèi)存泄漏,因為這里處理返回的流,使用到了byte [],之后注釋掉onReceive方法的業(yè)務(wù)處理(由于這個項目只是完成websocket客戶端獲取三個網(wǎng)站的數(shù)據(jù))。跑了四五個小時,再次查看內(nèi)存使用情況,發(fā)現(xiàn)沒有發(fā)生泄漏。此時定位到問題發(fā)生在onReceive方法中。

通過分析redisClient 沒有被釋放,導(dǎo)致引用的對象沒有被釋放,發(fā)生了內(nèi)存泄露。
最后使用弱引用來進行釋放。

以上是問題解決的時候的步驟(其實當(dāng)時是直接停掉了websocket,只是跑springboot)

實際排錯,比較曲折。最好是用過jmap命令,看到輸出對象里有BigDecimal就覺得有問題,因為按照代碼BigDecimal的對象不可能20多兆。但是也覺得可能是redisClient導(dǎo)致沒有釋放對象 。
把symbol , df置為null之后運行了幾個小時內(nèi)存還是泄漏。所以就使用以上關(guān)閉部分代碼的方法來準確定位(由于這一塊理論知識的不足才會導(dǎo)致排錯走了很多彎路)。

單例模式引發(fā)的內(nèi)存泄漏

由于單例對象的生命周期是伴隨著應(yīng)用的生命周期的,所以如果單例對象引用了其他對象,會導(dǎo)致其他對象很難被回收(長生命周期對象持有短生命周期對象)。

幾種引用方式 強引用

代碼中普遍存在的類似 Obejct o = new Object() 這類的引用,只要強引用還存在,垃圾收集器永遠不會回收掉被引用的對象

弱引用

非必須對象,被弱引用關(guān)聯(lián)的對象只能生存到下一次垃圾回收之前,垃圾收集器工作之后,無論當(dāng)前內(nèi)存是否足夠,都會回收掉只被弱引用關(guān)聯(lián)的對象。Java中的類WeakReference表示弱引用。

軟引用

還有用但非必須對象。在系統(tǒng)將要發(fā)生內(nèi)存溢出異常之前,將會把這些對象列進回收范圍進行二次回收。如果這次回收還沒有足夠的內(nèi)存,才會跑出了內(nèi)存溢出異常。java 中的類 SoftReference表示軟引用。

虛引用

這個引用存在的唯一目的就是這個對象被收集器回收時收到一個系統(tǒng)通知,被虛引用關(guān)聯(lián)的對象,和其生存時間完全沒有關(guān)系。Java中的類PhantomReference表示虛引用。

參考:

https://www.cnblogs.com/first...
https://www.cnblogs.com/study...
https://blog.csdn.net/aijiudu...
https://www.cnblogs.com/xiaox...
https://www.cnblogs.com/yydcd...
http://baijiahao.baidu.com/s?...
https://www.zhihu.com/questio...
https://www.cnblogs.com/soari...
https://www.cnblogs.com/my-ki...
https://blog.csdn.net/u012167...

關(guān)注我的公眾號第一時間閱讀有趣的技術(shù)故事
掃碼關(guān)注:

可以在微信搜索公眾號即可關(guān)注我:codexiulian

渴望與你一起成長進步!

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/76919.html

相關(guān)文章

  • 性能優(yōu)化(三)看完這篇文章,至少解決 APP 中 90 % 的內(nèi)存異常問題

    摘要:不能滿足被回收的條件,盡管調(diào)用也還是不能得到回收這就造成了內(nèi)存泄漏。種解決單例中的內(nèi)存泄漏將引用置為銷毀監(jiān)聽使用弱引用將監(jiān)聽器放入弱引用中從弱引用中取出回調(diào)通過第七小點就能完美的解決單例中回調(diào)引起的內(nèi)存泄漏。我們?yōu)槭裁匆獌?yōu)化內(nèi)存 showImg(https://user-gold-cdn.xitu.io/2019/5/12/16aac64e31d8c501); 在 Android 中我們寫的...

    Elle 評論0 收藏0
  • Node.js內(nèi)存管理和V8垃圾回收機制

    摘要:垃圾回收內(nèi)存管理實踐先通過一個來看看在中進行垃圾回收的過程是怎樣的內(nèi)存泄漏識別在環(huán)境里提供了方法用來查看當(dāng)前進程內(nèi)存使用情況,單位為字節(jié)中保存的進程占用的內(nèi)存部分,包括代碼本身棧堆。 showImg(https://segmentfault.com/img/remote/1460000019894672?w=640&h=426);作者 | 五月君Node.js 技術(shù)棧 | https:...

    JowayYoung 評論0 收藏0
  • Android內(nèi)存泄漏總結(jié)

    摘要:內(nèi)存泄漏總結(jié)內(nèi)存管理的目的就是讓我們在開發(fā)中怎么有效的避免我們的應(yīng)用出現(xiàn)內(nèi)存泄漏的問題。在中,內(nèi)存泄漏的范圍更大一些。 Android 內(nèi)存泄漏總結(jié) 內(nèi)存管理的目的就是讓我們在開發(fā)中怎么有效的避免我們的應(yīng)用出現(xiàn)內(nèi)存泄漏的問題。內(nèi)存泄漏大家都不陌生了,簡單粗俗的講,就是該被釋放的對象沒有釋放,一直被某個或某些實例所持有卻不再被使用導(dǎo)致 GC 不能回收。最近自己閱讀了大量相關(guān)的文檔資料,打...

    legendaryedu 評論0 收藏0
  • JS中的垃圾回收內(nèi)存泄漏

    摘要:介紹瀏覽器的具有自動垃圾回收機制,也就是說,執(zhí)行環(huán)境會負責(zé)管理代碼執(zhí)行過程中使用的內(nèi)存。中的內(nèi)存泄漏問題程序的內(nèi)存溢出后,會使某一段函數(shù)體永遠失效取決于當(dāng)時的代碼運行到哪一個函數(shù),通常表現(xiàn)為程序突然卡死或程序出現(xiàn)異常。 showImg(https://segmentfault.com/img/remote/1460000018932880?w=4400&h=3080); 1. 介紹 瀏...

    xiaolinbang 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<