如何强制发布软参考

时间:2019-02-13 22:01:49

标签: java garbage-collection soft-references

我只有在没有内存的情况下才知道软引用释放,但是我可以手动执行吗?

我的代码:

  Object object = new Object();
  ReferenceQueue queue = new ReferenceQueue();
  SoftReference softReference= new SoftReference(object, queue);
  object = null;
  System.gc();
  //now I force release soft reference.

我想发布softReference

我能做到吗?

最新的Java版本(8-11)是否有解决方案?

谢谢。

3 个答案:

答案 0 :(得分:1)

  • System.gc()可能永远不会运行,具体取决于启动垃圾收集之前设置的阈值。
  • 一种选择是在JVM配置中调整-XX:SoftRefLRUPolicyMSPerMB=2500参数。这意味着所有软引用的项目将在2.5秒内删除。希望有帮助。

答案 1 :(得分:1)

正如您所说,当存在内存压力和 强制执行此操作的一种方法是创建实际的内存压力。

例如以下代码

Object object = new Object();
ReferenceQueue queue = new ReferenceQueue();
SoftReference softReference= new SoftReference(object, queue);
new Thread(() -> {
    try {
        queue.remove();
        System.out.println("collected");
    } catch (InterruptedException ex) {}
}).start();
object = null;
try {
    object = new int[10][10][10][10][10][10][10][10][10][10][10][10];
} catch(OutOfMemoryError err) {
    System.out.println("...");
}

打印

collected
...

在我的机器上。

上面的代码示例遵循以下想法:通过肯定会失败的分配请求来触发行为,但是要防止JVM检测到它永远不会成功,就像当JVM检测到分配永远不会成功时一样垃圾收集器的工作,它可能会跳过垃圾收集(并因此清除软引用)。

多维数组分配,这是Java中的数组数组,似乎使当前的实现变得足够混乱,因此实际上可以尝试。使用纯数组的另一种方法是从一个小尺寸开始循环分配,并增大直到失败。

仍然存在JVM优化器检测到从未使用过分配的对象并完全消除分配的风险,但是,对于仅执行一次的代码,这种情况很少发生。

如果唯一需要的效果是清除SoftReference并将其排入队列,例如要测试处理代码,您只需调用clear(),然后在引用对象上调用enqueue()

Object object = new Object();
ReferenceQueue queue = new ReferenceQueue();
SoftReference softReference= new SoftReference(object, queue);
new Thread(() -> {
    try { queue.remove(); } catch (InterruptedException ex) {}
Object object = new Object();
ReferenceQueue queue = new ReferenceQueue();
SoftReference softReference= new SoftReference(object, queue);
new Thread(() -> {
    try {
        queue.remove();
        System.out.println("collected");
    } catch (InterruptedException ex) {}
}).start();
object = null;

Thread.sleep(500);
softReference.clear();
softReference.enqueue();

当软引用是对对象的唯一引用时,清除它会使该对象也有资格进行正常的垃圾回收,而不管实际的内存压力如何。

答案 2 :(得分:0)

  1. 通常,您不能:System.gc();仅建议JVM运行GC

  2. only when I have no memory-这是完全不对的。 GC的工作原理要复杂得多,并且在JVM级别上还有很多GC的设置...