在进行堆分析的时候,通常我们是比较两个点之间的堆的情况,调用GC,然后看存在实例最多的对象(这个就是最有可能内存泄漏的?),有没有什么技巧?怎么样才能真正的找出大的内存泄漏点??
---------------
我没有做过内存测试,就我的个人理解,在进行堆分析的时候,比较两个点之间的堆使用情况只能知道是哪些实例占用了比较多的内存,但你还是不知道一直使用着内存的实例到底是哪些啊!
我的经验是,你用java是做前台的肯定不会是数据库连接没有释放的问题,那一般内存泄露就是在使用一些容器的地方。我觉得你应该首先先查看自己的代码是不是存在问题,然后再进行优化!

解决方案 »

  1.   

    to  jFresH_MaN()(AbsolutelyFresh)(java欣人) :
       多谢你的建议,不过,可能是我前面没有说得太清楚:现在的情况是这样的,代码非常庞大(前台代码规模应该在50万行左右,而且是非空非注释的),而且这里面有很多代码都不是我写的:-).前段时间我的做法是,首先从下面的框架开始,一小块一小块的单独划分和加载,利用标记类似原子操作的形式进行分析实例的生成与是否能够回收,但是我发现这样太细了,而且感觉成效不是特别大,并没有发现有太大的泄漏!
      重要的是,现在时间不允许我再这样做下去!也就是说,目前小的泄漏或者说隐藏的非常深的那种泄漏,我可以暂时不理它,毕竟我们的客户的机器性能应该是很好的(一般内存都在G数量级的).
      但是,有什么好方法呢?按照Optimizeit 中Manual Profile中对堆分析的说法,比较两个点(后一个点认为是内存应该正常回收)以后,存在实例最多的就是最有可能内存泄漏的地方. 我很困惑,正如你说的,我仍然不知道实例在什么地方被引用! 查看代码当然是不可缺少的,但是,我现在想请教大虾们的是,有什么好的办法或者技巧可以查出真正泄漏比较严重的地方?(堆比较可以吗?需要注意什么地方?)还有就是什么地方应该重点关注?
       希望大家多多赐教,先谢了!
      

  2.   

    Optimizeit Profiler,JProbe Profiler,JinSight , Purify
    这些工具用过么?可以用来检验内存泄漏
    Vector
      

  3.   

    to tomuno:现在不是用不用工具的问题,我目前使用的是Optimizeit Profiler.我前面就有说明。现在的问题是怎么样能更有成效的检查内存泄漏。   
      真想晕倒
      

  4.   

    看来没有回复了,小弟还有点疑问,请大家帮忙解一下惑:
    1. Object objA = new Object();
    2. Object objB = new Object();
    3. Object objC = new Object();
    4. objA = objB;
    5. objB = objC;
    6. objC = null;
    7. objA = null;我记得以前好像哪个地方说考什么认证的时候,只有第七句才是java虚拟机认为可以回收的内存空间。
    小弟有点胡涂:如下的代码
    1. Object objA = new Object();
    2. Object objB = new Object();
    3. objA = objB;
    在第三句被执行以后,对象objA有一个指向objB的句柄(原来的句柄自动放弃),是否这个时候,最初生成的objA的内存空间就应该被java虚拟机回收呢?
    写一个简单的测试代码,并用Optimizeit跑了一下,发现生成两个A对象,一个是能回收的,如下:
    (但是这样的话,上面的理论好像让我产生了很多迷惑,大家帮帮忙吧!)
    public class Test
    {
        class A
        {
           int i = 0;
        }
        
        class MyFrame extends JFrame
        {
            A a = new A();
            A b = new A();
            public void freeRef()
            {
               a = b;
            }
        }
        
        public static void main(String[] args)
        {
            MyFrame frame = new MyFrame();
            frame.freeRef();
            frame.show();
        }}
      

  5.   

    希望这篇文章 能帮你http://www-900.ibm.com/developerWorks/cn/java/l-JavaMemoryLeak/index.shtml
      

  6.   

    to viano:
      多谢,那个文章我很早就看过了,写的不错。但是小弟不才,关于认证里说的那个问题仍然还是很疑惑:
    1. Object objA = new Object();
    2. Object objB = new Object();
    3. objA = objB;
    在第三句执行以后,objA是否还拥有第一个产生的对象的句柄?此时第一个对象的内存空间是否可以回收?我认为是可以的,正如我上面的例子一样,运行后是可以回收的。
       但是我看一些文章里讲到我上面的七句话时,都说的是第7句才是JVM可以认为回收的内存空间,因为这是JVM规范里规定的。
       我查了一下JVM的规范,没有找到相关的类似讲解的地方(呵呵,可能小弟理解能力不是太好)。现在我一个同事他就坚信,但是我确实没有说服他的理由(我用的是JBuilderX+Optimizeit,他说是JBuilder封装了JVM的缘故,并没有完全按照JVM的规范做?呵呵,晕倒),来个大虾帮忙解释一下吧,多谢了!
      

  7.   

    好像是要在对象赋null以后才能gc的
      

  8.   

    1. Object objA = new Object();
    2. Object objB = new Object();
    3. Object objC = new Object();
    4. objA = objB;
    5. objB = objC;
    6. objC = null;
    7. objA = null;
    第7句才是JVM可以认为回收的内存空间
    -------------
    我的理解,可以将上面的情况转换成
    1. Object objA = new Object(A,objA);
    2. Object objB = new Object(B,objB );
    3. Object objC = new Object(C,objC );
    4. objA = objB;
    5. objB = objC;
    6. objC = null;
    7. objA = null;4.“objA ”指向对象“new Object(B,objB )”
    5.“objB”指向对象“new Object(C,objC )”
    6.“objC”置空
    7.“objA”置空
    所以上面new 的三个对象只有new Object(A,objA)没有引用指向它
    =》所以可回收
    =》“第7句才是JVM可以认为回收的内存空间” 成立
      

  9.   


    其实文章中说的很清楚:“综上所述,Java也存在内存泄露问题,其原因主要是一些对象虽然不再被使用,但它们仍然被引用。”我理解为:   如果我们创建了对象,然后不使用对象 (可能的情况是 赋值null),但是我们仍然在某些地方引用了他们,这样gc 就无法回收 导致java内存泄漏!根据我的理解下面这段程序(1 .. 7 ):
    1. Object objA = new Object();
    2. Object objB = new Object();
    3. Object objC = new Object();
    4. objA = objB;
    5. objB = objC;
    6. objC = null;
    7. objA = null;也会造成内存泄漏, 因为 虽然 objC 被置为 null 但是 objB 引用了它 ojbB 没有被置为 null 后来 ojbA 也被置为 null 按照 文章中的解释 势必造成内存泄漏!
    以上是本人的观点, 希望大家指正!
    :)原文地址:http://www-900.ibm.com/developerWorks/cn/java/l-JavaMemoryLeak/index.shtml
      

  10.   

    我也面临搂主同样的问题
    现在正在检测
    还没有发现更好的办法来检测
    希望搂主发现好方法
    告诉我
    xlongbuilder#yahoo.com.cn
    谢了
      

  11.   

    to badboy_119(菜鸟):
       你的解释不错,对于那七句代码,确实如此,但是我是觉得我后面写的那个例子,重要的代码如下:
    class MyFrame extends JFrame
        {
            A a = new A();
            A b = new A();
            public void freeRef()
            {
               a = b;
            }
        }按照上面的理解: a 拥有"new A(a,a)"的句柄,b 拥有"new A(b,b)"的句柄。在执行了方法freeRef后
                     a拥有A(b,b)的句柄,但是我们并没有主动的动作让"new A(a,a)"的句柄被置空啊。
                     这就是我的疑惑点(测试后,发现这个实例可以回收。按照上面某文章说的JVM虚拟机认为可以回收的条件来核对的话,这并不是一个可以被JVM认为可以回收的空间)。当时,同事和我争论的地方就是这里,他认为是JBuilder在虚拟机的实现上做了改动? 有没有那位大虾可以出来帮忙解释一下,多谢了!!
    to  viano(有心就有翼,我想我能.......) :
        我的疑惑并不是理解不理解Java为什么会有内存泄漏的问题,而是我上面说的那个问题。不过,谢谢你热心帮助,那个文章我以前看过,对理解JAVA的内存泄漏还是有一定帮助。:-)
      

  12.   

    to  xlongbuilder(神仙?妖怪?) :
       呵呵,最后上面拨了几个人来,成立了小组检测。目前确实没有太好的方法,没有高人来指点一二啊。
      

  13.   

    是不是可回收的和已回收的问题啊!你的例子只是说明是可回收的!但是jvm到底什么时候会开始回收我也是一直不能搞清楚的!有大侠知道吗?根据通常的理解,回收肯定是一个设定了一个时间点或是满足某种条件才开始的一段代码!所以,是不是问题在于回收的条件不满足,而,你的项目中确实有好多可回收的资源呢?猜测。。