使用jprofile发现和修复内存泄露

9/6/2015来源:Java教程人气:2545

使用jPRofile发现和修复内存泄露

性能分析有一项是:发生OOM时,浏览对象分配和引用以发现和修复内存泄露;

示例程序PointFactory

public class PointFactory {    protected ArrayList points = new ArrayList();    protected static PointFactory instance = new PointFactory();    public Point createPoint(int x, int y) {        Point point = new Point(x, y);        this.points.add(point);        return point;    }    public void removePoint(Point point) {        this.points.remove(point);    }    public void printTestPoints() {        for (int i = 0; i < 5; i++) {            Point point = createPoint(i, i);            System.out.println("Point = " + point);        }    }    public static PointFactory getInstance() {        return instance;    }    public static void main(String[] args) throws Exception {        JFrame frame = new JFrame("Points Test");        frame.setDefaultCloSEOperation(WindowConstants.EXIT_ON_CLOSE);        JButton button = new JButton("Print Test Points");        button.addActionListener(new ActionListener() {            public void actionPerformed(ActionEvent e) {                PointFactory.getInstance().printTestPoints();            }        });        frame.getContentPane().add(button);        frame.setSize(200, 100);        frame.setVisible(true);    }}
View Code

运行PointFactory;

clip_image001[8]

运行jprofile,选择本地jvm;

clip_image002[5]

选择程序;

clip_image003[4]

来了个很恐怖的警告:

clip_image004[4]

某些情况下,在attach mode下有一个bug会导致jvm崩溃;

Sun JVM Attach API是Sun JVM中的一套非标准的可以连接到JVM上的API;

Bug详情:

  • Sun java (HotSpot) client JVM can crash in attach mode due to a JVM bug Due to a JVM bug 6776659 HotSpot client JVM can crash in attach mode. There is no crash for the server JVM: JVM option -server solves the problem.

源文档 <https://www.yourkit.com/docs/java/help/attach_agent.jsp>

咱还是听话运行在server mode吧;

clip_image005[4]

这次就没提示了;

选择

clip_image006[4]

选择instrumentation仪表盘,我们要看所有的分析;

clip_image007[4]

这么多类咋看嘛,怀疑Point类存在内存泄露,那就只看它了,设置View Filters;

clip_image008[4]

这时候还没有点按钮,所以没有创建一个类;点!

clip_image009[4]

clip_image010[4]

但是视图里边还是空啊;

得用java.awt.Point,幸好我够机智;

clip_image011[4]

为啥5个类出来total是333?

再点一次,变成418;

clip_image012[4]

点击垃圾回收Run GC:

clip_image013[4]

剩10个实例,正常了;本应10个实例,为什么会有418个那么多;

以此类推,点按钮,Run GC,然后total每点一次增加5个,证明了Point类是回收不掉的;

已经集成到eclipse的话,可以Profile As Java application,很方便;

clip_image014[4]

那为啥Point类没释放呢?明明它已经没用了;

实际项目中,找源代码然后逐个找引用会累死人,咱还是通过运行时堆栈的快照来看吧;

切换到Heap视图;

clip_image015[6]

在累计引用列表可以看到谁引用了Point;

clip_image015[7]

这里是points这个Arraylist引用了,但是没有移除导致;

使用完之后调用removePoint就可以了。