https://blog.csdn.net/lidengchun/article/details/75085680
堆內存根據生命周期進行分而治之,分區之后可以提高JVM垃圾收集的效率,更好地回收為了更好地分配。
如果在堆中無法分配內存,並且堆也無法再擴展時,將會拋出OutOfMemoryError異常。
http://blog.csdn.net/qq_17612199/article/details/52316719
HeapByteBuffer與DirectByteBuffer,在原理上,前者可以看出分配的buffer是在heap區域的,其實真正flush到遠程的時候會先拷貝得到直接內存,再做下一步操作(考慮細節還會到OS級別的內核區直接內存),其實發送靜態文件最快速的方法是通過OS級別的send_file,只會經過OS一個內核拷貝,而不會來回拷貝;在NIO的框架下,很多框架會采用DirectByteBuffer來操作,這樣分配的內存不再是在Java heap上,而是在C heap上,經過性能測試,可以得到非常快速的網絡交互,在大量的網絡交互下,一般速度會比HeapByteBuffer要快速好幾倍。
直接內存(Direct Memory)並不是虛擬機運行時數據區的一部分,也不是Java虛擬機規范中定義的內存區域,但是這部分內存也被頻繁地使用,而且也可能導致OutOfMemoryError 異常出現,所以我們放到這里一起講解。
在JDK 1.4 中新加入了NIO(New Input/Output)類,引入了一種基於通道(Channel)與緩沖區(Buffer)的I/O 方式,它可以使用Native 函數庫直接分配堆外內存,然后通過一個存儲在Java 堆里面的DirectByteBuffer 對象作為這塊內存的引用進行操作。這樣能在一些場景中顯著提高性能,因為避免了在Java 堆和Native 堆中來回復制數據。
import sun.nio.ch.DirectBuffer; import java.nio.ByteBuffer; public class Main { public static void main(String[] args) throws InterruptedException { System.out.println("Hello World!"); ByteBuffer bb = ByteBuffer.allocateDirect(1024 * 1024 * 128); Thread.sleep(10000); ((DirectBuffer)bb).cleaner().clean(); Thread.sleep(10000); } }
可以在任務管理器那觀察變化
堆外內存的優點和缺點
堆外內存,其實就是不受JVM控制的內存。相比於堆內內存有幾個優勢:
1 減少了垃圾回收的工作,因為垃圾回收會暫停其他的工作(可能使用多線程或者時間片的方式,根本感覺不到)
2 加快了復制的速度。因為堆內在flush到遠程時,會先復制到直接內存(非堆內存),然后在發送;而堆外內存相當於省略掉了這個工作。
缺點:
1 堆外內存難以控制,如果內存泄漏,那么很難排查
2 堆外內存相對來說,不適合存儲很復雜的對象。一般簡單的對象或者扁平化的比較適合。
優點:
1. 減少GC時間
2. 進程間可以共享,減少虛擬機間的復制
_______________________________________________________________________________________________
為什么引進非Java堆?
1 Java如果和外界通訊,把Java 堆中的內容傳輸到外界,則需要把Java堆復制到非Java堆,如果使用native堆,則避免了內容在Java堆和非Java堆之間的copy.
在什么場景下使用非Java堆?
1 非Java堆的回收不受java gc的影響,一般需要手工進行回收。如果大量的使用非Java堆,則丟失了Java 自動垃圾回收的特點。
一般使用非Java堆進行和外界通訊,並且做為緩存使用。如DirectByteBuffer。