1. 程式人生 > >堆內記憶體與對外記憶體區別

堆內記憶體與對外記憶體區別

名詞解釋:

    堆內記憶體:on-heap memory

    對外記憶體:off-heap memory


堆內與堆外的關係

     其實堆內堆外是兩個相對的關係,堆內記憶體是我們常用到的。Java分配的非空物件都是由java虛擬機器的垃圾收集器管理的,這一部分稱為堆內記憶體,虛擬機器會定期對垃圾記憶體進行回收,在某些特定的時間點,它會進行一次徹底的回收(full gc)。徹底回收時,垃圾收集器會對所有分配的堆內記憶體進行完整的掃描,這意味著一個重要的事實——這樣一次垃圾收集對Java應用造成的影響,跟堆的大小是成正比的。過大的堆會影響Java應用的效能。所以說給應用分配的記憶體越大,系統性能就越好,因為對應的垃圾回收的代價也就越大,具體如下圖:

堆內記憶體 = 新生代+老年代+持久代

  對於JVM,在jvm引數中只要使用-Xms,-Xmx等引數就可以設定堆的大小和最大值

目前常用的垃圾回收演算法有很多種:

     

  • 引用計數器法(Reference Counting)
  • 標記清除法(Mark-Sweep)
  • 複製演算法(Coping)
  • 標記壓縮法(Mark-Compact)
  • 分代演算法(Generational Collecting)
  • 分割槽演算法(Region)
其中 cms是常用的演算法。
為了解決堆內記憶體問題,一種解決方案就是使用堆外記憶體(off-heap memory)。堆外記憶體意味著把記憶體物件分配在Java虛擬機器的堆以外的記憶體,這些記憶體直接受作業系統管理(而不是虛擬機器)。這樣做的結果就是能保持一個較小的堆,以減少垃圾收集對應用的影響。
使用堆外記憶體的優勢:       

1、減少了垃圾回收


因為垃圾回收會暫停其他的工作。

2、加快了複製的速度
堆內在flush到遠端時,會先複製到直接記憶體(非堆記憶體),然後在傳送;而堆外記憶體相當於省略掉了這個工作。

同樣任何一個事物使用起來有優點就會有缺點,堆外記憶體的缺點就是記憶體難以控制,使用了堆外記憶體就間接失去了JVM管理記憶體的可行性,改由自己來管理,當發生記憶體溢位時排查起來非常困難。

目前很流行spark技術,經常導致OOM,就是因為堆內記憶體管理出現問題,但是也提出改進

這一部分後續再新增


部分參考:http://www.jianshu.com/p/50be08b54bee

   spark記憶體管理機制:https://www.ibm.com/developerworks/cn/analytics/library/ba-cn-apache-spark-memory-management/index.html