4年前 (2020-12-21)  jvm |   抢沙发  4419 
文章评分 0 次,平均分 0.0

使用JProfiler查找内存泄漏

JProfiler是由ej技术开发的java剖析器,它可以帮助开发人员解决性能瓶颈、发现内存泄漏和理解线程问题。它提供了许多有用的工具,如内存分析、分析堆快照的方法以及显示当前正在使用的所有对象的实时内存视图。JProfiler提供了更多的特性,比如数据库分析,但是这些特性不在本文的讨论范围之内。

有很多关于不同类型的内存泄漏及其内存占用情况的博客文章和文章,不幸的是,仅仅基于内存图很难找到内存泄漏。我们将研究一个内存泄漏,并研究如何使用JProfiler提供的工具进行检测。

JProfiler在启动后显示几个图形。根据我们选择的选项,在启动分析会话时,它会向我们显示内存、垃圾收集器活动、记录的吞吐量、CPU负载等等。

例如,这是用于启动服务的内存图。

使用JProfiler查找内存泄漏

对于从未处理过内存泄漏的人,查看此图,他可能会认为内存泄漏是随着内存使用量不断增加而发生的。但是如果我们查看启动期间内存增加的GC活动图,我们会发现垃圾收集器没有运行(活动为0%)。只有在启动期结束时,我们才能看到垃圾收集器图中的峰值和已用内存的急剧减少。因此,如果我们没有等待足够长的时间让垃圾回收器运行,我们可能会得出错误的结论,即发生了内存泄漏。

为了了解实际内存泄漏的情况,我们在Baeldung内存泄漏文章的基础上创建了一个示例。在我们的示例中,我们希望加载某种不同模型的所有属性。对于这个例子,我们自己生成包含属性的模型对象。

private static List<Model.Attribute> getAllModelAttributes(){
        // Model is only used within this method
        List<Model> models = Model.getModelList();

        return models.stream()
                .map(Model::getAttribute)
                .collect(Collectors.toList());
    }

使用JProfiler查找内存泄漏

让我们看看GC活动图;在显示的持续时间内有许多峰值。这意味着垃圾回收器尝试释放内存,但是如果我们查看峰值发生时的内存图,就会发现垃圾回收器没有成功,因为没有释放内存。这可能有内存泄漏以外的原因,例如,一个大的缓存来加速属性访问。但是,我们知道我们的应用程序没有这样的缓存,内存的高使用率是相当可疑的。为了确保我们必须处理内存泄漏,让我们看看当前内存中的所有对象。

使用JProfiler查找内存泄漏

为了找出内存中当前有哪些对象,我们使用“livememory/allobjects”视图。从前两行可以看出,我们有大量的模型实例和模型.属性类,它们一起消耗2.4GB内存。好了,现在我们知道是什么占据了内存。不幸的是,我们还不知道代码在哪里被引用。因为我们只提取模型的属性,然后就不再使用它了,因此应该由垃圾回收器收集。通过获取堆快照,我们可以进一步分析内存问题。通过查看“传入引用”,我们可以使用“Show Paths to GC Root”函数来确定垃圾回收器无法处理这些实例的原因。

使用JProfiler查找内存泄漏

现在我们寻找第一个对我们来说很熟悉的条目;在本例中,它是io.viesure.Model$属性。这意味着Model.Attribute对象包含对模型对象的引用,现在我们必须研究为什么会出现这种情况。

为了找到问题,我们查看模型.属性类以及如何实例化这些对象。在本例中,问题在于开发人员将属性类定义为非静态嵌套类,即所谓的内部类。

public class Model {
    ...
    public class Attribute{
        ...
    }
}

内部类可以访问包含类实例的实例成员,因此需要对其包含类的引用。对于我们的用例,我们不需要这种行为,所以我们只需将内部类更改为静态嵌套类。

public class Model {
    ...
    public static class Attribute{
        ...
    }
}

让我们再次分析一下我们的应用程序,看看内存消耗是否发生了变化。

使用JProfiler查找内存泄漏

将新的内存图与旧的内存图进行比较,我们发现内存使用量比以前低了很多,从3gb左右下降到1.5gb。我们还可以记录对象并检查是否仍然可以找到模型类的实例。

使用JProfiler查找内存泄漏

我们成功地发现了内存泄漏,并显著减少了应用程序使用的内存。当然,这只是一个小例子,关于如何使用JProfiler来分析我们的应用程序,大多数情况下很难发现内存泄漏,但是这个博客简要介绍了哪些工具可以帮助识别内存泄漏。
使用JProfiler查找内存泄漏

 

除特别注明外,本站所有文章均为老K的Java博客原创,转载请注明出处来自https://javakk.com/1067.html

关于

发表评论

表情 格式

暂无评论

登录

忘记密码 ?

切换登录

注册