我在使用来自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();
}
}


在第60次迭代时,当java的调用方式如下:java -Xms2m -Xmx2m -cp guava-r09.jar:. test.MapMakerTest(故意减小堆设置以便于查看发生的情况)时,它会因OutOfMemoryError:HeapSpace爆炸。

但是,当映射为Map<String, SoftReference<String>>时(并根据代码其余部分中的更改:侦听器和放置),我可以看到驱逐发生了,代码简单地起作用了,并且值被垃圾回收了。

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

我在用番石榴r09。

谁能解释我在做什么错,为什么我的假设错了?

最好的祝福,
乌杰克

最佳答案

您将相同的对象用作键和值,因此,即使值可以轻而易举地达到,它也可以很强地作为键,并且不适合进行垃圾回收:

map.put(s, s);


尝试使用其他实例:

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

关于java - google-guava MapMaker .softValues()-值未获得GC编辑,OOME:紧随其后的是HeapSpace,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6946213/

10-14 10:47