如何让java系统释放软引用? [英] How to make the java system release Soft References?

查看:19
本文介绍了如何让java系统释放软引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将使用基于 SoftReference 的缓存(这本身就是一件非常简单的事情).但是,我在为它编写测试时遇到了一个问题.

I'm going to use a SoftReference-based cache (a pretty simple thing by itself). However, I've came across a problem when writing a test for it.

测试的目的是检查缓存是否确实在内存清理发生后再次从服务器请求先前缓存的对象.

The objective of the test is to check if the cache does request the previously cached object from the server again after the memory cleanup occurs.

这里我发现了如何让系统释放软引用对象的问题.调用 System.gc() 是不够的,因为软引用在内存不足之前不会被释放.我正在 PC 上运行此单元测试,因此 VM 的内存预算可能非常大.

Here I find the problem how to make system to release soft referenced objects. Calling System.gc() is not enough because soft references will not be released until the memory is low. I'm running this unit test on the PC so the memory budget for the VM could be pretty large.

================== 稍后添加 =============================

================== Added later ==============================

感谢所有认真回答的人!

Thank you all who took care to answer!

在考虑了所有优点和缺点之后,我决定按照 nandajarnbjo 的建议采用蛮力方式.然而,看起来 JVM 并没有那么愚蠢——如果你要求一个单独大于 VM 内存预算的块,它甚至不会尝试垃圾收集.所以我修改了这样的代码:

After considering all pro's and contra's I've decided to go the brute force way as advised by nanda and jarnbjo. It appeared, however, that JVM is not that dumb - it won't even attempt garbage collecting if you ask for a block which alone is bigger than VM's memory budget. So I've modified the code like this:

    /* Force releasing SoftReferences */
    try {
        final List<long[]> memhog = new LinkedList<long[]>();
        while(true) {
            memhog.add(new long[102400]);
        }
    }
    catch(final OutOfMemoryError e) {
        /* At this point all SoftReferences have been released - GUARANTEED. */
    }

    /* continue the test here */

推荐答案

这段代码强制 JVM 刷新所有 SoftReference.而且做起来非常快.

This piece of code forces the JVM to flush all SoftReferences. And it's very fast to do.

它比 Integer.MAX_VALUE 方法工作得更好,因为这里 JVM 确实会尝试分配那么多内存.

It's working better than the Integer.MAX_VALUE approach, since here the JVM really tries to allocate that much memory.

try {
    Object[] ignored = new Object[(int) Runtime.getRuntime().maxMemory()];
} catch (OutOfMemoryError e) {
    // Ignore
}

我现在在任何需要使用 SoftReferences 对代码进行单元测试的地方都使用这段代码.

I now use this bit of code everywhere I need to unit test code using SoftReferences.

更新:这种方法确实只适用于小于 2G 的最大内存.

Update: This approach will indeed work only with less than 2G of max memory.

此外,使用 SoftReferences 时需要非常小心.很容易错误地保留一个硬引用,这会抵消 SoftReferences 的效果.

Also, one need to be very careful with SoftReferences. It's so easy to keep a hard reference by mistake that will negate the effect of SoftReferences.

这是一个简单的测试,显示它每次在 OSX 上都能正常工作.有兴趣知道 JVM 在 Linux 和 Windows 上的行为是否相同.

Here is a simple test that shows it working every time on OSX. Would be interested in knowing if JVM's behavior is the same on Linux and Windows.


for (int i = 0; i < 1000; i++) {
    SoftReference<Object> softReference = new SoftReferencelt<Object>(new Object());
    if (null == softReference.get()) {
        throw new IllegalStateException("Reference should NOT be null");
    }

    try {
        Object[] ignored = new Object[(int) Runtime.getRuntime().maxMemory()];
    } catch (OutOfMemoryError e) {
        // Ignore
    }

    if (null != softReference.get()) {
        throw new IllegalStateException("Reference should be null");
    }

    System.out.println("It worked!");
}

这篇关于如何让java系统释放软引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆