google-guava MapMaker .softValues ​​() - значения не получают GC-ed, OOME: HeapSpace следует - PullRequest
1 голос
/ 04 августа 2011

У меня проблемы с использованием MapMaker из google-guava.Вот код:

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<String, SoftReference<String>> (и соответственно изменениям в остальной части кода: слушателе и путе), я вижу, как происходит выселение, и код просто работает, и значения получаютсясборщик мусора.

Во всей документации, включая эту: http://guava -libraries.googlecode.com / svn / tags / release09 / javadoc / index.html , нетупоминание SoftReferences явно.Разве реализация Map не должна оборачивать значения в SoftReference при вызове put?Я действительно запутался в предполагаемом использовании.

Я использую guava r09.

Может кто-нибудь объяснить, что я делаю неправильно и почему мои предположения неверны?

С уважением, wujek

1 Ответ

3 голосов
/ 04 августа 2011

Вы используете один и тот же объект для ключа и значения, поэтому он легко доступен в качестве ключа и не подходит для сборки мусора, несмотря на то, что значение легко достижимо:

map.put(s, s); 

Попробуйте использовать разныеэкземпляры:

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