【问题标题】:How can I force release soft reference如何强制释放软引用
【发布时间】:2019-02-13 22:01:48
【问题描述】:

我知道软引用只会在 JVM 内存不足时释放。如何手动完成?

我的代码:

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

最新的java版本(8-11)有解决办法吗?

【问题讨论】:

  • 这不是重复的,我问的是软引用。
  • 为什么需要这样做?测试工具?
  • 我一直在参考参考资料,想知道这是否可能
  • 它是重复的,因为你不能强制垃圾回收,它包括强引用、弱引用、软引用和幻像。

标签: java garbage-collection soft-references


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

【讨论】:

    【解决方案2】:

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

    例如以下代码

    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();
    

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

    【讨论】:

      【解决方案3】:
      1. 一般你不能:System.gc(); 只是建议 JVM 运行 GC

      2. only when I have no memory - 这完全不对。 GC 的工作比这复杂一点,在 JVM 级别有很多 GC 设置...

      【讨论】:

      • 有什么方法可以模拟吗?
      • 据我所知,没有办法——这是 Java 的一点——你不能对代码中的 GC 做任何事情。仍然放System.gc() 不是一个坏主意,有时它会有所帮助,但不能保证。
      • 这不是问题。也许最新版本的 Java 有一些东西——我已经有足够长的时间没有接触这个领域了,Java 离最初的基本概念越来越远。仍然没有太大的意义担心。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-09-04
      • 2015-10-25
      • 1970-01-01
      • 1970-01-01
      • 2016-12-24
      • 2015-09-15
      • 2012-08-13
      相关资源
      最近更新 更多