如何强制释放软引用
How can I force release soft reference
我知道软引用只会在 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)有解决方案吗?
一般来说你不能:System.gc();
只是建议JVM去运行 GC
only when I have no memory
- 这是不对的。 GC 的工作比这复杂一点,在 JVM 级别上有一堆 GC 设置...
System.gc()
可能永远 运行 取决于垃圾收集开始前设置的阈值。
- 一种选择是调整 JVM 配置中的
-XX:SoftRefLRUPolicyMSPerMB=2500
参数。这意味着任何软引用项都将在 2.5 秒内被删除。希望这有帮助。
如你所说,软可达对象在内存压力和
强制执行此操作的一种方法是创建实际的内存压力。
例如以下代码
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();
当软引用是对象的唯一引用时,清除它会使对象也符合正常垃圾回收的条件,而不管实际内存压力如何。
我知道软引用只会在 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)有解决方案吗?
一般来说你不能:
System.gc();
只是建议JVM去运行 GConly when I have no memory
- 这是不对的。 GC 的工作比这复杂一点,在 JVM 级别上有一堆 GC 设置...
System.gc()
可能永远 运行 取决于垃圾收集开始前设置的阈值。- 一种选择是调整 JVM 配置中的
-XX:SoftRefLRUPolicyMSPerMB=2500
参数。这意味着任何软引用项都将在 2.5 秒内被删除。希望这有帮助。
如你所说,软可达对象在内存压力和 强制执行此操作的一种方法是创建实际的内存压力。
例如以下代码
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();
当软引用是对象的唯一引用时,清除它会使对象也符合正常垃圾回收的条件,而不管实际内存压力如何。