今天在研究JVM的直接內存溢出時發現直接內存和堆內存同樣,在直接內存快滿時會觸發full gc,full gc會將未被引用的對象及其指向的直接內存釋放掉,以下爲測試代碼:java
package test.oom; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; /** * VM args: -XX:+PrintGCDetails -XX:MaxDirectMemorySize=500M * @author TZ0643 * */ public class DirectMemoryOOM { private static final int _1MB = 1024 * 1024 * 300; public static void main(String[] args) throws Exception { int count = 0; List<ByteBuffer> bufs = new ArrayList<ByteBuffer>(); while(true) { count++; System.out.println("count=" + count); Thread.sleep(10000); System.out.println("allocate direct."); ByteBuffer buf = ByteBuffer.allocateDirect(_1MB); // 將引用加入集合中防止被GC回收致使直接內存被釋放 // bufs.add(buf); } } }
以下爲執行日誌:測試
count=1 spa
allocate direct.
count=2
allocate direct.
[GC [PSYoungGen: 655K->536K(18944K)] 655K->536K(61440K), 0.0046150 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC [PSYoungGen: 536K->0K(18944K)] [ParOldGen: 0K->479K(42496K)] 536K->479K(61440K) [PSPermGen: 2548K->2547K(21504K)], 0.0184197 secs] [Times: user=0.05 sys=0.00, real=0.02 secs]
Exception in thread "main" Heap
java.lang.OutOfMemoryError: Direct buffer memory
at java.nio.Bits.reserveMemory(Bits.java:658)
at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123)
at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:306)
at test.oom.DirectMemoryOOM.main(DirectMemoryOOM.java:27)
PSYoungGen total 18944K, used 983K [0x00000000eb280000, 0x00000000ec780000, 0x0000000100000000)
eden space 16384K, 6% used [0x00000000eb280000,0x00000000eb375d18,0x00000000ec280000)
當程序在執行第一次的時候內存爲300多M,當buf不添加到list集合中時,不會出現OOM,JVM每次都釋放直接內存;日誌
當buf添加到list中,則出現OOM,因爲buf被引用,沒法被full gc回收,致使直接內存爲600M,而最大直接內存爲500M,出現OOMcode