日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

开发高性能JAVA应用程序基础(内存篇)

發布時間:2025/3/14 编程问答 12 豆豆
生活随笔 收集整理的這篇文章主要介紹了 开发高性能JAVA应用程序基础(内存篇) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

雖然Java的垃圾回收和當前高配置的服務器可以讓程序員大部分時間忘掉OutOfMemoryError的存在,但是訪問量增大后頻繁的GC會額外消耗CPU (使用top查看結果為us值高),系統響應速度下降,積壓的請求又會占用更多內存從而惡性循環,嚴重時可能導致系統不斷Full GC造成應用停頓。

優化內存的使用可從以下幾方面著手:

一、節流
1 使用單例模式

單例模式是開發者最早接觸并使用的設計模式之一,盡管寫代碼的時候可能還不知道用了設計模式。簡單來說就是構造函數private化,通過靜態方法獲得唯一實例。因為其特性,對于某些場景例如每次請求都要使用無狀態工具類的檢驗方法,使用單例模式可以大量節省創建新對象的開銷。

?

[java]?view plaincopy print?
  • public?class?Singleton?{??
  • ??
  • ????private?Singleton()?{}??
  • ??????
  • ????private?static?Singleton?instance?=?new?Singleton();??
  • ??????
  • ????public?static?Singleton?getInstance()?{??
  • ????????return?instance;??
  • ????}??
  • ??????
  • ????public?void?doSomething()?{?}??
  • }??
  • 2 緩存常用對象

    簡單來說就是按一定特征創建"對象緩存池",使用集合類保存已創建的對象,當有相同特征的對象申請時,使用緩存池中現有的對象代替通過 new關鍵字重新創建。

    ?

    [java]?view plaincopy print?
  • public?class?BigObjectPoolTest?{??
  • ????public?static?void?main(String[]?args)?{??
  • ????????long?start?=?System.nanoTime();??
  • ????????for(int?i?=?0;?i?<?10000;?i++)?{??
  • ????????????BigObjectPool.getBigObject("xxx",?true);??
  • ????????}??
  • ????????System.out.println("使用緩存池耗時"?+?TimeUnit.MILLISECONDS.convert(System.nanoTime()?-?start,?TimeUnit.NANOSECONDS)?+?"毫秒");??
  • ????????start?=?System.nanoTime();??
  • ????????for(int?i?=?0;?i?<?10000;?i++)?{??
  • ????????????BigObjectPool.getBigObject("xxx",?false);??
  • ????????}??
  • ????????System.out.println("不使用緩存池耗時"?+?TimeUnit.MILLISECONDS.convert(System.nanoTime()?-?start,?TimeUnit.NANOSECONDS)?+?"毫秒");??
  • ????}??
  • }??
  • ??
  • class?BigObjectPool?{??
  • ????private?static?Map<String,?BigObject>?map?=?new?HashMap<String,?BigObject>();??
  • ??????
  • ????static?{??
  • ????????map.put("xxx",?new?BigObject("xxx"));??
  • ????????map.put("yyy",?new?BigObject("yyy"));??
  • ????}??
  • ??????
  • ????public?static?BigObject?getBigObject(String?key,?boolean?usePool)?{??
  • ????????if(usePool)?{??
  • ????????????BigObject?bo?=?map.get(key);??
  • ????????????if(bo?==?null)?{??
  • ????????????????bo?=?new?BigObject(key);??
  • ????????????}??
  • ????????????return?bo;??
  • ????????}?else?{??
  • ????????????return?new?BigObject(key);??
  • ????????}??
  • ????}??
  • }??
  • ??
  • class?BigObject{??
  • ????private?String?name;??
  • ????private?byte[]?data?=?new?byte[1024?*?1024];??
  • ????public?BigObject(String?name)?{?this.name?=?name;?}??
  • }??
  • ?

    ?

    以-Xms32m -Xmx32m -Xloggc:d:/gc.log 參數運行

    ?

    [java]?view plaincopy print?
  • 使用緩存池耗時3毫秒??
  • 不使用緩存池耗時998毫秒??
  • (查看gc.log,可以觀察到不使用緩存池觸發Minor GC 1000次以上)

    ?

    實際業務中通常使用EhCache等框架代替自己實現緩存池。

    與這種實現原理相似的也有一個設計模式:享元模式,區別是享元模式更關注類設計結構上的優化,對上下文環境的設計也做了明確定義。

    3 避免設計過大的對象

    如果業務模型中要求的類的屬性和方法都非常多,可以嘗試將其拆分成多個小類,再通過合成/聚合模式組裝成一個大類,這也符合設計模式的優化思想。甚至可以結合上面的對象緩存池的方式將其中一部分內容緩存化。

    ?

    [java]?view plaincopy print?
  • class?Composition?{??
  • ????private?BigObject?bigObject?=?null;??
  • ????private?int?id;??
  • ??
  • ????public?void?setBigObject(BigObject?bigObject)?{??
  • ????????this.bigObject?=?bigObject;??
  • ????}??
  • ??
  • ????public?Composition(int?id)?{??
  • ????????this.id?=?id;??
  • ????}??
  • }??
  • ?

    ?

    ?

    [java]?view plaincopy print?
  • Composition?c?=?new?Composition(1);??
  • c.setBigObject(BigObjectPool.getBigObject("xxx",?true));??
  • 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应用程序基础(内存篇)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。