java由于拥有自动垃圾回收机制,所以一般情况下,我们不需要考虑内存泄漏的问题。jvm会自动收回无用的对象。所谓无用的对象,表示你的程序不可能再访问的对象。

但是,有一种情况必须考虑,就是要防止容器(List,Map等)内的对象无限增大。因为对象存贮在容器中,会被容器引用,从而如果容器的有效,容器内的对象就不会释放。

一旦真的出现内存泄漏,随着时间的推移,java程序逐渐增大内存消耗,最后出现OutOfMemory异常而终止。

如何查找内存泄漏?

这种情况下,一般需要找到内存泄漏的对象。也就是要找到哪个对象数量最大。我们可以利用java SDK 自带的工具 jmap


在命令行中输入: jmap -histo:live [java进程id]>C:Log.txt


例如:如果当前内存泄漏的程序进程id是 3696,但是进程还没有终止。这个时候,可以在命令行中输入 jmap -histo:live 3696>C:\\Log.txt

这样会将结果输入到C:\\Log.txt文件中,应写字板打开,可以看到对象数量以及占用内存情况:


 num     #instances         #bytes  class name
----------------------------------------------
   1:      34637921     1385516840  World.GameMap$ChangeTunAction
   2:         17093      172636824  [Ljava.lang.Object;
   3:        441074      140380032  [C
   4:        439899       10557576  java.lang.String
   5:         48858        8277760  [I
   6:         60774        2917152  java.util.TreeMap
   7:         84480        2703360  World.Task.GameTaskLevelUpVIP
   8:         55968        2238720  World.Task.GameTaskPassLevel
   9:         63979        2047328  java.util.LinkedList
  10:         46754        1496128  java.util.HashMap$Node
  11:         60767        1458408  core.Timer
  12:         34848        1393920  World.Task.GameTaskLogin
  13:          1056        1334784  [LWorld.Task.GameTask;

......


以上日志可以看出,World.GameMap.ChangeTunAction类的实例数量有34637921个,占用内存1.28G,因此可以断定,是这个类的对象没有释放造成内存泄漏。

查找源程序相关代码,可以迅速找到出错位置。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐