JVM直接内存
概述
直接內(nèi)存并不是虛擬機運行時數(shù)據(jù)區(qū)的一部分,也不是Java 虛擬機規(guī)范中農(nóng)定義的內(nèi)存區(qū)域。在JDK1.4 中新加入了NIO(New Input/Output)類,引入了一種基于通道(Channel)與緩沖區(qū)(Buffer)的I/O 方式,它可以使用native 函數(shù)庫直接分配堆外內(nèi)存,然后通脫一個存儲在Java堆中的DirectByteBuffer 對象作為這塊內(nèi)存的引用進行操作。這樣能在一些場景中顯著提高性能,因為避免了在Java堆和Native堆中來回復(fù)制數(shù)據(jù)。
-
本機直接內(nèi)存的分配不會受到Java 堆大小的限制,受到本機總內(nèi)存大小限制
-
配置虛擬機參數(shù)時,不要忽略直接內(nèi)存 防止出現(xiàn)OutOfMemoryError異常
直接內(nèi)存(堆外內(nèi)存)與堆內(nèi)存比較
代碼驗證:
package com.xnccs.cn.share;import java.nio.ByteBuffer;/*** 直接內(nèi)存 與 堆內(nèi)存的比較*/ public class ByteBufferCompare {public static void main(String[] args) {allocateCompare(); //分配比較operateCompare(); //讀寫比較}/*** 直接內(nèi)存 和 堆內(nèi)存的 分配空間比較* * 結(jié)論: 在數(shù)據(jù)量提升時,直接內(nèi)存相比非直接內(nèi)的申請,有很嚴重的性能問題* */public static void allocateCompare(){int time = 10000000; //操作次數(shù) long st = System.currentTimeMillis();for (int i = 0; i < time; i++) {//ByteBuffer.allocate(int capacity) 分配一個新的字節(jié)緩沖區(qū)。ByteBuffer buffer = ByteBuffer.allocate(2); //非直接內(nèi)存分配申請 }long et = System.currentTimeMillis();System.out.println("在進行"+time+"次分配操作時,堆內(nèi)存 分配耗時:" + (et-st) +"ms" );long st_heap = System.currentTimeMillis();for (int i = 0; i < time; i++) {//ByteBuffer.allocateDirect(int capacity) 分配新的直接字節(jié)緩沖區(qū)。ByteBuffer buffer = ByteBuffer.allocateDirect(2); //直接內(nèi)存分配申請}long et_direct = System.currentTimeMillis();System.out.println("在進行"+time+"次分配操作時,直接內(nèi)存 分配耗時:" + (et_direct-st_heap) +"ms" );}/*** 直接內(nèi)存 和 堆內(nèi)存的 讀寫性能比較* * 結(jié)論:直接內(nèi)存在直接的IO 操作上,在頻繁的讀寫時 會有顯著的性能提升* */public static void operateCompare(){int time = 1000000000;ByteBuffer buffer = ByteBuffer.allocate(2*time); long st = System.currentTimeMillis();for (int i = 0; i < time; i++) {// putChar(char value) 用來寫入 char 值的相對 put 方法buffer.putChar('a');}buffer.flip();for (int i = 0; i < time; i++) {buffer.getChar();}long et = System.currentTimeMillis();System.out.println("在進行"+time+"次讀寫操作時,非直接內(nèi)存讀寫耗時:" + (et-st) +"ms");ByteBuffer buffer_d = ByteBuffer.allocateDirect(2*time);long st_direct = System.currentTimeMillis();for (int i = 0; i < time; i++) {// putChar(char value) 用來寫入 char 值的相對 put 方法buffer_d.putChar('a');}buffer_d.flip();for (int i = 0; i < time; i++) {buffer_d.getChar();}long et_direct = System.currentTimeMillis();System.out.println("在進行"+time+"次讀寫操作時,直接內(nèi)存讀寫耗時:" + (et_direct - st_direct) +"ms");} }輸出:?
在進行10000000次分配操作時,堆內(nèi)存 分配耗時:12ms?
在進行10000000次分配操作時,直接內(nèi)存 分配耗時:8233ms?
在進行1000000000次讀寫操作時,非直接內(nèi)存讀寫耗時:4055ms?
在進行1000000000次讀寫操作時,直接內(nèi)存讀寫耗時:745ms
可以自己設(shè)置不同的time 值進行比較
分析
從數(shù)據(jù)流的角度,來看
非直接內(nèi)存作用鏈:?
本地IO –>直接內(nèi)存–>非直接內(nèi)存–>直接內(nèi)存–>本地IO?
直接內(nèi)存作用鏈:?
本地IO–>直接內(nèi)存–>本地IO
直接內(nèi)存使用場景
- 有很大的數(shù)據(jù)需要存儲,它的生命周期很長
- 適合頻繁的IO操作,例如網(wǎng)絡(luò)并發(fā)場景
參考
《深入理解Java虛擬機》 –周志明
博文:https://www.cnblogs.com/xing901022/p/5243657.html
轉(zhuǎn)發(fā):https://blog.csdn.net/leaf_0303/article/details/78961936
總結(jié)
- 上一篇: 【C++深度剖析教程15】经典问题解析之
- 下一篇: AdBlock插件离线安装