直接內存
1.直接內存不是虛擬機運行時數據區的一部分,也不是《Java虛擬機規范》中定義的內存區域。
2.直接內存是Java堆外的、直接向系統申請的內存區間。
3.簡單理解: java process memory = java heap + native memory
示例代碼:
/** * IO NIO (New IO / Non-Blocking IO) * byte[] / char[] Buffer * Stream Channel * * 查看直接內存的占用與釋放 */ public class BufferTest { private static final int BUFFER = 1024 * 1024 * 1024;//1GB public static void main(String[] args){ //直接分配本地內存空間 ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER); System.out.println("直接內存分配完畢,請求指示!"); Scanner scanner = new Scanner(System.in); scanner.next(); System.out.println("直接內存開始釋放!"); byteBuffer = null; System.gc(); scanner.next(); } }
直接內存來源於NIO
通過存在堆中的DirectByteBuffer操作Native內存。訪問直接內存的速度會優於Java堆。即讀寫性能高。
- 因此出於性能考慮,讀寫頻繁的場合可能會考慮使用直接內存
- Java的NIO庫允許Java程序使用直接內存,用於數據緩沖區
直接內存異常OOM
同樣,也可能導致OutOfMemoryError異常:OutOfMemoryError: Direct buffer memory
由於直接內存在Java堆外,因此它的大小不會直接受限於一Xmx指定的最大 堆大小,但是系統內存是有限的,Java堆和直接內存的總和依然受限於操作系統能給出的最大內存。
/** * 本地內存的OOM: OutOfMemoryError: Direct buffer memory */ public class BufferTest2 { private static final int BUFFER = 1024 * 1024 * 20;//20MB public static void main(String[] args) { ArrayList<ByteBuffer> list = new ArrayList<>(); int count = 0; try { while(true){ ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER); list.add(byteBuffer); count++; try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } finally { System.out.println(count); } } }
直接內存參數設置
- 使用直接內存的缺點
- 分配回收成本較高
- 不受JVM內存回收管理
- 直接內存大小可以通過MaxDirectMemorySize設置
- 如果不指定,默認與堆的最大值一Xmx參數值一致