欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

關(guān)于java的socket有可能出現(xiàn)內(nèi)存泄漏的問題

系統(tǒng) 1818 0
前段時(shí)間寫了一個(gè)java socket相關(guān)的程序,大概意思就是client和server是采用socket長連接方式,之間通信都是通過通過ObjectOutputStream和OjbectInputStream來進(jìn)行寫和讀操作。

其實(shí)以前就很多次的用到過ObjectOutputStream,不過沒有詳細(xì)的琢磨過,這次就想著琢磨一下,主要也是因?yàn)槲野l(fā)現(xiàn)程序中存在內(nèi)存泄漏的問題,通過Jprobe跟蹤,排除了別的泄漏因素,最后定位在是在socket這里發(fā)生了泄漏,具體情況下面進(jìn)行分析。

先來說說ObjectOutputStream,通過ObjectOutputStream來進(jìn)行socket寫入,那么會在流中加入Object的信息,也就是說如果想要是跨平臺的socket通信那么可能會帶來一些問題,因?yàn)閿?shù)據(jù)流中加入的是java特有的信息,class類型以及成員變量的類型信息,同樣通過ObjectInputStream來讀取也有相應(yīng)的規(guī)則來進(jìn)行解析。

下面我們來看一下寫入的信息,首先有一個(gè)簡單的類

    
class MyObject implements Serializable {
	private static final long serialVersionUID = -9163423175612080544L;
	String str1;
	String str2;
}

  


我們通過ObjectOutputStream來把該類寫入文件中,查看一下寫入的內(nèi)容
    
 sr com.travelsky.test.MyObject€喳+?^` L str1t Ljava/lang/String;L str2q ~ xpt test1t test2q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ 

  

我們可以看到寫入的內(nèi)容中包含了寫入類的類型以及成員變量信息,當(dāng)然關(guān)于插入的內(nèi)容,我們可以覆蓋ObjectOutputStream類的writeStreamHeader()方法來實(shí)現(xiàn)插入我們自定義的內(nèi)容,當(dāng)然如果這樣做的話,我們就必須對ObjectInputStream類進(jìn)行重寫

上面是一些題外話,下面回到正題,關(guān)于我標(biāo)題中提到的有內(nèi)存泄漏的問題。為了更清晰直觀的說明該問題,我又寫了一個(gè)很簡單的測試,代碼如下:
    
            FileOutputStream fos = new FileOutputStream("c:\\test.txt");
	    ObjectOutputStream oos = new ObjectOutputStream(fos);

	    MyObject myObj = new MyObject();
	    myObj.str1 = "test1";
	    myObj.str2 = "test2";
	    for (int i = 0; i < 20; i++) {
	        oos.writeObject(myObj);
	        oos.writeObject(myObj);
	    }
	    fos.close();

  

我在這里循環(huán)了20次,那么大家可以猜想一下文件中會是什么內(nèi)容,可能會有人認(rèn)為是我剛才在上面貼出的內(nèi)容重復(fù)20遍,起初我也是這么認(rèn)為的,但事實(shí)不是這么回事。
我現(xiàn)在更改一下程序,不再循環(huán),只寫入一次,那么寫入的內(nèi)容是
    
 sr com.travelsky.test.MyObject€喳+?^` L str1t Ljava/lang/String;L str2q ~ xpt test1t test2q ~ 

  

循環(huán)10次
    
 sr com.travelsky.test.MyObject€喳+?^` L str1t Ljava/lang/String;L str2q ~ xpt test1t test2q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ 

  

循環(huán)20次
    
sr com.travelsky.test.MyObject€喳+?^` L str1t Ljava/lang/String;L str2q ~ xpt test1t test2q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ q ~ 

  


這樣的測試我們還是不夠清晰,下面我們讓他每次循環(huán)寫入的對象的屬性都不相同,我們這樣修改一下代碼
    
            FileOutputStream fos = new FileOutputStream("c:\\test.txt");
	    ObjectOutputStream oos = new ObjectOutputStream(fos);

	    for (int i = 0; i < 10; i++) {
	    	MyObject myObj = new MyObject();
	    	myObj.str1 = "test1" + i;
	    	myObj.str2 = "test2" + i;
	        oos.writeObject(myObj);
	        oos.writeObject(myObj);
	    }
	    fos.close();

  

那么這個(gè)時(shí)候文件里的內(nèi)容是什么呢,我們再來看一下
    
 sr com.travelsky.test.MyObject€喳+?^` L str1t Ljava/lang/String;L str2q ~ xpt test10t test20q ~ sq ~  t test11t test21q ~ sq ~  t test12t test22q ~ sq ~  t test13t test23q ~ sq ~  t test14t test24q ~ sq ~  t test15t test25q ~ sq ~  t test16t test26q ~ sq ~  t test17t test27q ~ sq ~  t test18t test28q ~ sq ~  t test19t test29q ~ 

  

這樣就顯而易見了,我們雖然寫入了10次,但是不會每次寫入都會插入寫入對象和成員變量類型的信心,而是在第一次寫入的時(shí)候插入一些頭信息,以后再寫就不會再插入了。這實(shí)際是java做的優(yōu)化,通過該優(yōu)化從而減少socket傳輸?shù)拈_銷。
那么會有人問了,你說的內(nèi)存泄漏的問題呢,寫到這里,我想應(yīng)該有人已經(jīng)看出問題來了,它之所以可以這么做優(yōu)化,前提是持有MyObject的引用,也就是說,不會釋放掉MyObject的引用。現(xiàn)在明白了吧,如果你是長連接的方式,ObjectOutputStream會一直持有你以前發(fā)送過的對象的引用,從而導(dǎo)致jvm在進(jìn)行垃圾回收的時(shí)候不能回收之前發(fā)送的對象的實(shí)例,經(jīng)過漫長時(shí)間的運(yùn)行,最終導(dǎo)致內(nèi)存溢出了。這一點(diǎn)從我通過Jprobe跟蹤也得到了印證。

下面我們來談?wù)勅绾伪苊庠搯栴},說著這里我們就得提到ObjectOutputStream的reset方法了,JDK文檔中是這么解釋該方法的:
“重置將丟棄已寫入流中的所有對象的狀態(tài)。重新設(shè)置狀態(tài),使其與新的 ObjectOutputStream 相同。將流中的當(dāng)前點(diǎn)標(biāo)記為 reset,相應(yīng)的 ObjectInputStream 也將在這一點(diǎn)重置。以前寫入流中的對象不再被視為正位于流中。它們會再次被寫入流。”
就是說調(diào)用reset那么就丟棄所持有對象的狀態(tài)(也就是釋放掉了對對象的應(yīng)用),同時(shí)會在流中設(shè)置reset標(biāo)識。

還是之前那個(gè)例子,我們來修改一下代碼,在每次寫入后都調(diào)用一下reset方法
    
            FileOutputStream fos = new FileOutputStream("c:\\test.txt");
	    ObjectOutputStream oos = new ObjectOutputStream(fos);

	    for (int i = 0; i < 10; i++) {
	    	MyObject myObj = new MyObject();
	    	myObj.str1 = "test1" + i;
	    	myObj.str2 = "test2" + i;
	        oos.writeObject(myObj);
	        oos.writeObject(myObj);
                oos.reset();
	    }
	    fos.close();

  

我們再來看一下寫入文件內(nèi)容
    
 sr com.travelsky.test.MyObject€喳+?^` L str1t Ljava/lang/String;L str2q ~ xpt test10t test20q ~ ysr com.travelsky.test.MyObject€喳+?^` L str1t Ljava/lang/String;L str2q ~ xpt test11t test21q ~ ysr com.travelsky.test.MyObject€喳+?^` L str1t Ljava/lang/String;L str2q ~ xpt test12t test22q ~ ysr com.travelsky.test.MyObject€喳+?^` L str1t Ljava/lang/String;L str2q ~ xpt test13t test23q ~ ysr com.travelsky.test.MyObject€喳+?^` L str1t Ljava/lang/String;L str2q ~ xpt test14t test24q ~ ysr com.travelsky.test.MyObject€喳+?^` L str1t Ljava/lang/String;L str2q ~ xpt test15t test25q ~ ysr com.travelsky.test.MyObject€喳+?^` L str1t Ljava/lang/String;L str2q ~ xpt test16t test26q ~ ysr com.travelsky.test.MyObject€喳+?^` L str1t Ljava/lang/String;L str2q ~ xpt test17t test27q ~ ysr com.travelsky.test.MyObject€喳+?^` L str1t Ljava/lang/String;L str2q ~ xpt test18t test28q ~ ysr com.travelsky.test.MyObject€喳+?^` L str1t Ljava/lang/String;L str2q ~ xpt test19t test29q ~ y

  

這次跟之前不同的,每一次寫入都加入了頭信息且每一次末尾都加入了y,我想這個(gè)標(biāo)識應(yīng)該就是reset標(biāo)識,至于具體是什么,我們沒必要深究了。

通過上面一系列的測試,我們大概對Object流有了一定了解,那么具體到我們?nèi)粘>幋a中到底該不該調(diào)用reset呢,這個(gè)我想不能一概而論了,我們通過測試也看到了,在不調(diào)用reset的方式下,java的優(yōu)化對于減輕socket開銷還是很可觀的,當(dāng)然代價(jià)是有的,那就是直到你調(diào)用reset或者是關(guān)閉輸出流之前,對于發(fā)送過的對象的實(shí)例是不會釋放的。

結(jié)論:當(dāng)然只是我自己的片面之詞。如果你的程序需要很長時(shí)間的運(yùn)行,我建議你還是調(diào)用reset避免最后內(nèi)存溢出程序崩潰,但是如果你又要長時(shí)間運(yùn)行,且發(fā)送的消息量又很大,那么調(diào)用reset無疑會增加開銷,那么這個(gè)時(shí)候最好的做法我覺得是你自己實(shí)現(xiàn)一套機(jī)制,定時(shí)的調(diào)用reset或者是定量,比如查看到內(nèi)存已經(jīng)漲到一個(gè)水平后調(diào)用一下,這樣既可以避免內(nèi)存無限的增長下去,又可以減少不少socket通信的開銷

anson在這里感謝大家花了這么長時(shí)間閱讀該文章,希望能給大家?guī)Я艘恍椭硗馍厦娴姆治龆际俏覀€(gè)人的理解,肯定存在一定的局限性,大家有什么更深刻的認(rèn)識,還請大家指出來,我們一起交流,共同進(jìn)步

關(guān)于java的socket有可能出現(xiàn)內(nèi)存泄漏的問題


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 久久久国产视频 | 久草国产视频 | 亚洲人成网站看在线播放 | 亚洲国产区 | 性xxxx免费观看视频 | 丝袜美腿视频一区二区三区 | 人人爱人人爽 | 欧美第一页草草影院浮力 | 青青草视频破解版 | 久操青青 | 亚洲欧洲精品成人久久曰影片 | 中文成人在线 | 一级片a级片 | 亚洲综合久久伊人热 | 一级免费a| 五月婷亚洲 | 午夜资源站 | 日韩亚洲人成网站在线播放 | 99精品欧美一区二区三区综合在线 | 欧美一级色片 | 国产最新一区 | 黑色丝袜美女被狂躁 | 在线中文字幕视频 | 91久久青青草原免费 | 日韩欧美精品综合一区二区三区 | 久碰人澡人澡人澡人澡91 | 99国精产品一区二区三区A片 | 99久久99 | 亚洲精品乱码久久久久久蜜桃 | 人人狠狠综合88综合久久 | 久久99综合国产精品亚洲首页 | 欧美成熟丰满老妇xxxx | 91麻豆国产极品在线观看洋子 | 国产精品久久久久久久久久红粉 | 亚洲国产欧洲精品路线久久 | 91免费版在线观看 | 九九综合九九 | 亚洲欧美视频在线播放 | 色综合激情 | 欧美在线综合 | 一级做a爰片性色毛片中国 日本黄色免费片 |