第11章ダイレクトメモリ(ダイレクトメモリ)
ShangシリコンバレーのSongHongkangが説明したJVM:bilibili link
-
これは、仮想マシンのランタイムデータ領域の一部ではなく、「Java仮想マシン仕様」で定義されているメモリ領域でもありません。
-
直接メモリは、Javaヒープの外側にあり、システムに直接適用されるメモリ空間です。
-
これはNIOから取得され、ヒープに格納されているDirectByteBufferを介してネイティブメモリを操作します。
/** * 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(); } }
-
一般に、直接メモリへのアクセス速度は、Javaヒープの速度よりも優れています。つまり、高い読み取りおよび書き込みパフォーマンスです。
- したがって、パフォーマンスを考慮するために、頻繁な読み取りと書き込みにはダイレクトメモリを考慮することができます。
- JavaのNIOライブラリを使用すると、Javaプログラムでデータバッファリングにダイレクトメモリを使用できます。
-
OutOfMemoryErrorを引き起こす可能性もあります
-
ダイレクトメモリはJavaヒープの外部にあるため、そのサイズは-Xmxで指定された最大ヒープサイズによって直接制限されませんが、システムメモリが優先され、Javaヒープとダイレクトメモリの合計はオペレーティングシステムの最大値に制限されます。 RAMを与えることができます。
/** * 本地内存的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で設定できます
/** * 绕过DirectByteBuffer,直接分配本地内存 * -Xmx20m -XX:MaxDirectMemorySize=10m * * @author shkstart [email protected] * @create 2020 0:36 */ public class MaxDirectMemorySizeTest { private static final long _1MB = 1024 * 1024; public static void main(String[] args) throws IllegalAccessException { Field unsafeField = Unsafe.class.getDeclaredFields()[0]; unsafeField.setAccessible(true); Unsafe unsafe = (Unsafe) unsafeField.get(null); while (true) { unsafe.allocateMemory(_1MB); } } }
-
指定しない場合、デフォルトはヒープ-Xmxパラメーター値の最大値と同じです。
簡単な理解:Javaプロセスメモリ= Javaヒープ+ネイティブメモリ