Java 内存溢出的原因和解决方法

你是否遇到过Java应用程序卡顿或突然崩溃的情况?您可能遇到过Java内存泄漏。在本文中,我们将深入研究Java内存泄漏的确切原因,并推荐一些最好的工具来防止内存泄漏发生。

什么是JAVA内存泄漏?

简单地说,Java内存泄漏是指对象不再被应用程序使用,而是在工作内存中处于活动状态。

在Java和大多数其他编程语言中,垃圾收集器的任务是删除不再被应用程序引用的对象。如果不选中,这些对象将继续消耗系统内存,并最终导致崩溃。有时java内存泄漏崩溃不会输出错误,但通常错误会以java.lang.OutOfMemoryError

JAVA内存泄漏的原因是什么?

当未被引用的对象被归类为引用对象时,就会导致Java内存泄漏。这会阻止垃圾回收器清除内存,导致内存最终耗尽并崩溃。

在内存中,对象可以有两种状态,未引用和已引用。被引用的对象仍然具有到Java应用程序的活动连接,而未被引用的对象则没有。垃圾回收器的任务是查找和标识未引用的对象并将其删除。

垃圾回收器不会清理似乎被引用或正在使用的对象。Java内存泄漏发生在未引用的对象重叠时,这些对象似乎仍在使用中。

我怎么知道是否有内存泄漏?

有几种方法可以检查你的代码,看看它是否发生了内存泄漏。识别泄漏的最简单方法是查找java.lang.OutOfMemoryError错误日志中的事件。如果列出了此事件,您将能够提取有关Java的哪些部分导致了这种情况的进一步详细信息。

您经常会发现有关Java堆空间的详细信息。这可能意味着内存泄漏,资源无法分配,或者堆大小设置得太低。

通常也会发现标记为PermGen空间的错误。在大多数情况下,这不是内存泄漏,而是需要扩展的分配空间。永久生成空间用于存储类对象,如果不扩展,则可以填充。

并不是所有的Java内存泄漏都是相同的,有些漏洞可以比其他漏洞更容易预防。让我们来看看Java内存泄漏的一些最常见的原因。

如何防止JAVA内存泄漏

最常见的内存泄漏类型之一是Java中的对象随着时间的推移而创建,但从未释放。提高性能和防止内存泄漏的一个简单方法是检查代码中静态字段的使用情况。

当您将Java中的任何对象设置为静态时,它会自动将该对象的生命周期附加到JVM本身,因此垃圾收集器从不清除它。正如您可以想象的那样,如果您有许多大对象被设置为静态的,这会在您的代码中造成相当大的问题。

一定要检查static和collections的所有用法。这两者都是导致Java内存泄漏和意外占用内存的最常见原因。

Java内存泄漏的另一个常见原因是存在未关闭的连接。代码中保持连接打开而不关闭连接的任何部分都可能导致内存过度使用。未闭合连接最常见的罪魁祸首是http调用、stream流、FTP站点和数据库访问。

当保持打开状态时,连接会迅速导致堆内存膨胀,并最终导致应用程序崩溃。若要解决此问题,请始终确保在代码中指定了关闭连接的时间。

就像未关闭的连接一样,未关闭的流会导致非常类似的内存泄漏和资源问题。如果未选中,则打开的流将增加堆内存使用量,以达到临界级别,并最终崩溃。在旧版本的Java中,流必须手动关闭,但是现在使用try with resources语句,这可以自动实现。

虽然寻找这些具体的例子可能会有所帮助,但每个程序的编码都是不同的,需要采用不同的方法。如果您要手动查看代码,启用详细的垃圾收集可以帮助您更好地了解哪些内容正在被收集,哪些内容没有被收集。

添加-verbose:gc参数到配置将准确地输出垃圾收集工具正在执行的操作,并让您深入了解可能需要修改的内容。这是一个简单的技巧,但仍然需要你的时间和精力来筛选结果。

对代码进行可靠的审核还可以发现阻碍性能或导致内存泄漏的潜在问题。虽然这看起来很费时,但这通常是处理所有代码的最佳实践,并有助于避免严重的麻烦。

防止JAVA内存泄漏的工具

最后,为了更快地堵住内存泄漏,可以考虑使用Java分析器。探查器允许您监视特定的JVM参数,例如对象创建和垃圾回收。探查器甚至比详细模式更进一步,可以帮助突出显示需要数小时手动跟踪的内存和资源问题。

您可以使用诸如YourKit或JProfiler这样的Java探查器,不仅可以帮助您发现Java代码中的内存泄漏,还可以确定优化和改进的机会。YourKit和JProfiler都有助于删减不必要的代码并识别应用程序中的冗余。虽然这两个示例都不会导致内存泄漏,但它们会影响代码的性能。

JAVA Profiler可以提供以下功能:

  • 创建的所有对象
  • 所有方法的CPU时间
  • 执行期间创建的对象
  • 从内存中删除的对象
  • 垃圾收集信息

但是,使用一个好的Java分析器只是成功的一半;您还需要监视应用程序的运行状况,因为它会随着时间的推移而变化。为此,您需要将Java分析器与一个著名的Java性能工具配对。

您可以将Java探查器看作是一种反应式工具,而Java性能监视器则是一种主动式工具。您既要确保您的应用程序为您的用户以最佳方式运行,又要避免不必要的停机时间。Java性能监视工具可以测量应用程序的响应能力,监视sla,甚至可以根据用户数据计算许多不同的度量来跟踪用户体验。

我们花了一些时间来寻找一些最好的Java性能工具,可以用来帮助防止Java内存泄漏,并保持代码平稳运行。

以下是我们精选的最佳JAVA性能工具:

  • SolarWinds AppOptics(免费试用)提供多种应用程序的深度视觉效果和报告功能。
  • DataDog Java性能监控工具平衡了易用性,同时优先考虑了主动特性
  • VisualVM是一个简单的Java探查器,非常适合基本的故障排除。
  • JProfiler一种付费的Java评测器,可以检测不同级别的大量bug
  • Eclipse内存分析器MAT提供了Java堆内存的详细细分,以更好地了解内存泄漏。
  • Glowroot一个开源的性能监视器,通过本地浏览器显示数据。

1. SOLARWINDS APPOPTICS(免费试用)

SolarWinds公司的AppOptics是一款全服务的应用程序性能监视器,为大量不同的应用程序构建。虽然AppOptics支持许多程序,但它在监视和排除Java应用程序故障方面做得特别好。

与DataDog类似,AppOptics将强大的功能组合到一个易于使用的仪表板中,允许您自定义和控制您的监视体验。可以从头开始创建警报,也可以从软件附带的预配置模板库中选择警报。

虽然仪表板为您提供了应用程序及其状态的完整概述,但您也可以深入到代码级别并将AppOptics用作性能调谐器。这使得接收实时数据并立即在同一软件中进行故障排除变得很容易。

开发人员可以通过监视Java堆使用率、调用数、错误率和响应时间等指标来监视Java应用程序是否存在内存泄漏或其他许多问题。性能数据也可以通过日志、图表或瀑布跟踪历史地查看,这样可以很容易地缩小时间范围并隔离出问题代码行。

2. DataDog Java性能监控工具

datadog是专门为使监视Java应用程序成为一个简单而直观的过程而构建的。通过交互式仪表板,您可以在服务、客户和端点级别查看Java代码的状态。Datadog通过一个简单的软件即服务(SaaS)模型提供了这些见解。

一旦您输入了代码,DataDog就可以通过自动生成的服务映射识别Java问题、依赖关系和机会。所有这些数据都是从向DataDog报告信息的简单代理安装中提取的。主仪表板将实时和历史性能信息作为可视化和列表项引入,您可以对其进行排序。

总错误、延迟和请求数等指标可以通过仪表板轻松跟踪。可以将此视图更改为网络拓扑视图,以帮助更好地可视化查询之间的关系,以及性能如何影响链下游的其他功能。

通过警报仪表板,您可以根据正常运行时间、异常情况或您设置的特定阈值快速设置通知。很高兴看到这个软件允许您在设置警报模板时组合触发条件。通过尽可能细化您的警报条件,它有助于减少警报疲劳,并保持您的收件箱干净。警报可以通过电子邮件发送,也可以发送到Slack或Pagerduty等其他工具。

当您处理像Java应用程序的性能监视这样复杂的事情时,找到一个既直观又强大的工具会让您耳目一新。您可以免费测试DataDog及其所有功能14天。

3. VisualVM

VisualVM是一个Java故障排除工具,它直接连接到JDK来检测问题,并通过图形界面引起您的注意。开发人员可以查看他们的应用程序堆转储,分析他们的代码,并查看他们的Java应用程序的许多其他见解。因为它直接绑定到您的JDK中,所以可以方便地从您正在工作的地方访问它。

VisualVM相当轻量级,并且直接驻留在本地计算机上,这使得它非常适合在运行中进行故障排除,而且不必依赖基于SaaS的产品。虽然还有其他工具可以提供对Java相关问题的更深入的见解,但VisualVM是一个简单而干净的工具,它非常适合在故障排除过程的开始使用。

当谈到Java分析器时,VisualVM是一个很好的起点,但是您可能需要考虑将其与性能监视工具或其他更详细的探查器配对,以确保找到所有潜在的bug。

您可以在Windows、Linux或macOS操作系统上免费下载VisualVM

4. JPROFILER

JProfiler by EJ Technologies是一款Java评测器,它以易用性和与Java应用程序的轻松集成而自豪。在JVM级别,您可以在执行代码时查看并快速诊断代码中的问题。像Java代码中的内存泄漏这样的问题会在堆内存分析器下快速突出显示。打开和关闭的连接可以通过一个彩色编码的时间线可视化,这样就可以很容易地看到丢失的连接,这些连接保持打开状态并利用资源。JProfiler还有一个内置的堆遍历器,开发人员可以使用它从多个角度查看任何一组对象,以便进行更深入的检查。

默认情况下支持JEE,并将JEE组件分组到调用树中的组中,这样可以更容易地对更高级别的分析数据进行排序,下到粒度级别和其他子系统。

JProfiler与Windows、Linux和macOS兼容,可以使用试用密钥免费测试。

5. Eclipse内存分析器 MAT

为了获得堆内存的详细细分,Eclipse内存分析器被设计成突出显示内存收集中的缺陷并监视Java堆使用的健康状况。存储的任何对象都将显示并在堆中可见,Eclipse内存分析器将监视和报告内存的分配方式以及是否已清除。

仪表板精确地分解堆的大小,以及图表格式中哪些对象的大小最大。您可以配置自己的视图,也可以使用许多预先配置的视图按对象大小、重复类或顶级使用者进行排序。这些指标可以帮助您快速解决堆中的问题,并为优化性能设置更好的策略。

Eclipse内存分析器可以免费下载,并且与Windows、Linux和macOS系统兼容。

6. GLOWROOT

Glowroot是一个开源的java apm,设置起来很快,也很容易开始使用。只需将根目录文件解压并添加到你的浏览器面板上。

如果您需要一个开销极低的工具,Glowroot在资源消耗方面处于类的首位。大量的测试表明,Glowroot在其环境中造成的影响非常小,因此响应时间必须以微秒为单位进行记录。

除了运行极其精简的Glowroot之外,Glowroot还有许多其他特性,可以用来分析和监视Java应用程序。所有数据的实时和历史汇总可以通过MBean支持图表轻松执行实时和长期测试。虽然Glowroot并不是功能最丰富的性能监视器,但它确实提供了可配置的警报功能,从而为长期使用提供了额外的灵活性。

Glowroot可以免费下载,如果你想体验一下这个工具,它还附带了一个方便的演示站点。

https://glowroot.org/overhead.html

选择JAVA性能工具

Java内存泄漏可能会令人沮丧,但是确切地知道它是什么以及如何对其进行故障排除将使处理它们变得更加容易。我们知道Java内存泄漏是由于堆内存中的对象未清理而导致的。让我们回顾一下修复和防止内存泄漏的最佳方法。

使用Java编译器 - 你的工具包是一个很好的选择,这些工具将帮助您节省数不清的调试时间,并有助于突出显示代码中本来很难找到的问题。

使用可信的Java性能监视器 - Java性能监视器不仅可以提醒您代码中的问题,还可以帮助您在应用程序中发现内存泄漏的迹象,以免它影响到您的用户。

审核你的代码 - 在实现新代码时,定期的审核和测试可以起到很大的作用。安排审核以及清理Java将帮助您的应用程序运行更快,并使故障排除变得更容易。

以上就是Java 内存溢出的原因和解决方法的详细内容,更多关于Java 内存溢出的资料请关注我们其它相关文章!

(0)

相关推荐

  • 解决Java导入excel大量数据出现内存溢出的问题

    问题:系统要求导入40万条excel数据,采用poi方式,服务器出现内存溢出情况. 解决方法:由于HSSFWorkbook workbook = new HSSFWorkbook(path)一次性将excel load到内存中导致内存不够. 故采用读取csv格式.由于csv的数据以x1,x2,x3形成,类似读取txt文档. private BufferedReader bReader; /** * 执行文件入口 */ public void execute() { try { if(!path.

  • JAVA 内存溢出案例汇总

    写在前面 作为程序员,多多少少都会遇到一些内存溢出的场景,如果你还没遇到,说明你工作的年限可能比较短,或者你根本就是个假程序员!哈哈,开个玩笑.今天,我们就以Java代码的方式来列举几个典型的内存溢出案例,希望大家在日常工作中,尽量避免写这些low水平的代码. 定义主类结构 首先,我们创建一个名称为BlowUpJVM的类,之后所有的案例实验都是基于这个类进行.如下所示. public class BlowUpJVM { } 栈深度溢出 public static void testStackOv

  • Java 堆内存溢出原因分析

    前言 任何使用过基于 Java 的企业级后端应用的软件开发者都会遇到过这种低劣.奇怪的报错,这些报错来自于用户或是测试工程师: java.lang.OutOfMemoryError:Java heap space. 为了弄清楚问题,我们必须返回到算法复杂性的计算机科学基础,尤其是"空间"复杂性.如果我们回忆,每一个应用都有一个最坏情况特征.具体来说,在存储维度方面,超过推荐的存储将会被分配到应用程序上,这是不可预测但尖锐的问题.这导致了堆内存的过度使用,因此出现了"内存不够&

  • Java虚拟机常见内存溢出错误汇总

    一.引言 从事java开发的小伙伴在平时的开发工作中,应该会遇见各式各样的异常和错误,在实际工作中积累的异常或者错误越多,趟过的坑越多,就会使我们编码更加的健壮,就会本能地避开很多严重的坑.以下介绍几个Java虚拟机常见内存溢出错误.以此警示,避免生产血案. 二.模拟Java虚拟机常见内存溢出错误 1.内存溢出之栈溢出错误 package com.jayway.oom; /** * 栈溢出错误 * 虚拟机参数:-Xms10m -Xmx10m * 抛出异常:Exception in thread

  • Java常见内存溢出异常分析与解决

    Java虚拟机规范规定JVM的内存分为了好几块,比如堆,栈,程序计数器,方法区等,而Hotspot jvm的实现中,将堆内存分为了三部分,新生代,老年代,持久带,其中持久带实现了规范中规定的方法区,而内存模型中不同的部分都会出现相应的OutOfMemoryError错误,接下来我们就分开来讨论一下.java.lang.OutOfMemoryError这个错误我相信大部分开发人员都有遇到过,产生该错误的原因大都出于以下原因: JVM内存过小.程序不严密,产生了过多的垃圾. 导致OutOfMemor

  • 详解Java内存溢出的几种情况

    JVM(Java虚拟机)是一个抽象的计算模型.就如同一台真实的机器,它有自己的指令集和执行引擎,可以在运行时操控内存区域.目的是为构建在其上运行的应用程序提供一个运行环境.JVM可以解读指令代码并与底层进行交互:包括操作系统平台和执行指令并管理资源的硬件体系结构. 1. 前言 JVM提供的内存管理机制和自动垃圾回收极大的解放了用户对于内存的管理,大部分情况下不会出现内存泄漏和内存溢出问题.但是基本不会出现并不等于不会出现,所以掌握Java内存模型原理和学会分析出现的内存溢出或内存泄漏,对于使用J

  • 完美解决java读取大文件内存溢出的问题

    1. 传统方式:在内存中读取文件内容 读取文件行的标准方式是在内存中读取,Guava 和Apache Commons IO都提供了如下所示快速读取文件行的方法: Files.readLines(new File(path), Charsets.UTF_8); FileUtils.readLines(new File(path)); 实际上是使用BufferedReader或者其子类LineNumberReader来读取的. 传统方式的问题: 是文件的所有行都被存放在内存中,当文件足够大时很快就会

  • Java虚拟机内存溢出与内存泄漏

    一.基本概念 内存溢出:简单地说内存溢出就是指程序运行过程中申请的内存大于系统能够提供的内存,导致无法申请到足够的内存,于是就发生了内存溢出. 内存泄漏:内存泄漏指程序运行过程中分配内存给临时变量,用完之后却没有被GC回收,始终占用着内存,既不能被使用也不能分配给其他程序,于是就发生了内存泄漏. 内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory: 内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间

  • Java内存溢出实现原因及解决方案

    1.JVM Heap(堆)溢出:java.lang.OutOfMemoryError: Java heap space JVM在启动的时候会自动设置JVM Heap的值, 可以利用JVM提供的-Xmn -Xms -Xmx等选项可进行设置.Heap的大小是Young Generation 和Tenured Generaion 之和.在JVM中如果98%的时间是用于GC,且可用的Heap size 不足2%的时候将抛出此异常信息. 解决方法:手动设置JVM Heap(堆)的大小. Java堆用于储存

  • Java 内存溢出的原因和解决方法

    你是否遇到过Java应用程序卡顿或突然崩溃的情况?您可能遇到过Java内存泄漏.在本文中,我们将深入研究Java内存泄漏的确切原因,并推荐一些最好的工具来防止内存泄漏发生. 什么是JAVA内存泄漏? 简单地说,Java内存泄漏是指对象不再被应用程序使用,而是在工作内存中处于活动状态. 在Java和大多数其他编程语言中,垃圾收集器的任务是删除不再被应用程序引用的对象.如果不选中,这些对象将继续消耗系统内存,并最终导致崩溃.有时java内存泄漏崩溃不会输出错误,但通常错误会以java.lang.Ou

  • Java中java.lang.ClassCastException异常原因及解决方法

    通常我们在 OOP 设计中都会使用到继承. ​​但是在继承对象之间的强制转换可能会遇到​​java.lang.ClassCastException​​异常的错误. 错误的日志如下: 19:58:25.010 [http-nio-8080-exec-5] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw

  • IntelliJ IDEA右键文件夹没有Java Class文件的原因及解决方法

    问题: 在项目里创建文件夹后,发现竟然不能新建class文件,问题详细如下图: 原因分析: 这里涉及到Sources的作用.Sources 一般用于标注类似 src 这种可编译目录.有时候我们项目当中,可能不单单是 src 目录为可编译的,很可能其他一些特别的目录也得是可编译的,因此我们便需要对该目录进行此标注.而在此项目中,只有 Sources 这种可编译目录才可以新建 Java 类和包. 解决方式: (1)选择 File  -> Project Structure  ->  Project

  • Java内存各部分OOM出现原因及解决方法(必看)

    一,jvm内存区域 1,程序计数器 一块很小的内存空间,作用是当前线程所执行的字节码的行号指示器. 2,java栈 与程序计数器一样,java栈(虚拟机栈)也是线程私有的,其生命周期与线程相同.通常存放基本数据类型,对象引用(一个指向对象起始地址的引用指针或一个代表对象的句柄),reeturnAddress类型(指向一条字节码指令的地址) 栈区域有两种异常类型:如果线程请求的栈深度大于虚拟机所允许的深度,将抛StrackOverflowError异常:如果虚拟机栈可以动态扩展(大部分虚拟机都可动

  • java OOM内存泄漏原因及解决方法

    前言 这篇文章主要介绍了java OOM内存泄漏原因及解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.什么是OOM OOM,全称"Out Of Memory",翻译成中文就是"内存用完了",当JVM因为没有足够的内存来为对象分配空间并且垃圾回收器也已经没有空间可回收时,就会抛出这个error 二.为什么会OOM.出现的原因是什么 为什么会没有内存了呢?原因不外乎有两点: ① 分配的少了:比如虚拟机本身可

  • JAVA程序内存溢出问题原因分析

    本文较为详细的分析了JAVA程序内存溢出问题原因.分享给大家供大家参考.具体如下: 遇到一个线上系统报 java.lang.OutOfMemoryError: PermGen space 错误,需要定位一下问题.很久之前到时弄过这个,现在还真有点不记得了,但这个真的是一个非常有意思的问题,值得好好研究一下.首先第一反应当然是加上-XX:+PrintGCDetails参数来看具体的GC日志,但是由于程序是tomcat启动的,担心里面封装的东西太多不好定位,既然在windows下面,所以还是借助可视

  • JAVA各种OOM代码示例与解决方法

    周末了,觉得我还有很多作业没有写,针对目前大家对OOM的类型不太熟悉,那么我们来总结一下各种OOM出现的情况以及解决方法. 我们把各种OOM的情况列出来,然后逐一进行代码编写复现和提供解决方法. 1. 堆溢出-java.lang.OutOfMemoryError: Java heap space. 2. 栈溢出-java.lang.OutOfMemorryError. 3. 栈溢出-java.lang.StackOverFlowError. 4. 元信息溢出-java.lang.OutOfMem

  • Java内存溢出和内存泄露

    虽然jvm可以通过GC自动回收无用的内存,但是代码不好的话仍然存在内存溢出的风险. 一.为什么要了解内存泄露和内存溢出? 1.内存泄露一般是代码设计存在缺陷导致的,通过了解内存泄露的场景,可以避免不必要的内存溢出和提高自己的代码编写水平: 2.通过了解内存溢出的几种常见情况,可以在出现内存溢出的时候快速的定位问题的位置,缩短解决故障的时间.  二.基本概念  理解这两个概念非常重要. 内存泄露:指程序中动态分配内存给一些临时对象,但是对象不会被GC所回收,它始终占用内存.即被分配的对象可达但已无

  • Android 5.1 WebView内存泄漏问题及快速解决方法

    问题背景 在排查项目内存泄漏过程中发现了一些由WebView引起的内存泄漏,经过测试发现该部分泄漏只会出现在android 5.1及以上的机型.虽然项目使用WebView的场景并不多,但秉承着一个泄漏都不放过的精神,我们肯定要把它给解决了. 遇到的问题 项目中使用WebView的页面主要在FAQ页面,问题也出现在多次进入退出时,发现内存占用大,GC频繁.使用LeakCanary观察发现有两个内存泄漏很频繁: 我们分析一下这两个泄漏: 从图一我们可以发现是WebView的ContentViewCo

随机推荐