当前位置: 首页 > 面试题库 >

使用sun.misc.Unsafe?强制释放直接由ByteBuffer分配的本地内存的示例?

董喜
2023-03-14
问题内容

JDK提供了分配所谓的直接ByteBuffer的能力,其中内存是在Java堆之外分配的。这可能是有益的,因为该内存不会被垃圾收集器占用,因此不会增加GC开销:这对于诸如缓存之类的长期存在的属性非常有用。

但是,现有实现存在一个关键问题:仅当拥有的ByteBuffer被html" target="_blank">垃圾回收时,底层内存才被异步分配;没有办法强制提前解除分配。这可能是有问题的,因为GC周期本身不受ByteBuffer的处理的影响,并且考虑到ByteBuffer可能位于旧一代内存区域中,因此有可能在ByteBuffer不再使用后数小时调用了GC。

但是从理论上讲,应该可以直接使用sun.misc.Unsafe方法(freeMemory,allocateMemory):这是JDK本身用于分配/取消分配本机内存的方法。查看代码时,我看到的一个潜在问题是可能会双重释放内存-
因此,我想确保可以正确清除状态。

谁能指出我这样做的代码?理想情况下,将要使用它代替JNA。

看起来指出的答案是个不错的方法:这是Elastic
Search中使用该想法的代码示例。谢谢大家!


问题答案:

sun.misc.Unsafe由于分配的本机内存的基址是java.nio.DirectByteBuffer构造函数的局部变量,因此使用几乎是不可能的。

实际上,您可以使用以下代码强制释放本机内存:

import sun.misc.Cleaner;

import java.lang.reflect.Field;
import java.nio.ByteBuffer;

...

public static void main(String[] args) throws Exception {
    ByteBuffer direct = ByteBuffer.allocateDirect(1024);
    Field cleanerField = direct.getClass().getDeclaredField("cleaner");
    cleanerField.setAccessible(true);
    Cleaner cleaner = (Cleaner) cleanerField.get(direct);
    cleaner.clean();
}


 类似资料:
  • 我改进了代码,以便从垃圾收集器中获得更好的结果。 现在,当我调用时,它确实释放了所有内存。但是,当我在不调用 的情况下观察内存使用情况时,应用程序确实会保留并使用越来越多的内存。 这是否意味着我的改进正在起作用,我的所有引用都是正确的,我可以忽略JVM是如何自己释放内存的。或者,我的代码中是否存在其他问题,这些问题是JVM在不运行垃圾收集器的情况下保留更多内存的原因。

  • 本文向大家介绍Shell实现强制释放内存脚本分享,包括了Shell实现强制释放内存脚本分享的使用技巧和注意事项,需要的朋友参考一下 公司服务器最近两天老是因为内存被使用满而造成死机,实在是受不了老叫机房的人去帮忙重启,专门写了个脚本来释放下内存,当然这台服务器不是太重要,我粗鲁的处理方式估计不会适合大多数服务器,请大家使用之前先考虑清楚,不然造成数据丢失就不关我的事了. 脚本内容: cat che

  • 问题内容: 如果您运行的代码调用Java中的本机库,那么当内存分配应在对象的生存期内持续时,释放这些库分配的内存的常用方法是什么?在C ++中,我将使用析构函数,但是Java从来没有真正使用过析构函数,现在更少了。 我最感兴趣的特定情况是JOCL,其中有一个对象,该对象包装了已编译的OpenCL内核及其所有始终相同的参数。表示已编译内核和参数的结构都在库侧分配,JOCL提供了一种方法,您可以调用该

  • 问题内容: 我正在阅读Python内存管理,希望减少应用程序的内存占用。有人建议,子流程可以大大减轻该问题;但是我在概念上需要做些麻烦。可以请一个简单的例子说明如何解决这个问题。 …变成一个 真正的 子处理函数,该函数不存储额外的“自由列表”? 奖励问题: 这个“自由列表”概念也适用于python c扩展吗? 问题答案: 关于优化建议的重要事项是确保仅在子流程中调用该建议。该和是无关的- 一旦你在

  • 问题 假设我的工作是扫描从直接字节缓冲区读回的所有字节,那么对我来说最快的方法是什么? 我最初问“...利用sun.misc.unsafe”,但这可能是错误的假设。 null 这不同于“我可以使用Unsafe来更快地迭代一个字节[]吗?”问题是,如果没有必要,我甚至不打算在内部将字节拉到byte[]中。 谢谢你抽出时间;只是好奇如果有人(彼得?)做这样的事不安全。

  • Java虚拟机在执行的时候会把管理的内存分配到不同的区域,这些区域称为虚拟机内存;同时对于虚拟机没有直接管理的物理内存,也会有一定的利用,这些被利用但不在虚拟机内存的地方称为本地内存。 JVM内存:受虚拟机内存大小的参数控制,当大小超过参数设置的大小时会报OOM。 本地内存:本地内存不受虚拟机内存参数的限制,只受物理内存容量的限制;虽然不受参数的限制,如果所占内存超过物理内存,仍然会报OOM。 虚