java記憶體最佳化實踐

來源:互聯網
上載者:User

標籤:

一般在java程式中,記憶體是個比較頭痛的話題。雖然jvm能夠通過GC機制很智能地回收資源,但是由於記憶體的釋放都是jvm在進行操作,不恰當的使用會導致java的程式記憶體持續增大,直至最終OOM(out of memery) 
那麼,如何對java進行記憶體最佳化呢?一方面可以通過調整jvm的一些配置(記憶體,GC等),從jvm層最佳化配置;另一方面,從java程式角度,在代碼層次上進行最佳化。

近期,做了些在java程式方面記憶體最佳化實踐,積累了一些心得,總結如下:

    1. 對於資源消耗較大的對象(如資料庫連接,Stream,大的collection等),儘早進行釋放,還得考慮到異常情況

      對於這種情況,就沒必要釋放obj了,因為在執行完func後,GC會自動回收資源 
      Public void func(){ 
      Object obj =new Object(); 
      …… 
      Obj=null; 

      但是對於這類操作就有必要提前釋放了,特別是一些串連資源,大記憶體對象等 
      Public void func(){ 
      Object obj =new Object(); 
      …… 
      Obj=null; 
      xxxx; // 耗時操作 

      而且對於資料庫資源/stream,在釋放的時候,要考慮到出現exception的情況,建議在finalize中釋放串連 
      public static Properties loadProperties(String fileName) throws IOException { 
      FileInputStream stream = new FileInputStream(fileName); 
      try { 
      Properties props = new Properties(); 
      props.load(stream); 
      return props; 

      finally { 
      stream.close(); 

      }

    2. 最佳化邏輯,避免不必要對象的建立,且盡量使用局部變數 
      由於局部變數是在stack上進行分配的,速度較快,且生命週期是固定的,同時可以最佳化程式的邏輯,避免一些不必要的邏輯的建立,如

      A a = new A(); 
      if(i==1){list.add(a);}

      應該改為 
      if(i==1){ 
      A a = new A(); 
      list.add(a); 

      還有,比如: 
      FileInputStream stream = new FileInputStream(fileName); 
      if (xxx) { 
      return; 

      stream.xxx; 
      應該改成: 
      if (xxx) { 
      return; 

      FileInputStream stream = new FileInputStream(fileName); 
      stream.xxx;

    3. 最佳化迴圈邏輯,減少迴圈邏輯裡對象的建立和調用

      for (int i = 0; i < xxx.size(); i++) { 
      xxx 

      這樣xxx.size()會被調用多次,效率較低,可以使用: 
      for (int i = 0, len = xxx.size(); i < len; i++) { 
      xxx 

      同樣要在迴圈裡面對於對象的建立要謹慎,如 
      for (int i = 0; i < 1000; ++i) { 
      Map myMap = new HashMap<>(); 
      myMap.xxx; 

      應該改成 
      Map myMap = new HashMap<>(); 
      for (int i = 0; i < 1000; ++i) { 
      myMap.clear(); 
      myMap.XXX(); 
      }

    4. 使用基本類型替代物件類型 
      比如使用int替代Integer,long替代Long等,數組替代vector等,減少對象建立。而且函數中,基本類型是存放於棧上建立和使用效率較高。

    5. 使用stringBuffer和stringBuilder替代多次String對象 
      因為String對象是定長的,任何關於String的變更操作都會導致新的String對象建立。因此可以在合適的時機使用stringBuferr或者stringBuilder替代String對象,單線程使用StringBuilder,多線程情況下使用StringBuffer。

    6. 提前分配stringBuffer,數組,array,vector等容量 
      對於需要連續分配的對象,最好先提前分配容量,一般預設的初始容量都比較小,如stringBuffer的容量是只有16,如果按照預設的容量很容易在容量滿了之後重新分配一塊大的資源,耗時費記憶體。因此可以通過提前分配資源的方式避免這個情況

    7. 緩衝經常要使用的對象和資料 
      對於經常需要使用的對象和資料,可以使用緩衝存起來(比如記憶體中的共用記憶體,或者redis,memcached等remote cache server),減少一些對象的重複建立計算代價

    8. 慎用exception 
      當建立一個異常時,需要收集一個棧跟蹤(stack track),這個棧跟蹤用於描述異常是在何處建立的。構建這些棧跟蹤時需要為運行時棧做一份快照,正是這一部分開銷很大。因此要慎用異常,一般而言,異常是只有當前處理不了的異常才往上層拋,否則可以通過函數傳回值(bool false,object=null)等方式向上呈現結果。

    9. 數組複製時,使用System.arraycopy()命令。 
      arrayCopy命令比迴圈複製數組快很多

java記憶體最佳化實踐

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.