如果应用程序的执行时间越来越长,或者操作系统的执行速度越来越慢,这可能是内存泄漏的迹象。换句话说,虚拟内存正在分配,但不再需要时不会返回。最终应用程序或系统内存不足,应用程序异常终止。
使用Java飞行记录器调试内存泄漏Java飞行记录器(JFR)是商业特征。您可以在开发人员的台式机或笔记本电脑上免费使用,也可以在测试、开发和生产环境中使用。
但是,应该在生产服务器上使用JFR,必须有商业许可证。在JDK用于其他目的Java任务控制(JMC)不需要商业许可证。
下面的部分显示了图片,描述了如何使用它Java调试飞行记录器内存泄漏。路由知识
检测内存泄漏使用Java尽快检测内存泄漏,防止内存不足。
可能很难检测到缓慢的内存泄漏。一个典型的症状是,由于垃圾回收频繁,应用程序在长时间运行后会变慢。最后,可能会看到OutOfmemoryErrors。然而,使用Java在问题发生之前,飞行记录可以尽快发现内存泄漏。
随着时间的推移,观察应用程序的实时集是否增加。live set旧集合(所有非活动对象都被垃圾回收)后使用Java堆量。可以通过多种方式检查活动集:使用-verbosegc运行或使用选项jmc jmx连接到控制台JVM并查看com.sun.management.GarbageCollectorAggregator MBean。然而,另一个简单的方法是记录飞行记录。
启动录制时,启用堆统计信息,在录制开始和结束时触发旧集合。这可能会导致应用程序略有延迟。但是,堆统计信息生成准确的活动集信息。如果你怀疑内存泄漏的速度很快,你可以做一个分析记录,比如一个小时。单击Memory并路由网选择选项卡Garbage Collections如图所示:
如图所示,选择第一个旧集合进行查看GC之后的堆数据和堆使用。在图中,它是34.10 MB。现在,查看列表中最后一个旧集合中的相同数据,看看活动集是否增长。应用程序必须在录制前启动并稳定。
如果泄漏缓慢,你可以在5分钟内录音。然后再录一次,比如24小时后(取决于你怀疑内存泄漏的速度)。显然,你的实时设置可能有上有下,但如果你看到稳定的增长,你可能会有内存泄漏。
找出内存泄漏的类别使用Java内存泄漏识别内存泄漏。
记录显示泄漏后,可以查看对象的统计信息。查看长记录,然后查看哪些类型的堆使用比记录增长最快。假如你每隔一段时间记录几次,那就把内容堆起来,看看这些记录中哪些对象类型增加最多,如图所示:
特别要注意不属于标准库的类别。例如,你经常看到它Char数组是顶级增长对象。因此,请注意保持这些字符串活动的对象。如果你的类有10个字符串作为成员,对象本身不会使用太多的堆。堆将由字符串使用,字符串主要包括方向Char数组指针。因此,最好根据实例的数量而不是对象的大小进行排序。若某个应用程序中有多个例子,则可能是这些对象使其他对象保持活动。
找到漏洞使用Java附加信息识别飞行记录中的内存泄漏提示。
使用Java在飞行记录中可以找到一些额外的信息。
查看Allocations选项卡,如图所示,以获取一些对象分配位置的示例。
如果排除特定类别的泄漏,请查看新的TLAB选项卡中的分配。检查正在分配的样品类型。如果泄漏速度很慢,可能会分配一些对象,可能没有样本。此外,只有特定的分配站才会导致泄漏。总之,这并不能保证堆栈跟踪的正确分配,但它可能会提供重要的线索。
了解OutOfMemoryError异常java.lang.OutOfMemoryError当没有足够的空间Java在堆中分配对象时抛出错误。
内存泄漏的常见迹象之一是java.lang.OutOfMemoryError例外情况。在这种情况下,垃圾回收器无法腾出空间容纳新物体,堆放也无法进一步扩展。此外,当机器内存不足时,无法支持Java加载类别时,可能会抛出这个错误。在极少数情况下java.lang.OutOfMemoryError垃圾收集时间过长,释放的内存很少。
当java.lang.OutOfMemoryError抛出异常时,还会打印堆栈跟踪。
这个java.lang.OutOfMemoryError机库代码在不能满足本机分配时(例如,如果交换空间很低)也会引起异常。
诊断OutOfMemoryError异常的早期步骤是确定异常的原因。它是因为Java堆满了,还是因为本机堆满了而抛出?为了帮助您找到原因,异常文本在最后包含详细信息,如下列异常所示。
线程名异常:Java.Lang.OutOfMemoryError:Java Heap Space原因:详细的消息Java heap space指示无法在Java堆中分配对象。这个错误并不一定意味着内存泄漏。问题可以简单地分配到问题,指定的堆大小(或默认大小,如果没有指定)不足以用于应用程序。
在其他情况下,特别是对于长生存期的应用程序,新闻可能意味着应用程序无意中保留了对象的参考,以防止对象被垃圾回收。这相当于内存泄漏Java语言。注:应用程序调用api对象引用也可能无意中保存。
另一个潜在的错误来源是过度使用终结器的应用程序。如果类具有finalize方法,这类对象在收集垃圾时不会回收空间。相反,垃圾回收后,这些对象将排队等待最终确定,这将在未来发生。Sun由服务终结器组成Oracle线程终结器由后台程序执行。如果终结器线程跟不上终结队列,Java堆可能会填满并导致这种类型OutOfMemoryError异常。可能导致这种情况的一种情况是,当应用程序创建高优先级线程时,这些线程会增加终结队列比终结器线程提供服务的速度。
操作:如果您想了解如何监控挂起对象的详细信息,请监控挂起对象。
线程线程名异常:Java.Lang.OutOfMemoryError: GC Overhead Limit Exceeded 超出GC限制原因:详细消息“GC overhead limit exceeded垃圾回收器一直在运行,而Java进度很慢。垃圾收集后,如果Java这个过程花了大约98%的时间收集垃圾,而且它恢复的堆积不到2%,而且在最近5次(编译时间)的连续垃圾收集中一直这样做,所以java.lang.OutOfMemoryError被抛出。这种异常通常会导致,因为活动数据的数量很难放入Java堆中,因为Java新分配的可用空间很少用于堆放。这种异常通常会导致,因为活动数据的数量很难放入Java堆中,因为Java新分配的可用空间很少用于堆放。
操作:增加堆大小。这个java.lang.OutOfMemoryError可使用命令行标志-XX:-usegcoveredlimit关闭超出GC费用限制异常。
线程线程名异常:Java.Lang.OutOfMemoryError:要求的数组大小超过VM限制原因:详细信息“要求的数组大小超过VM限制表示应用程序(或应用程序使用)API)试图分配大于堆大小的数组。例如,如果应用程序试图分配512 MB但最大堆是256 MB,则会抛出OutOfMemoryError,并给出要求的数组大小超过VM限制的原因
操作:通常的问题是配置问题(堆太小)或者导致应用程序试图创建大数组(例如,用计算错误大小的算法计算数组中的元素数时)。
线程线程名异常:Java.Lang.OutOfMemoryError:Metaspace 元空间原因:Java类元数据(Java类虚拟机内表示)分布在本机内存中(这里称为元空间)。若类元数据的元空间耗尽,则java.lang.OutOfMemoryError引发具有detail元空间异常。若类元数据的元空间耗尽,则java.lang.OutOfMemoryError引发具有detail元空间异常。参数可用于类元数据的元空间量MaxMetaSpaceSize该参数在命令行中指定。当类元数据所需的本机内存超过MaxMetaSpaceSize时,一个
java.lang.OutOfMemoryError引发具有detail元空间异常。
操作:如果在命令行上设置MaxMetaSpaceSize,请增加其值。元空间是从和Java堆放相同的地址空间。减小Java堆的大小将是MetaSpace提供更多的可用空间。只有在Java当堆中有多余的可用空间时,这是正确的权衡。有关交换空间不足的详细信息,请参考以下操作。线程线程名异常:Java.Lang.OutOfMemoryError:请求字节大小的原因。交换空间不足?原因:详细信息请求字节大小的原因。交换空间不足?”似乎是
OutOfMemoryError异常。但当本机堆分配失败,本机堆可能接近耗尽时,Java hotspotsvm代码会报告这种明显的异常。该消息指示了失败请求的大小(以字节为单位)和内存请求的原因。一般原因是报告分配失败的源模块的名称,尽管有时这是实际原因。
操作:当这个错误的消息被抛出时,VM调用致命错误处理机制(即生成致命错误日志文件,包括关于崩溃时线程、过程和系统的有用信息)。当本机堆耗尽时,日志中的堆内存和内存映射信息可能非常有用。请参阅致命错误日志。假如这种类型
OutOfMemoryError在异常情况下,可能需要使用操作系统上的故障排除实用程序来进一步诊断问题。线程线程名异常:Java.Lang.OutOfMemoryError:压缩空间原因:在64位平台上,指向类元数据的指针可以用32位偏移表示(使用UseCompressedOops)。这是命令行的标志UseCompressedClassPointers控制(默认情况下启用)。如果使用UseCompressedClassPointers,类元数据的可用空间固定为CompressedClassSpaceSize。如果UseCompressedClassPointers超过所需空间CompressedClassSpaceSize,则
java.lang.OutOfMemoryError使用detail压缩空间。
操作:增加“CompressedClassSpaceSize”以禁用“UseCompressedClassPointers”。注意:CompressedClassSpaceSize可接受的尺寸有界限。例如-XX:CompressedClassSpaceSize=4g,超出可接受界限将导致以下消息:CompressedClassSpaceSize of 4294967296 is invalid; must be between 1048576 and 3221225472.
注意
:
有不止一种类元数据,即klass元数据等元 数据