Bộ đệm NIO trực tiếp sử dụng bộ nhớ không được quản lý. Nó có nghĩa là chúng được cấp phát trên heap gốc, không phải trên vùng heap Java. Kết quả là, chúng được giải phóng chỉ khi JVM hết bộ nhớ trên vùng heap Java, không phải trên heap gốc. Nói cách khác, nó không được quản lý = tùy thuộc vào bạn để quản lý chúng. Buộc việc thu gom rác bị nản chí và sẽ không giải quyết được vấn đề này phần lớn thời gian.
Khi bạn biết rằng bộ đệm NIO trực tiếp trở nên vô dụng đối với bạn, bạn phải giải phóng bộ nhớ riêng bằng cách sử dụng sun.misc.Cleaner (StaxMan là đúng) và gọi clean() (trừ Apache Harmony), gọi miễn phí() (với Apache Harmony) hoặc sử dụng API công khai tốt hơn để làm điều đó (có thể trong Java> = 1,9, AutoCleaning mở rộng AutoCloseable?).
Nó không phải công việc JOGL để làm điều đó, bạn có thể sử dụng mã Java đơn giản để tự làm điều đó. My example là theo GPL v2 và this example là theo giấy phép dễ dãi hơn.
Chỉnh sửa .: My latest example hoạt động ngay cả với Java 1.9 và hỗ trợ OpenJDK, Java Java, Sun Java, Apache Harmony, GNU Classpath và Android. Bạn có thể phải loại bỏ một số đường syntactical để làm cho nó hoạt động với Java < 1.7 (đa bắt, kim cương và generics).
tham khảo: http://www.ibm.com/developerworks/library/j-nativememory-linux/
đối tượng trực tiếp ByteBuffer dọn dẹp bộ đệm mẹ đẻ của họ tự động nhưng chỉ có thể làm như vậy như là một phần của Java đống GC - vì vậy họ không tự động ứng phó với áp lực lên đống bản địa.GC chỉ xảy ra khi vùng heap Java trở nên đầy, nó không thể đáp ứng yêu cầu phân bổ heap hoặc nếu ứng dụng Java yêu cầu một cách rõ ràng (không phải được đề xuất vì nó gây ra vấn đề về hiệu suất).
tham khảo: http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#direct
Nội dung của bộ đệm trực tiếp có thể cư trú bên ngoài đống rác-thu bình thường
This solution (trong JEP này, vẫn còn là một dự thảo, có lẽ không có sẵn trong Java 1.9) rất hứa hẹn, chúng tôi sẽ không cần sử dụng các API không công khai.
public long memory(long index) {
// The scope where the memory region is available
// Implements AutoClosable but `close` can be called manually as well
try (Scope scope = new NativeScope()) {
// Allocate the actual memory area, in this case in the style of a "long-array"
Pointer<Long> ptr = scope.allocate(
NativeLibrary.createLayout(long.class), numElements);
// Get the reference to a certain element
Reference<Long> ref = ptr.offset(index).deref();
// Set a value to this element through the reference
ref.set(Long.MAX_VALUE);
// Read the value of an element
return ref.get();
}
}
NB: sun.misc.Cleaner đã được di chuyển vào jdk.internal.ref.Cleaner trong Java 1.9 trong module "java.base" nhưng cụ sau java.lang.Runnable (nhờ Alan Bateman đã nhắc nhở tôi rằng Sự khác biệt). Sau đó, bạn chỉ cần chuyển trình dọn dẹp sang Runnable và gọi phương thức run()
(không gọi nó bằng cách phản ánh để tránh nhận một java.lang.IllegalAccessException). Nó hoạt động, tôi vừa thử nghiệm (tháng 8, 6, 2016) với Java 1.9 Truy cập sớm xây dựng 129.
Tuy nhiên, jdk.internal.ref.Cleaner có thể được chuyển đến java.ref.Cleaner $ Có thể xóa sau.
Có a good example in Lucene theo giấy phép dễ dãi hơn.
Bằng cách "gọi gc", bạn có nghĩa là 'System.gc()' tôi đoán; nó thực sự là một shot dài, như cuộc gọi đó không được đảm bảo để thực sự làm bất cứ điều gì. Hãy chắc chắn để đặt bất kỳ tham chiếu đến bộ đệm trực tiếp '= null' trước khi gọi đó, hoặc GC chắc chắn sẽ nghĩ rằng bộ đệm vẫn còn sử dụng. – Ricket
Nhìn vào câu trả lời của tôi ... – gouessej