如何让java系统发布Soft References? [英] How to make the java system release Soft References?

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

问题描述

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



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



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



============= =====后来添加==============================



<感谢所有照顾过的人!



在考虑了所有专业人士和反对者之后,我决定按照 nanda的建议采取蛮力方式/ strong>和 jarnbjo 。然而,似乎JVM并不是那么愚蠢 - 如果你要求一个比VM的内存预算更大的块,它甚至都不会尝试垃圾收集。所以我修改了这样的代码:

  / *强制释放SoftReferences * / 
试试{
final List< long []> memhog = new LinkedList< long []>();
while(true){
memhog.add(new long [102400]);
}
}
catch(最终OutOfMemoryError e){
/ *此时所有SoftReferences都已发布 - 保证。 * /
}

/ *在此继续测试* /


解决方案

这段代码强制JVM刷新所有SoftReferences。而且它的速度非常快。



它比Integer.MAX_VALUE方法更好用,因为这里JVM确实试图分配那么多内存。

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

我现在在我需要使用SoftReferences单元测试代码的任何地方使用这段代码。



更新:这种方法确实只能在低于2G的情况下工作最大内存。



另外,需要非常小心SoftReferences。错误地保留硬引用很容易否定SoftReferences的影响。



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

  
for(int i = 0 ; i< 1000; i ++){
SoftReference< Object> softReference = new SoftReferencelt< Object>(new Object());
if(null == softReference.get()){
抛出新的IllegalStateException(引用不应为null);
}

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

if(null!= softReference.get()){
抛出新的IllegalStateException (参考应为空);
}

System.out.println(它有效!);
}


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.

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!

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 */

解决方案

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

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
}

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

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

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.

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系统发布Soft References?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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