1. 内存泄漏种类 Java使用的内存种类包含三种,这三种类型的内存都可能发生内存泄漏。 • 堆内存泄漏,如果JVM 不能在java 堆中获得更多内存来分配更多java 对象,将会抛出java堆内存不足(java OOM) 错误。如果java 堆充满了活动对象,并且JVM 无法再扩展java 堆,那么它将不能分配更多java 对象。更多情况是程序设计有问题,生成的对象占用过多的堆内存造成堆内存泄漏。 • 本地内存泄漏, 如果JVM 无法获得更多本地内存,它将抛出本地OOM错误。当进程用到的内存到达操作系统的最大限值,或者当计算机用完RAM 和交换空间时,通常会发生这种情况。当发生这种情况时,JVM处于本地内存OOM状态,此时虚拟机会打印相关信息并退出。本地内存泄漏根本原因是Java调用本地库或方法,这些本地库中的API有内存泄漏。 • 加载类(字节码)的Perm内存不足.即指定的Permsize不足以加载系统运行使用的.class字节码文件,就发发生Perm内存不足的错误。 大多数内存泄漏是JVM堆内存泄漏,下面举一个堆内存泄漏的分析及解决方法。
  2. 问题诊断 在压力测试环境,对一Java应用服务进行12小时稳定性压测,压测结束后服务器的CPU使用率还很高,使用top使用观察Java进程使用了720%,机器配置为8C。 使用jstat命令查看java进程,eden区内存占用了接近100%,老年代占用了99.79%,从FGC列看到JVM在不断做Full GC操作。 通过上述分析,可以确定问题的原因是JVM有内存泄漏。
  3. 解决问题 JVM内存泄漏问题的解决相对来说比较简单。 (1)使用下面的命令dump出JVM内存映像 jmap -dump:format=b,file=mydump.bin pid 生成的dump文件会比较大,比JVM配置的堆大小相当 (2)使用内存泄漏工具分析这个dump文件,内存泄漏工具有很多,在百度上一搜就能搜到很多,如MemoryAnalyzer.exe。 从工具分析生成的分析结果可以很容易找到占用内存最多的对象,结合程序分析这个对象在程序中的使用,一般很容易就定位出内存泄漏的原因。
  4. 小结 定位问题和分析问题时下面的工具就可以定位问题和解决问题。 --linux的top命令 --JDK自带的工具jstat和jmap --JVM内存泄漏工具 JVM内存泄漏问题的处理相比C程序内存泄漏更好定位和解决,主要原因是Java有更好用的诊断和分析工具。 对于本地内存泄漏,上述分析方法就不灵了。本地内存泄漏用JDK的工具(如jstat和jmap)是无法找到原因的。解决这类问题还得用解决C程序内存泄漏的方法多定位和分析,结合操作系统日志和命令及一些经验技巧来解决。