如何在Java应用程序中查找内存泄漏

如何在Java应用程序中查找内存泄漏,java,memory-leaks,heap-memory,jprofiler,jhat,Java,Memory Leaks,Heap Memory,Jprofiler,Jhat,这是我上一个问题的后续问题。我在Java应用程序中看到内存泄漏。起初,我认为泄漏来自我的应用程序的服务器组件。但根据其他人的建议,事实并非如此 我使用工具转储堆内存,并使用JProfiler将其可视化。显然,这是由于我怀疑的HashMaps。但我不确定,因为我不熟悉如何解释垃圾场 下面是我的应用程序结构的一个简短片段(它每隔15分钟缓存一些文本数据,以便快速检索服务器线程) 是什么导致泄漏问题?如何从下面的垃圾堆中识别它? 显然,我做newobject()和HashMap.put()的方式有一

这是我上一个问题的后续问题。我在Java应用程序中看到内存泄漏。起初,我认为泄漏来自我的应用程序的服务器组件。但根据其他人的建议,事实并非如此

我使用工具转储堆内存,并使用
JProfiler
将其可视化。显然,这是由于我怀疑的HashMaps
。但我不确定,因为我不熟悉如何解释垃圾场

下面是我的应用程序结构的一个简短片段(它每隔15分钟缓存一些文本数据,以便快速检索服务器线程)

是什么导致泄漏问题?如何从下面的垃圾堆中识别它? 显然,我做
newobject()
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();
    }
}

内存分析器告诉你,你有3个巨大的HashMap数据结构,占据了大约8GB的内存。。。包括它们引用的闭包键和值对象。看起来它们可能是地图中的地图

这可能就是你内存泄漏的证据。您的应用程序正在向地图数据结构添加越来越多的条目,并且(大概)没有删除它们。这是内存泄漏的一种形式


(请注意,这是您在上一个问题中没有向我们展示的部分代码…

添加了my类的所有片段。我想知道我的
Hashmaps
不应该变大。你能看一看吗?很明显,它们确实变大了。如果如您所想,地图每15分钟被清除一次,那么这意味着~8GB是15分钟的数据。但不管怎样,您都应该假设探查器实际上告诉您这些映射的内存利用率的真相。您是如何找到8GB的?我看不到任何线索!我算错了。不止这些。3,135 + 2,627 + 2,570 + 2,378 + 2,125 + ... 超过10GB。现在,我不是那种用户界面的专家,可以说地图之间有一些共享。但它仍然在说“很多记忆”。好的。我不知道其他的
1670
hashmap项目是什么。我在每次迭代中创建它们。但我假设GC会清除这些,但显然没有。
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);
}