ダイレクトメモリ
ダイレクトメモリの概要
-
これは、仮想マシンのランタイムデータ領域の一部ではなく、「Java仮想マシン仕様」で定義されているメモリ領域でもありません。
-
直接メモリは、システムに直接適用されるJavaヒープの外側のメモリ領域です。
-
NIOから来て、ヒープに格納されたDirectByteBufferを介してネイティブメモリを操作します
-
一般に、直接メモリへのアクセス速度は、Javaヒープの速度よりも優れています。つまり、高い読み取りおよび書き込みパフォーマンスです。
- したがって、パフォーマンスを考慮するために、頻繁な読み取りと書き込みにはダイレクトメモリを考慮することができます。
- JavaのNIOライブラリを使用すると、Javaプログラムでデータバッファにダイレクトメモリを使用できます。
/**
* 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();
}
}
1Gのローカルメモリを直接占有します!
BIO 与 NIO
間接バッファ領域(BIO):元のBIOアーキテクチャが使用されます。ローカルファイルの読み取りと書き込みを行うときは、ユーザーモードからカーネルモードに切り替える必要があります。
ダイレクトバッファ(NIO):物理ディスクを直接操作し、中間プロセスの必要性を排除します。
ダイレクトメモリとOOM
- ダイレクトメモリもOutofMemoryErrorを引き起こす可能性があります。
- ダイレクトメモリはJavaヒープの外部にあるため、そのサイズは-Xmxで指定された最大ヒープサイズによって直接制限されませんが、システムメモリは制限され、Javaヒープとダイレクトメモリの合計はオペレーティングシステムによって制限されます。最大メモリを与えることができます
- ダイレクトメモリの欠点は次のとおりです。割り当てとリサイクルのコストが高く、JVMメモリのリサイクル管理の対象ではありません。
- ダイレクトメモリサイズはMaxDirectMemorySizeで設定できます。
- 指定しない場合、デフォルトはヒープ-Xmxパラメーター値の最大値と同じです。
OOMの例:
/**
* 本地内存的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);
}
}
}
異常な出力:
Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
at java.nio.Bits.reserveMemory(Bits.java:694)
at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123)
at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311)
at com.heu.java.BufferTest2.main(BufferTest2.java:21)
簡単な理解:Javaプロセスメモリ= Javaヒープ+ネイティブメモリ。