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年,坐落于俄亥俄州的克里夫兰,是一所以独立研究闻名的世界顶级私立大学,美国一级国家级大学。美国作为当今世界留学费用最高的国家之一,费用问题是所有赴美留学的学生都非常…

ffmpeg 缩放算法_图像尺寸调整算法介绍并手动实现近邻算法

课程更新完毕,后面会根据同学的意见维护此课程课程讲师:【夏曹俊】课程基于opencv**版3.2讲解,全部使用**的c接口,旧的接口会逐步被opencv抛弃,所以我们学习还是尽量学习新的接口,QT使用**的5.8版本&#x…

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

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

gradle web_简单的Gradle Web应用程序

gradle webGradle通过“ war”和“ jetty”插件轻松支持Java Web应用程序。 本教程将向您展示如何快速创建一个简单的Java Servlet Web应用程序。 我们的基本项目结构将是: basic-websrcmainjavacomcodetutrHelloWorldServlet.javawebappWEB-INFweb.xml首先&#x…

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

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

centos格式化优盘命令_u盘格式化工具fat32u盘安装centos6.5

3、声卡驱动不完全匹配,重装下声卡驱动(这种情况很少)朋友电脑开不了机,找我帮他看看,雨林木风win10家庭版,他电脑系统是有做过备份的现在做64位系统引起的■灵活设置背景2、电脑主板电池怎么换新的主板电池不贵的,才不…

maven 安装本地jar_使用Maven安装本地jar

maven 安装本地jar1.问题与选择 Maven是一种非常通用的工具,其可用的公共存储库首屈一指。 但是,总会有一个不在任何地方托管的工件,或者托管该工件的存储库有依赖的风险,因为当您需要它时,它可能不会启动。 发生这种情…

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

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

redis集群scan_Redis scan命令的一次坑

Redis作为当前服务架构不可或缺的Cache,其支持丰富多样的数据结构,Redis在使用中其实也有很多坑,本次博主遇到的坑或许说是Java程序员会遇到的多一点,下面就听博主详细道来。线上服务堵塞String key keyOf(appid);int retryCount…

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

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

hashmap 扩容是元素还是数组_HashMap 中的容量与扩容实现

总有人心里有火炬,而且彼此能看见。高手过招,招招致命JDK1.8 中 HashMap 的底层实现,我相信大家都能说上来个 一二,底层数据结构 数组 链表(或红黑树) ,源码如下/*** 数组*/transient Node[] table;/*** 链表结构*/st…

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

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

红米路由器ac2100怎样设置ipv6_Redmi路由器AC2100开箱:六天线简单直接,功能丰富对玩家友好...

原标题:Redmi路由器AC2100开箱:六天线简单直接,功能丰富对玩家友好Redmi K30系列旗舰新品发布会期间,Redmi红米发布了Redmi路由器AC2100。这一命名让人不禁想起小米路由器AC2100。但就像同期发布的Redmi小爱音箱Play与小米小爱音箱…

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

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

word2003流程图变成图片_Word中流程图怎么画 手把手教你制作!

步骤三:绘制流程图框架接下来我们开始绘制流程图的框架。所谓框架就是画出图形、把图形大致布局并在其中输入文字。在这里大家可以体会到,如果已经作好了草图,这里的操作将是比较轻松的,如果在这里边想边画,可能会耽搁…

cmakelists语法_CMakeList语法知识

在写这篇文章之前开始是想一些shell脚本与Makefile的一些基础语法知识。但是又觉得太过基础。关于Liunx shell脚本可以看看教程http://c.biancheng.net/linux_tutorial/ CMake是一种跨平台编译工具,CMake主要是编写CMakeLists.txt文件,然后通过cmake命令…

spring pom设置_Spring社交Twitter设置

spring pom设置在本系列的第一部分中 ,我们研究了如何使用StackExchange REST API来检索其主要问题。 第二部分将重点设置使用Spring Social Twitter项目与Twitter REST API交互所需的支持。 最终目标是能够在多个帐户上每天发送两个问题,每个帐户集中讨…

apache mediawiki 安装_如何在CentOS 7上安装MediaWiki

如果您想构建自己的wiki网站,可以使用MediaWiki轻松完成, MediaWiki是一个最初为WikiPedia创建的PHP开源应用程序。 由于为此应用程序开发的第三方扩展,其功能可以轻松扩展。在本文中,我们将讨论如何使用LAMP (Linux,A…

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

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

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

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