Как найти утечки памяти в моем приложении Java - PullRequest
3 голосов
/ 30 марта 2019

Это дополнительный вопрос из моего предыдущего вопроса ЗДЕСЬ .Я был свидетелем утечки памяти в моем приложении Java.Первоначально я думал, что утечка происходит от серверного компонента моего приложения.Но по предложению другого, это не так.

Я использовал инструмент для сброса памяти кучи и визуализации ее с помощью JProfiler.Видимо, это связано с моим подозрением HashMaps.Но я не уверен, так как не знаю, как интерпретировать дамп.

enter image description here

Вот краткий фрагмент структуры моего приложения (кэширует некоторые текстовые данные каждые 15 минут для быстрого поиска потока сервера).

В чем причина утечки?А как это идентифицировать из дампа ниже?Очевидно, что у меня new Object() и HashMap.put() есть некоторые проблемы с утечками?!

Первый класс стартера / основной.Здесь я инициирую 7 основных HashMaps, каждый из которых сопоставляет ключ (сейчас только один - в конечном итоге будет иметь 16 ключей) с временным рядом NavigableMap из примерно 4000 однострочных JSON строк.

public class MyCache {
        static HashMap <String, NavigableMap <Long, String>> map1= new HashMap <String, NavigableMap <Long, String>> ();
        static HashMap <String, NavigableMap <Long, String>> map2= new HashMap <String, NavigableMap <Long, String>> ();
        static HashMap <String, NavigableMap <Long, String>> map3= new HashMap <String, NavigableMap <Long, String>> ();
        static HashMap <String, NavigableMap <Long, String>> map4= new HashMap <String, NavigableMap <Long, String>> ();
        static HashMap <String, NavigableMap <Long, String>> map5= new HashMap <String, NavigableMap <Long, String>> ();
        static HashMap <String, NavigableMap <Long, String>> map6= new HashMap <String, NavigableMap <Long, String>> ();
        static HashMap <String, NavigableMap <Long, String>> map7= new HashMap <String, NavigableMap <Long, String>> ();

        public static void main(String[] args) throws Exception {
    new Server();
    new Aggregation();
    }
}

А затем в Aggregation() я получаю некоторые тексты из ресурса HTTP, преобразую их в строки JSON и кэширую их во временные NavigableMaps, а затем помещаю их в основной HashMap (поэтому обновление не будетсильно влияет на сервер).

public class Aggregation {
    static NavigableMap <Long, String> map1Temp= new ConcurrentSkipListMap <Long, String> ();;
    static NavigableMap <Long, String> map2Temp = new ConcurrentSkipListMap <Long, String> ();
    static NavigableMap <Long, String> map3Temp= new ConcurrentSkipListMap <Long, String> ();
    static NavigableMap <Long, String> map4Temp= new ConcurrentSkipListMap <Long, String> ();
    static NavigableMap <Long, String> map5Temp = new ConcurrentSkipListMap <Long, String> ();
    static NavigableMap <Long, String> map6Temp = new ConcurrentSkipListMap <Long, String> ();
    static NavigableMap <Long, String> map7Temp = new ConcurrentSkipListMap <Long, String> ();

public Aggregation(){

// loop to cache last 15 mins
while (true) {
            logger.info("START REFRESHING ...");
    for (int i = 0; i < mylist.size(); i++) {
        long startepoch = getTime(mylist.get(i).time);
        MyItem m = mylist.get(i);
        String index=(i+1)+"";

        process1(index, m.name, startepoch);
        //adds to map1Temp
        process2(index, m.name, startepoch);
        //adds to map2Temp
        process3(index, m.name, startepoch);
        //adds to map3Temp
        process4(index, m.name, startepoch);
        //adds to map4Temp
        process5(index, m.name, startepoch);
        //adds to map5Temp
        process6(index, m.name, startepoch);
        //adds to map6Temp
        process7(index, m.name, startepoch);
        //adds to map7Temp
        }

    //then `put` them in the main `HashMap` all at-once:
            MyCache.map1.put(channel, new ConcurrentSkipListMap <Long, String> (map1Temp));
            MyCache.map2.put(channel, new ConcurrentSkipListMap <Long, String> (map2Temp));
            MyCache.map3.put(channel, new ConcurrentSkipListMap <Long, String>(map3Temp));
            MyCache.map4.put(channel, new ConcurrentSkipListMap <Long, String>(map4Temp));
            MyCache.map5.put(channel, new ConcurrentSkipListMap <Long, String> (map5Temp));
            MyCache.map6.put(channel, new ConcurrentSkipListMap <Long, String> (map6Temp));
            MyCache.map7.put(channel, new ConcurrentSkipListMap <Long, String> (map7Temp));

//printing the size of all Hashmap entries. They don't grow :-/
logger.info("\t"+"map1.size(): "+MyCache.map1.get(key).size());
logger.info("\t"+"map2.size(): "+MyCache.map2.get(key).size());
//and other 5...        

//then clear the temp maps so they don't grow over and over
            map1Temp.clear();
            map2Temp.clear();
            map3Temp.clear();
            map4Temp.clear();
            map5Temp.clear();
            map6Temp.clear();
            map7Temp.clear();
    }
//sleep for 15 min until next caching cycle
Thread.sleep(cacheEvery*1000*60);
}

1 Ответ

3 голосов
/ 30 марта 2019

Анализатор памяти сообщает вам, что у вас есть 3 огромных структуры данных HashMap, занимающих около 8 ГБ ОЗУ ... включая ключ закрытия и объекты значений, на которые они ссылаются. Похоже, это могут быть карты карт.

Это, вероятно, свидетельство вашей утечки памяти. Ваше приложение добавляет все больше и больше записей в структуры данных карты и (предположительно) не удаляет их. Это форма утечки памяти.

(Обратите внимание, что это часть кода, который вы не показали нам в своем предыдущем вопросе ...)

...