。如果返回java不必release,java會(huì)自己回收。
jstring jstr = env->NewStringUTF((*p).sess_id);
...
env->DeleteLocalRef( jstr);
jobject jobj = env->NewObject(clazz,midInit);
return jobj;
內(nèi)存泄露可以先從windows資源管理器中,看到隨程序運(yùn)行,內(nèi)存不斷增長(zhǎng)的趨勢(shì),具體可以用hp jmeter檢測(cè)。在運(yùn)行程序時(shí),加jvm參數(shù) -Xrunhprof:heap=all,cutoff=0 ,生成java.hprof.txt,用jmeter打開(kāi),Metric -> Residual Objects (Count),可以看到未回收的對(duì)象,選中要查看的對(duì)象,點(diǎn)Mark記錄下要查看的對(duì)象,Window -> New Window 打開(kāi)新窗口,用Metric -> Reference Graph Tree,然后點(diǎn)Find Immediately可以看到對(duì)象被哪里引用。
找出內(nèi)存泄漏另一方法
程序有內(nèi)存泄漏的第一個(gè)跡象通常是它拋出一個(gè) OutOfMemoryError
,或者因?yàn)轭l繁的垃圾收集而表現(xiàn)出糟糕的性能。幸運(yùn)的是,垃圾收集可以提供能夠用來(lái)診斷內(nèi)存泄漏的大量信息。如果以 -verbose:gc
或者 -Xloggc
選項(xiàng)調(diào)用 JVM,那么每次 GC 運(yùn)行時(shí)在控制臺(tái)上或者日志文件中會(huì)打印出一個(gè)診斷信息,包括它所花費(fèi)的時(shí)間、當(dāng)前堆使用情況以及恢復(fù)了多少內(nèi)存。記錄 GC 使用情況并不具有干擾性,因此如果需要分析內(nèi)存問(wèn)題或者調(diào)優(yōu)垃圾收集器,在生產(chǎn)環(huán)境中默認(rèn)啟用 GC 日志是值得的。
有工具可以利用 GC 日志輸出并以圖形方式將它顯示出來(lái),JTune 就是這樣的一種工具(請(qǐng)參閱 參考資料)。觀察 GC 之后堆大小的圖,可以看到程序內(nèi)存使用的趨勢(shì)。對(duì)于大多數(shù)程序來(lái)說(shuō),可以將內(nèi)存使用分為兩部分:baseline 使用和 current load 使用。對(duì)于服務(wù)器應(yīng)用程序,baseline 使用就是應(yīng)用程序在沒(méi)有任何負(fù)荷、但是已經(jīng)準(zhǔn)備好接受請(qǐng)求時(shí)的內(nèi)存使用,current load 使用是在處理請(qǐng)求過(guò)程中使用的、但是在請(qǐng)求處理完成后會(huì)釋放的內(nèi)存。只要負(fù)荷大體上是恒定的,應(yīng)用程序通常會(huì)很快達(dá)到一個(gè)穩(wěn)定的內(nèi)存使用水平。如果在應(yīng)用程序已經(jīng)完成了其初始化并且負(fù)荷沒(méi)有增加的情況下,內(nèi)存使用持續(xù)增加,那么程序就可能在處理前面的請(qǐng)求時(shí)保留了生成的對(duì)象。
圖 1 顯示 GC 之后應(yīng)用程序堆大小隨著時(shí)間的變化圖。上升趨勢(shì)是存在內(nèi)存泄漏的警示信號(hào)。(在真實(shí)的應(yīng)用程序中,坡度不會(huì)這么大,但是在收集了足夠長(zhǎng)時(shí)間的 GC 數(shù)據(jù)后,上升趨勢(shì)通常會(huì)表現(xiàn)得很明顯。)
圖 1. 持續(xù)上升的內(nèi)存使用趨勢(shì)

確信有了內(nèi)存泄漏后,下一步就是找出哪種對(duì)象造成了這個(gè)問(wèn)題。所有內(nèi)存分析器都可以生成按照對(duì)象類(lèi)進(jìn)行分解的堆快照。有一些很好的商業(yè)堆分析工具,但是找出內(nèi)存泄漏不一定要花錢(qián)買(mǎi)這些工具 —— 內(nèi)置的 hprof
工具也可完成這項(xiàng)工作。要使用 hprof
并讓它跟蹤內(nèi)存使用,需要以 -Xrunhprof:heap=sites
選項(xiàng)調(diào)用 JVM。
清單 3 顯示分解了應(yīng)用程序內(nèi)存使用的 hprof
輸出的相關(guān)部分。(hprof
工具在應(yīng)用程序退出時(shí),或者用 kill -3
或在 Windows 中按 Ctrl+Break 時(shí)生成使用分解。)注意兩次快照相比,Map.Entry
、Task
和 int[]
對(duì)象有了顯著增加。
請(qǐng)參閱 清單 3。
清單 4 展示了 hprof
輸出的另一部分,給出了 Map.Entry
對(duì)象的分配點(diǎn)的調(diào)用堆棧信息。這個(gè)輸出告訴我們哪些調(diào)用鏈生成了 Map.Entry
對(duì)象,并帶有一些程序分析,找出內(nèi)存泄漏來(lái)源一般來(lái)說(shuō)是相當(dāng)容易的。
清單 4. HPROF 輸出,顯示 Map.Entry 對(duì)象的分配點(diǎn)
|
另外
jstring jstr = (jstring)env->CallObjectMethod(authenRequest, mid_authenReq_getSdId_S);
env->GetStringUTFRegion(jstr,0,env->GetStringLength(jstr),authenReq.sd_id);
當(dāng)jstr是null時(shí),env->GetStringLength(jstr)會(huì)出錯(cuò),導(dǎo)致jvm崩潰