import java.lang.reflect.Method; import java.nio.ByteBuffer; public class ByteBufferTest { public static void main(String[] args) { final String src = "abcdefghijklmn"; final ByteHandler bh = new ByteHandler(); Thread t1 = new Thread(new Runnable() { @Override public void run() { while(true) { ByteBuffer bb = ByteBuffer.allocateDirect(100); bb.put(src.getBytes()); bh.wirte(bb); try { Thread.sleep(200); } catch(InterruptedException e) { e.printStackTrace(); } } } }); t1.start(); try { Thread.sleep(1000); } catch(InterruptedException e) { e.printStackTrace(); } Thread t2 = new Thread(new Runnable() { @Override public void run() { bh.cancel(); } }); t2.start(); } } class ByteHandler { ByteBuffer input = ByteBuffer.allocateDirect(10 * 1024 * 1024); public void wirte(ByteBuffer bs) { int cap = input.capacity(); System.out.println(" -- cap:" + cap); int has = input.limit() - input.position(); System.out.println(" -- has:" + has); if(input.position() > 0) { input.flip(); System.out.println(" -- filip:"); } input.put(bs); System.out.println(" -- put:" + input.getClass().getName() + " , pos:" + cap + ", has:" + has); } public void cancel() { System.out.println(" -- cancel start:"); Clean.gcBuffer(input); System.out.println(" -- cancel:"); } } class Clean { public static void gcBuffer(ByteBuffer buf) { if(buf == null || !buf.isDirect()) { return; } try { Class cls = buf.getClass(); Method cleanerm = cls.getMethod("cleaner"); cleanerm.setAccessible(true); Object cleaner = cleanerm.invoke(buf); Method clean = cleaner.getClass().getMethod("clean"); clean.setAccessible(true); clean.invoke(cleaner); System.out.println("RELEASE operating system mem for " + buf); } catch(Exception ex) { ex.printStackTrace(); } } }
使用堆外内存 byteBuffer, 当 byteBuffer被操作系统清除后, 再对byteBuffer进行put类似的操作, jvm会crash.
目前只是在 1.6 , 1.7 , 1.8 上都有问题. 没有在 1.9 试过.