allocateDirect(int capacity): 分配新的直接字節緩衝區.新的緩衝區的位置將爲0,其界限爲其容量,其標記是不肯定的.不管它是否具備底層實現數組,其標記都是不肯定的.java
allocate(int capacity): 分配一個新的非直接字節緩衝區.新緩衝區的位置爲0,其界限爲其容量,其標記是不肯定的.它將具備一個底層實現數組,且其數組偏移量將爲0.編程
若是字節緩衝區爲直接字節緩衝區,則JVM會盡可能在直接字節緩衝區上執行本機I/O操做,也就是直接對內核空間進行訪問,以提升運行效率.提升運行效率的原理就是在每次調用基於操做系統地I/O操做以前或以後,JVM都會盡可能避免將緩衝區的內容複製到中間緩衝區中,或者從中間緩衝區中複製內容,這樣就節省了一個步驟.數組
經過allocateDirect()返回的緩衝區進行內存的分配和釋放所需的時間成本一般高於非直接緩衝區.直接緩衝區操做的數據不在JVM堆中,而是在內核空間中,根據這個結構能夠分析出,直接緩衝區善於保存那些易受操做系統本機I/O操做影響的大量、長時間保存到的數據。bash
使用allocateDirect()方法建立出來的緩衝區類型爲DirectByteBuffer,使用allocate()方法建立出來的緩衝區類型爲HeapByteBuffer.ui
使用allocateDirect()方法建立ByteBuffer緩衝區時,capacity指的是字節的個數,而建立IntBuffer緩衝區時,capacity指的是int值得數目,若是要轉換成字節,則capacity要乘以4,來算出佔用的總字節數。spa
package me.qianlv;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit;
/**
* @author xiaoshu
* 直接緩衝區釋放內存方法
* 1. 手動釋放
* 2. 交給JVM處理
* <p>
* 此程序運行的效果就是1秒鐘以後當即回收內存
* 也就是回收"直接緩衝區"所佔用的內存
*/
public class Test9 {
public static void main(String[] args) throws InterruptedException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
System.out.println("A");
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(Integer.MAX_VALUE);
System.out.println("B");
byte[] byteArray = new byte[]{1};
System.out.println(Integer.MAX_VALUE);
for (int i = 0; i < Integer.MAX_VALUE; i++) {
byteBuffer.put(byteArray);
}
System.out.println("put end.");
TimeUnit.SECONDS.sleep(1);
Method cleanerMethod = byteBuffer.getClass().getMethod("cleaner");
cleanerMethod.setAccessible(true);
Object returnValue = cleanerMethod.invoke(byteBuffer);
Method cleanMethod = returnValue.getClass().getMethod("clean");
cleanMethod.setAccessible(true);
cleanMethod.invoke(returnValue);
}
}
複製代碼
package me.qianlv;
import java.nio.ByteBuffer;
/**
* @author xiaoshu
* 直接緩衝區釋放內存方法
* 1. 手動釋放
* 2. 交給JVM處理
* <p>
* 此程序屢次運行後,一直在耗費內存
* 進程結束後,也不會立刻回收內存
* 而是會在某個時機觸發GC垃圾回收器進行內存回收
*/
public class Test10 {
public static void main(String[] args) {
System.out.println("A");
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(Integer.MAX_VALUE);
System.out.println("B");
byte[] byteArray = new byte[]{1};
System.out.println(Integer.MAX_VALUE);
for (int i = 0; i < Integer.MAX_VALUE; i++) {
byteBuffer.put(byteArray);
}
System.out.println("put end.");
}
}
複製代碼
此*.java類能夠運行屢次,產生多個進程,而後再查看內存使用狀況會更加直觀.操作系統
參考:code