我們嘗試調(diào)整JVM的參數(shù),例如,設(shè)置更大空間的堆、修改GC的算法等。盡管效果不錯,但這種做法顯然是治標(biāo)不治本。
事實(shí)上,在這個時候,我們已經(jīng)感覺到兒童定位軟件使用是解決性能問題的關(guān)鍵。無論是CPU還是GC,都與內(nèi)存的使用密切相關(guān)。降低內(nèi)存的使用,可以減少GC的頻率,最終讓CPU把更多的時間用于業(yè)務(wù)計(jì)算。
我們找到了一些降低內(nèi)存使用的線索。
首先,我們要避免在循環(huán)中創(chuàng)建新的對象。例如,在循環(huán)中不斷地調(diào)用StringBuffer(通常占用了較多的內(nèi)存)的toString方法,每一次這樣的調(diào)用,都會產(chǎn)生一個新的String對象。
其次,我們希望更多的對象是無狀態(tài)的。這些無狀態(tài)的對象應(yīng)該以單個實(shí)例的形式來響應(yīng)外部的調(diào)用,這可以避免創(chuàng)建新對象。
再次,我們要快速釋放對象。這樣做的好處是,可以把對象保留在年輕代(Nurser-y)內(nèi)存區(qū),并通過GC的次要收集(Minor Collection)來進(jìn)行回收。釋放對象引用的方式也很簡單,通常是在使用完對象之后,把對象引用設(shè)為null。更新版的JDK提供了垃圾收集的優(yōu)化算法,可以更加自動化地釋放內(nèi)存。
最后,我們希望正常的邏輯路徑中不要包含Exception的處理。例如,有些邏輯NoSuchMethodException來遍歷大量不存在的方法。異常對象的創(chuàng)建會占用棧內(nèi)存。除了上面提到的線索,我們還發(fā)現(xiàn)了一些極不合理的做法,例如:不斷地往一個靜態(tài)的StringBuffer中添加信息;應(yīng)用程序定制了一個cache卻沒有任何管理機(jī)制;大對象的使用沒有節(jié)制等。
我們針對兒童定位軟件開發(fā)的問題給出了對應(yīng)的解決方案,換句話說,就是避免那些不合理的做法。之后,內(nèi)存的使用狀況明顯好轉(zhuǎn),GC的頻率也大大下降了。
那么,這些缺陷是軟件設(shè)計(jì)和實(shí)現(xiàn)中無法解決的嗎?不。
致遠(yuǎn)服軟認(rèn)為:http://www.soft8.com.cn/不同的JVM在GC的實(shí)現(xiàn)上是有很大差異的。關(guān)于GC的原理,讀者可以去閱讀相關(guān)的參考資料。我在這里想強(qiáng)調(diào)的是一個重要的經(jīng)驗(yàn)知識。
對于Java程序來說,內(nèi)存和GC是性能分析的關(guān)鍵。
我們再來看看大連統(tǒng)計(jì)數(shù)據(jù)報表軟件開發(fā)的競爭公司。線程競爭不會占用CPU資源,相反,競爭的結(jié)果是造成CPU的等待。這同樣會對性能造成重大的影響。
Yourkit提供了線程報告。我們可以從兒童定位軟件開發(fā)報告中看到,哪些線程在工作狀態(tài)、哪些線程在等待狀態(tài)、哪些線程在堵塞狀態(tài)。理論上,這份線程報告也許有助于性能分析,但是實(shí)際上,我們只能從中得到一些關(guān)于系統(tǒng)性能的整體印象,例如,是否存在過多的線程等待等,卻沒有發(fā)現(xiàn)直接的幫助。