开发高性能JAVA应用程序基础(内存篇)
雖然Java的垃圾回收和當前高配置的服務器可以讓程序員大部分時間忘掉OutOfMemoryError的存在,但是訪問量增大后頻繁的GC會額外消耗CPU (使用top查看結果為us值高),系統響應速度下降,積壓的請求又會占用更多內存從而惡性循環,嚴重時可能導致系統不斷Full GC造成應用停頓。
優化內存的使用可從以下幾方面著手:
一、節流
1 使用單例模式
單例模式是開發者最早接觸并使用的設計模式之一,盡管寫代碼的時候可能還不知道用了設計模式。簡單來說就是構造函數private化,通過靜態方法獲得唯一實例。因為其特性,對于某些場景例如每次請求都要使用無狀態工具類的檢驗方法,使用單例模式可以大量節省創建新對象的開銷。
?
[java]?view plaincopy print?2 緩存常用對象
簡單來說就是按一定特征創建"對象緩存池",使用集合類保存已創建的對象,當有相同特征的對象申請時,使用緩存池中現有的對象代替通過 new關鍵字重新創建。
?
[java]?view plaincopy print??
?
以-Xms32m -Xmx32m -Xloggc:d:/gc.log 參數運行
?
[java]?view plaincopy print? (查看gc.log,可以觀察到不使用緩存池觸發Minor GC 1000次以上)
?
實際業務中通常使用EhCache等框架代替自己實現緩存池。
與這種實現原理相似的也有一個設計模式:享元模式,區別是享元模式更關注類設計結構上的優化,對上下文環境的設計也做了明確定義。
3 避免設計過大的對象
如果業務模型中要求的類的屬性和方法都非常多,可以嘗試將其拆分成多個小類,再通過合成/聚合模式組裝成一個大類,這也符合設計模式的優化思想。甚至可以結合上面的對象緩存池的方式將其中一部分內容緩存化。
?
[java]?view plaincopy print??
?
?
[java]?view plaincopy print?4 一些小技巧
使用StringBuilder代替用+號連接字符串
盡量使用int, long等基本類型代替Integer, Long包裝對象
合理利用SoftReference和WeakReference
二、開源 - 調整虛擬機參數
一般設置 java -server -Xms2048m -Xmx2048m?-XX:PermSize=256m ?-XX:MaxPermSize=256m
-Xms和-Xmx決定java堆區可使用的內存最小值和最大值,通常設為相同的值,避免運行期間反復的重新申請內存。如果出現OutOfMemoryError:?Java?heap space,則在硬件允許的情況下臨時調大-Xmx,為排查問題和優化代碼爭取時間。
-XX:PermSize和-XX:MaxPermSize決定永久代可用空間大小,存放class和meta信息,通常設置為相同的值。如果出現OutOfMemoryError:?PermGen space,說明加載的類和jar文件過多,可以調大這兩個參數值。
如果web容器下有多個應用引用了相同的第三方jar文件,可以轉移到容器的共享目錄。
另一個重要參數是-Xmn,決定堆區新生代的大小,通常占-Xmx的比值設置為1/4到1/3。如果業務中有大量體積大且生命周期很短的對象創建需求,可適當調大新生代空間以利于失效對象在新生代中被回收。
此外,可通過參數設置回收算法:
–XX:+UseSerialGC
–XX:+UseParallelGC
–XX:+UseParallelOldGC
–XX:+UseConcMarkSweepGC
回收算法的選擇和對比需要較大的篇幅介紹,這里不做詳細的解釋。通常來說,對于響應時間優先的web應用,ConcMarkSweepGC(CMS)是個不錯的選擇。
需要注意的是,經過幾代發展后,JVM對內存管理已經做的非常好。如果不是有明確的證據證明JVM的默認選擇不合理,就沒必要做過多細節的調整設置。調整后,可通過-XX:+PrintGCDetails -XX:+PrintGCTimeStamps等參數輸出GC信息進行比對,優化的首要目標是減少Full GC次數和時間。
?
參考資料:?分布式java應用基礎與實踐
轉載于:https://www.cnblogs.com/sa-dan/p/6837151.html
總結
以上是生活随笔為你收集整理的开发高性能JAVA应用程序基础(内存篇)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: postman+newman+jenki
- 下一篇: tr的display属性出现td的col