1

我知道软引用只会在 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)有解决方案吗?

4

3 回答 3

3
  • System.gc()根据垃圾收集开始之前设置的阈值,可能永远不会运行。
  • 一种选择是调整-XX:SoftRefLRUPolicyMSPerMB=2500JVM 配置中的参数。这意味着任何软引用的项目都将在 2.5 秒内被删除。希望这会有所帮助。
于 2019-02-13T22:30:55.707 回答
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();

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

于 2019-02-14T14:19:30.510 回答
0
  1. 一般来说,你不能: System.gc();只是建议 JVM 运行 GC

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

于 2019-02-13T22:11:27.203 回答