google-guava MapMaker .softValues() - 值不会被 GC 处理,OOME:HeapSpace 如下

发布于 2024-11-28 02:39:14 字数 2001 浏览 1 评论 0 原文

我在使用 google-guava 的 MapMaker 时遇到问题。这是代码:

package test;


import java.lang.ref.SoftReference;
import java.util.Map;
import java.util.Random;

import com.google.common.collect.MapEvictionListener;
import com.google.common.collect.MapMaker;


public class MapMakerTest {

private static Random RANDOM = new Random();

private static char[] CHARS =
    ("abcdefghijklmnopqrstuvwxyz" +
     "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
     "1234567890-=!@#$%^&*()_+").toCharArray();

public static void main(String[] args) throws Exception {
    MapEvictionListener<String, String> listener = new MapEvictionListener<String, String>() {

        @Override
        public void onEviction(String key, String value) {
            System.out.println(">>>>> evicted");
        }
    };
    Map<String, String> map = new MapMaker().
        concurrencyLevel(1).softValues().
        evictionListener(listener).makeMap();
    while (true) {
        System.out.println(map.size());
        String s = getRandomString();
        map.put(s, s);
        Thread.sleep(50);
    }
}

private static String getRandomString() {
    int total = 50000;
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < total; ++i) {
        sb.append(CHARS[RANDOM.nextInt(CHARS.length)]);
    }
    return sb.toString();
}
}

当调用java时,如下所示:java -Xms2m -Xmx2m -cp guava-r09.jar:。 test.MapMakerTest(堆设置如此之小,是为了更容易看到发生的情况),在第 60 次迭代时,它会出现 OutOfMemoryError: HeapSpace 错误。

但是,当映射为 Map> (并根据其余代码的更改:侦听器和放置)时,我可以看到正在发生驱逐,代码可以简单地工作,并且值会被垃圾收集。

在所有文档中,包括此文档:http://guava -libraries.googlecode.com/svn/tags/release09/javadoc/index.html,没有明确提及软引用。调用 put 时,Map 实现不是应该将值包装在 SoftReference 中吗?我对所谓的用法真的很困惑。

我正在使用番石榴 r09。

谁能解释我做错了什么,以及为什么我的假设是错误的?

此致, 乌耶克

I am having trouble using the MapMaker from google-guava. Here is the code:

package test;


import java.lang.ref.SoftReference;
import java.util.Map;
import java.util.Random;

import com.google.common.collect.MapEvictionListener;
import com.google.common.collect.MapMaker;


public class MapMakerTest {

private static Random RANDOM = new Random();

private static char[] CHARS =
    ("abcdefghijklmnopqrstuvwxyz" +
     "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
     "1234567890-=!@#$%^&*()_+").toCharArray();

public static void main(String[] args) throws Exception {
    MapEvictionListener<String, String> listener = new MapEvictionListener<String, String>() {

        @Override
        public void onEviction(String key, String value) {
            System.out.println(">>>>> evicted");
        }
    };
    Map<String, String> map = new MapMaker().
        concurrencyLevel(1).softValues().
        evictionListener(listener).makeMap();
    while (true) {
        System.out.println(map.size());
        String s = getRandomString();
        map.put(s, s);
        Thread.sleep(50);
    }
}

private static String getRandomString() {
    int total = 50000;
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < total; ++i) {
        sb.append(CHARS[RANDOM.nextInt(CHARS.length)]);
    }
    return sb.toString();
}
}

When java is called like: java -Xms2m -Xmx2m -cp guava-r09.jar:. test.MapMakerTest (the heap settings are so small intentionally to easier see what happens) around the 60th iteration it explodes with OutOfMemoryError: HeapSpace.

However, when the map is Map<String, SoftReference<String>> (and according changes in the rest of the code: the listener, and the put), I can see the evictions taking place, and the code simply works, and the values get garbage collected.

In all of the documentation, including this one: http://guava-libraries.googlecode.com/svn/tags/release09/javadoc/index.html, there is no mention of SoftReferences explicitly. Isn't the Map implementation supposed to wrap the values in SoftReference when put is called? I am really confused about the supposed usage.

I am susing guava r09.

Could anyone maybe explain what I am doing wrong, and why my assumptions are wrong?

Best regards,
wujek

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

寒江雪… 2024-12-05 02:39:14

您对键和值使用相同的对象,因此它作为键是强可达的,并且不符合垃圾回收的条件,尽管值是软可达的:

map.put(s, s); 

尝试使用不同的实例:

map.put(s, new String(s));

You use the same object for key and value, therefore it is strongly reachable as a key and is not eligible for garbage collection despite the fact that value is softly reachable:

map.put(s, s); 

Try to use different instances:

map.put(s, new String(s));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文