使用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;

使用jprofile发现和修复内存泄露_第1张图片

运行jprofile,选择本地jvm;

使用jprofile发现和修复内存泄露_第2张图片

选择程序;

使用jprofile发现和修复内存泄露_第3张图片

来了个很恐怖的警告:

使用jprofile发现和修复内存泄露_第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吧;

使用jprofile发现和修复内存泄露_第5张图片

这次就没提示了;

选择

使用jprofile发现和修复内存泄露_第6张图片

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

使用jprofile发现和修复内存泄露_第7张图片

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

使用jprofile发现和修复内存泄露_第8张图片

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

使用jprofile发现和修复内存泄露_第9张图片

使用jprofile发现和修复内存泄露_第10张图片

但是视图里边还是空啊;

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

使用jprofile发现和修复内存泄露_第11张图片

为啥5个类出来total是333?

再点一次,变成418;

使用jprofile发现和修复内存泄露_第12张图片

点击垃圾回收Run GC:

使用jprofile发现和修复内存泄露_第13张图片

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

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

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

使用jprofile发现和修复内存泄露_第14张图片

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

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

切换到Heap视图;

使用jprofile发现和修复内存泄露_第15张图片

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

使用jprofile发现和修复内存泄露_第16张图片

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

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

你可能感兴趣的:(profile)