openjpa_OpenJPA:内存泄漏案例研究

openjpa

本文将提供完整的根本原因分析详细信息以及解决影响Oracle Weblogic Server 10.0生产环境的Java堆内存泄漏(Apache OpenJPA泄漏)的方法。 这篇文章还将演示在管理javax.persistence.EntityManagerFactory生命周期时遵循Java Persistence API最佳实践的重要性。

环境规格

  • Java EE服务器 :Oracle Weblogic Portal 10.0
  • 操作系统 :Solaris 10
  • JDK :Oracle / Sun HotSpot JVM 1.5 32位@ 2 GB容量
  • Java Persistence API :Apache OpenJPA 1.0.x(JPA 1.0规范)
  • RDBMS :Oracle 10g
  • 平台类型 :Web门户

故障排除工具

  • Quest Foglight for Java( Java堆监视)
  • MAT(Java 堆转储分析 )

问题描述与观察

该问题最初是由Weblogic生产支持团队在生产中断后报告的。 最初的根本原因分析练习确实揭示了以下事实和观察结果:

  • 约2周的流量后,定期观察到生产中断。
  • 失败是由于Java堆(OldGen)耗尽所致,例如OutOfMemoryError:在Weblogic日志中发现Java堆空间错误。
  • 在一段时间后从Foglight监视工具检查了Java堆OldGen的空间利用率以及Java冗长的GC历史数据后,确认了Java堆内存泄漏。

发现上述问题后,决定移至RCA的下一个阶段,并对受影响的Weblogic(JVM)实例执行JVM 堆转储分析 。

JVM堆转储分析

**现在可以在此处获得解释以下JVM堆转储分析的视频。 为了产生一个
JVM堆转储受支持的团队确实使用了HotSpot 1.5 jmap实用程序,该实用程序生成了大约1.5 GB的堆转储文件(heap.bin)。 然后使用Eclipse Memory Analyzer Tool分析了堆转储文件。 现在,让我们回顾一下堆转储分析,以便我们了解OldGen内存泄漏的根源。

MAT提供了一个初步的泄漏可疑报告,这对于突出您的高内存贡献者非常有用。 对于我们的问题案例,MAT能够识别出可疑泄漏占近600 MB或占OldGen空间总容量的40%。

此时,我们找到了一个java.util.LinkedList实例,该实例使用了将近600 MB的内存,并已加载到我们的应用程序父类加载器之一(@ 0x7e12b708)。 下一步是了解泄漏的对象以及保留的来源。 MAT允许您检查应用程序的任何类加载器实例,并提供检查加载的类和实例的功能。 只需提供地址(例如0x7e12b708)来搜索所需的对象,然后通过选择带有外向引用的“列表对象”>检查加载的类和实例。

从上面的快照中您可以看到,该分析非常有启发性。 我们发现内存保留源中有一个org.apache.openjpa.enhance.PCRegistry实例; 罪魁祸首是实现为LinkedList的_listeners字段。 供您参考,内部使用Apache OpenJPA PCRegistry来跟踪已注册的具有持久性的类。 在Apache OpenJPA 1.0.4版中公开_listeners字段的PCRegistry源代码的片段下面。

/*** Tracks registered persistence-capable classes.** @since 0.4.0* @author Abe White*/
public class PCRegistry {// DO NOT ADD ADDITIONAL DEPENDENCIES TO THIS CLASSprivate static final Localizer _loc = Localizer.forPackage(PCRegistry.class);// map of pc classes to meta structs; weak so the VM can GC classesprivate static final Map _metas = new ConcurrentReferenceHashMap(ReferenceMap.WEAK, ReferenceMap.HARD);// register class listenersprivate static final Collection _listeners = new LinkedList();

现在的问题是,为什么这种内部数据结构的内存占用空间如此之大,并且随着时间的推移可能会泄漏? 下一步是深入研究_listeners LinkedLink实例,以检查泄漏的对象。

我们最终发现,泄漏的对象实际上是我们的应用程序用来对Oracle数据库执行各种查询的JDBC和SQL映射定义(元数据)。 对JPA规范,OpenJPA文档和源代码的回顾确实确认了根本原因与javax.persistence.EntityManagerFactory的错误用法有关,例如缺少关闭新创建的EntityManagerFactory实例。

如果仔细查看上面的代码快照,您将意识到close()方法确实负责清理最近使用的元数据存储库实例。 这也确实引起了另一个问题,为什么我们要一遍又一遍地创建这样的Factory实例……调查的下一步是对我们的应用程序代码执行代码遍历,尤其是围绕JPA EntityManagerFactory和EntityManager对象的生命周期管理。

根本原因和解决方案

应用程序代码的代码演练确实表明,该应用程序在每个单个请求上都创建了EntityManagerFactory的新实例,并且没有正确关闭它。

public class Application {@Resourceprivate UserTransaction utx = null;// Initialized on each application request and not closed!@PersistenceUnit(unitName = "UnitName")private EntityManagerFactory emf = Persistence.createEntityManagerFactory("PersistenceUnit"); public EntityManager getEntityManager() {return this.emf.createEntityManager();}public void businessMethod() {// Create a new EntityManager instance via from the newly created EntityManagerFactory instance// Do something...// Close the EntityManager instance}
}

JPA EntityManagerFactory的此代码缺陷和改进程序的使用导致在早期JVM堆转储分析中演示的OpenJPA _listeners数据结构内泄漏或积累了元数据存储库实例。 该问题的解决方案是通过Singleton模式集中管理线程安全javax.persistence.EntityManagerFactory的管理和生命周期。 最终解决方案的实现如下:

  • 每个应用程序类加载器仅创建和维护一个javax.persistence.EntityManagerFactory静态实例,并通过Singleton Pattern实现。
  • 为每个应用程序请求创建并处置EntityManager的新实例。

请阅读Stackoverflow上的 讨论 ,因为我们实现的解决方案非常相似。 在针对我们的生产环境实施解决方案之后,不再观察到Java堆OldGen内存泄漏。

参考: OpenJPA:我们的JCG合作伙伴 Pierre-Hugues Charbonneau在Java EE支持模式和Java教程博客上的内存泄漏案例研究 。

翻译自: https://www.javacodegeeks.com/2013/03/openjpa-memory-leak-case-study.html

openjpa

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/349103.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

美国凯斯西储大学计算机硕士专业怎么样,在凯斯西储大学读硕士大约需要多少花费?...

凯斯西储大学是美国著名大学之一,始建于1826年,坐落于俄亥俄州的克里夫兰,是一所以独立研究闻名的世界顶级私立大学,美国一级国家级大学。美国作为当今世界留学费用最高的国家之一,费用问题是所有赴美留学的学生都非常…

win7如何修改dns服务器地址,Win7系统DNS怎么设置?Win7系统DNS设置方法

Win7系统DNS怎么设置?众所周知,DNS地址是一个域名服务器地址,它可以把用户的网站地址解析成IP地址。如果这个服务器出现问题,可能就上不了网了。我们在使用Win7系统的时候,就是因为域名解析服务器不能将要访问的域名解析为正确的…

密钥文件登录服务器,密钥文件登录云服务器

密钥文件登录云服务器 内容精选换一换远程桌面协议(Remote Desktop Protocol,RDP),是微软提供的多通道的远程登录协议。本节为您介绍如何使用RDP文件远程登录Windows弹性云服务器。从管理控制台下载的RDP文件对应唯一的云服务器,当前RDP文件命…

一个网站服务器有多少个ip,一个服务器可以有多少个ip地址

一个服务器可以有多少个ip地址 内容精选换一换华为云帮助中心,为用户提供产品简介、价格说明、购买指南、用户指南、API参考、最佳实践、常见问题、视频帮助等技术文档,帮助您快速上手使用华为云服务。会话保持,指负载均衡器可以识别客户与服…

jbpm小项目测试_尝试使用jBPM Console NG(测试版)

jbpm小项目测试大家好! 这是有关jBPM Console NG的另一篇文章。 经过6个月的辛苦工作,我很高兴为开发人员社区撰写这篇文章,以进行尝试。 在这篇文章中,我将解释如何从源代码构建应用程序。 这背后的主要思想是知道如何在测试过程…

用友数据库服务器如何修改,用友u8数据库服务器怎么设置

用友u8数据库服务器怎么设置 内容精选换一换本章介绍如何在管理控制台购买GaussDB(for openGauss)实例,并通过内网使用弹性云服务器连接GaussDB(for openGauss)实例。GaussDB(for openGauss)提供gsql工具帮助您在命令行下连接数据库,您需要提前创建一台弹…

hibernate批量查询_使用Hibernate批量获取

hibernate批量查询如果需要从Java处理大型数据库结果集,则可以选择JDBC,以提供所需的低级控制。 另一方面,如果您已在应用程序中使用ORM,则回退到JDBC可能会带来一些额外的麻烦。 在导航域模型时,您将失去诸如乐观锁定…

Java 9迁移指南:七个最常见的挑战

我确定您已经听说过更新到Java 9并不是一件容易的事,甚至可能是不兼容的更新,而且对于大型代码库而言,迁移毫无意义。 这样做之后,我迁移了一个相当大的旧代码库,我可以告诉你,这还不错。 比碰到Java 8确实…

nuxt sass 全局变量的问题_Sass入门教程

SASS(Syntactically Awesome Stylesheet)是一个CSS预处理器,有助于减少CSS的重复,节省时间。 它是更稳定和强大的CSS扩展语言描述文档的风格结构。sass中文网而且Sass算是CSS的超集,它100%兼容CSS的语法,所有在 CSS 中正常工作的代…

用C语言实现优先级排序和MATLABsort函数的比较

为了实现对两个数组进行优先级排序,用c语言有两种实现方法, 一是需要对两个数组进行排序,然后对排序后的坐标再排序,(求最小值是我自己需要) 二是直接寻找数组排序后的元素坐标,调用qsort函数进行排序,排序后的数组会存放在原数组中,那么就有两种寻找坐标,一是寻找…

造成内存泄漏_如何造成内存泄漏

造成内存泄漏这将是一个相当邪恶的职位-当您确实希望使某人的生活陷入困境时,您将在谷歌上搜索。 在Java开发领域,内存泄漏只是您在这种情况下会引入的错误类型。 为您的受害者保证几天甚至几周的办公室不眠之夜。 我们将在这篇文章中描述两次泄漏。 两…

通过Java,Spring Boot应用程序将Gmail用作SMTP服务器

Gmail用户可以使用Gmail的SMTP服务器smtp.gmail.com从其Spring Boot应用程序发送电子邮件。 为此,让我们在应用程序中进行一些设置: 在application.properties文件中提供SMTP连接属性: spring.mail.hostsmtp.gmail.com spring.mail.username…

在建工地扬尘在线监控系统推荐_配电室为何需要安装蓄电池在线监控系统?保定钰鑫电气...

配电室蓄电池在线监控系统提高了蓄电池运行质量、增强了电力系统的安全运行、保障蓄电池运行环境的可靠,打造无人值守配电室、智能化运维模式,减少蓄电池损耗、浪费,降低了维护成本,为何需要安装一套配电室蓄电池在线监测系统&…

最好的Java开发人员测试和集成工具

通过从应用程序中学习企业APM产品,发现更快,更高效的性能监控。 参加AppDynamics APM导览! 无论您是刚开始还是已经使用了一段时间,使用正确的工具进行编程都可以对项目的成功产生巨大的影响。 适当的工具使您可以编写更好的代码…

最速下降法matlab全局最小值_梯度下降概念

1、梯度概念(1)从几何意义上讲,就是函数变化最快的地方。在单变量的函数中,梯度只是导数,其实就是函数在某个给定点的切线的斜率;在多变量函数中,梯度是一个向量,向量有方向,梯度的方向就指出了…

IntelliJ中的远程调试Wildfly应用程序

远程调试Java应用程序意味着使用本地开发环境连接到远程运行的应用程序。 Java开箱即-agentlib:jdwp[options]支持远程调试:目标应用程序必须使用-agentlib:jdwp[options]选项执行, -agentlib:jdwp[options]选项加​​载Java调试线协议(jdwp&…

+h eclipse中ctrl_Eclipse 常用的快捷键都有哪些?

今天,小编大概整理了 几 组 Eclipse 的快捷键,希望对你有帮助。1、打开资源CTRL SHIFT R:打开所有类型文件,不包括 JAR 包; CTRL SHIFT T:打开 Java 类型文件,包括 JAR 包;2、查…

apache.camel_Apache Camel 2.11发布

apache.camel上周Apache Camel 2.11发布了。 这篇博客文章总结了最引人注目的新功能和改进。 有关详细说明,请参见Camel 2.11发行说明 。 1)新组件 与往常一样,每个新版本都包含许多新组件,这些组件是由我们庞大的用户群贡献的。…

c向文件中插入数据_Redis从文件中批量插入数据

简介在redis中,有时候需要批量执行某些命令,但是在redis的redis-cli下,只能一条条的执行指令,实在太麻烦了!想到这,你是不是蓝瘦香菇? 如果能将要执行的指令一行行存储到文件中,然后…

python多级目录import_你真的会用Python模块与工具包吗?

在开发过程中,我们无法把所有代码、资源都放在同一个文件中。因此,模块导入在编码中是很常见的。无论是C、Java,还是Python、Go。可以把不同功能、不同模块进行分离,当使用的时候,可以通过import关键字在一个模块中使用…