Java中典型的内存泄露问题和解决方法

 更新时间:2014年04月28日 08:37:04   转载 作者:  
这篇文章主要介绍了Java中典型的内存泄露问题和解决方法,典型的内存泄露例子是一个没有实现hasCode和 equals方法的Key类在HashMap中保存的情况,可以通过实现Key类的equals和hasCode方法解决这种内存泄漏问题,需要的朋友可以参考下

Q:在Java中怎么可以产生内存泄露?
A:Java中,造成内存泄露的原因有很多种。典型的例子是一个没有实现hasCode和
equals方法的Key类在HashMap中保存的情况。最后会生成很多重复的对象。所有的内存泄露
最后都会抛出OutOfMemoryError异常,下面通过一段简短的通过无限循环模拟内存泄露
的例子说明一下。

复制代码 代码如下:

import java.util.HashMap;
import java.util.Map;

public class MemoryLeak {

 public static void main(String[] args) {
  Map<Key, String> map = new HashMap<Key, String>(1000);

  int counter = 0;
  while (true) {
       // creates duplicate objects due to bad Key class
   map.put(new Key("dummyKey"), "value");
   counter++;
   if (counter % 1000 == 0) {
    System.out.println("map size: " + map.size());
    System.out.println("Free memory after count " + counter
      + " is " + getFreeMemory() + "MB");

    sleep(1000);
   }

   
  }
 }

 // inner class key without hashcode() or equals() -- bad implementation
 static class Key {
  private String key;

  public Key(String key) {
   this.key = key;
  }

 }

 //delay for a given period in milli seconds
 public static void sleep(long sleepFor) {
  try {
   Thread.sleep(sleepFor);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
 }

 //get available memory in MB
 public static long getFreeMemory() {
  return Runtime.getRuntime().freeMemory() / (1024 * 1024);
 }

}

结果如下:

复制代码 代码如下:

map size: 1000
Free memory after count 1000 is 4MB
map size: 2000
Free memory after count 2000 is 4MB
map size: 1396000
Free memory after count 1396000 is 2MB
map size: 1397000
Free memory after count 1397000 is 2MB
map size: 1398000
Free memory after count 1398000 is 2MB
map size: 1399000
Free memory after count 1399000 is 1MB
map size: 1400000
Free memory after count 1400000 is 1MB
map size: 1401000
Free memory after count 1401000 is 1MB
.....
.....
map size: 1452000
Free memory after count 1452000 is 0MB
map size: 1453000
Free memory after count 1453000 is 0MB
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
 at java.util.HashMap.addEntry(HashMap.java:753)
 at java.util.HashMap.put(HashMap.java:385)
 at MemoryLeak.main(MemoryLeak.java:10)

Q:怎么解决上面的内存泄露?
A:实现Key类的equals和hasCode方法。
 

复制代码 代码如下:

    .....
static class Key {
 private String key;

 public Key(String key) {
  this.key = key;
 }

 
 @Override
 public boolean equals(Object obj) {

  if (obj instanceof Key)
   return key.equals(((Key) obj).key);
  else
   return false;

 }

 @Override
 public int hashCode() {
  return key.hashCode();
 }
}
.....
 

 重新执行程序会得到如下结果:
 

复制代码 代码如下:

 map size: 1
Free memory after count 1000 is 4MB
map size: 1
Free memory after count 2000 is 4MB
map size: 1
Free memory after count 3000 is 4MB
map size: 1
Free memory after count 4000 is 4MB
...
Free memory after count 73000 is 4MB
map size: 1
Free memory after count 74000 is 4MB
map size: 1
Free memory after count 75000 is 4MB
 

Q:在实际场景中,你怎么查找内存泄露?
A:通过以下代码获取线程ID

复制代码 代码如下:

C:\>jps
5808 Jps
4568 MemoryLeak
3860 Main

通过命令行打开jconsole

复制代码 代码如下:

C:\>jconsole 4568

实现了hasCode和equals的Key类和没有实现的图表如下所示:

没有内存泄露的:

造成内存泄露的:



相关文章

  • 谨慎使用Java8的默认方法

    谨慎使用Java8的默认方法

    为什么要谨慎使用Java8的默认方法?本文给出了为什么要慎用Java8默认方法的原因,解释的很详细,感兴趣的朋友可以参考一下
    2016-01-01
  • java用split分割字符串的一个有趣现象

    java用split分割字符串的一个有趣现象

    最近在项目中使用了java中的split分割字符串,发现了一个bug,充分了展示了自己对java底层的认知有很多的不足和欠缺。下面将这次的经过总结出来分享给大家,有需要的朋友们可以参考借鉴,下面来一起看看吧。
    2016-12-12
  • Spring Boot启动过程(四)之Spring Boot内嵌Tomcat启动

    Spring Boot启动过程(四)之Spring Boot内嵌Tomcat启动

    这篇文章主要介绍了Spring Boot启动过程(四)之Spring Boot内嵌Tomcat启动的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2017-04-04
  • 详解Spring Cloud Gateway 数据库存储路由信息的扩展方案

    详解Spring Cloud Gateway 数据库存储路由信息的扩展方案

    这篇文章主要介绍了详解Spring Cloud Gateway 数据库存储路由信息的扩展方案,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-11-11
  • Mybatis中collection和association的使用区别详解

    Mybatis中collection和association的使用区别详解

    这篇文章主要介绍了Mybatis中collection和association的使用区别详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-11-11
  • Java面试问题知识点总结

    Java面试问题知识点总结

    本文主要介绍并且整理了Java面试知识点总结,,有需要的小伙伴可以参考下
    2017-04-04
  • Java各种排序算法汇总(冒泡,选择,归并,希尔及堆排序等)

    Java各种排序算法汇总(冒泡,选择,归并,希尔及堆排序等)

    这篇文章主要介绍了Java各种排序算法,以大量实例形式汇总分析了Java常用的各种排序算法,包括冒泡排序、快速排序、堆排序、插入排序、希尔排序、选择排序、归并排序等,需要的朋友可以参考下
    2015-11-11
  • idea快速搭建spring cloud注册中心与注册的方法

    idea快速搭建spring cloud注册中心与注册的方法

    这篇文章主要介绍了idea快速搭建spring cloud注册中心与注册的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-07-07
  • 3行代码快速实现Spring Boot Oauth2服务功能

    3行代码快速实现Spring Boot Oauth2服务功能

    oauthserver是一个基于Spring Boot Oauth2的完整的独立的Oauth服务器。仅仅需要创建相关数据表,修改数据库的连接信息,你就可以得到一个Oauth服务器。这篇文章给大家介绍3行代码快速实现Spring Boot Oauth2服务功能,需要的朋友参考下吧
    2018-04-04
  • Java中死锁的原理实战分析

    Java中死锁的原理实战分析

    这篇文章主要介绍了Java中死锁的原理,结合具体案例形式分析了java死锁形成的相关原理,需要的朋友可以参考下
    2019-08-08

最新评论