Java系统内存泄漏分析

Java系统内存泄漏分析报告



 1    概述    2
1.1    背景    2
2    Java内存泄漏    2
2.1    Java是如何管理内存    2
2.2    什么是Java的内存泄漏    2
2.3    如何跟踪Java内存泄漏    3
3    调查内容    4
3.1    环境配置    4
3.1.1    安装JRockit JDK 1.4    4
3.1.2    修改Eclipse默认JRE为JRockit    5
3.1.3    修改部分源码使其适应JDK1.4标准    5
3.1.4    修改JVM才参数,开放JMX调试服务    6
3.1.5    配置BEA JRockit(R) Mission Control连接    6
3.1.6    跟踪资源使用情况    7
3.2    PC端功能    7
3.2.1    ThreadLocal缓存对象生命周期跟踪    7
3.2.1.1    修改方式    9
3.2.2    Session对象回收周期过长    9
3.2.2.1    修改方式    9
4    参考资料    10

 

1    概述

1.1    背景

X项目中系统使用过程中,运行时间过长出现内存资源持续占用不能被及时回收的情况,并且其资源占用量随运行时间与并发性成正相关,初步判断为Java内存泄漏导致,所以进行内存泄漏方面的调查分析。

2    Java内存泄漏

2.1    Java是如何管理内存

Java通过GC功能不定时地回收内存资源,GC判断一个对象是否可以回收的标准是该对象是否可达,即是否被引用,JVM在以有向图的方式管理所有堆上资源,这使环形循环引用的不可达对象依旧可以被有效的回收,下图简单的描述了一个可回收单元的产生。
 

2.2    什么是Java的内存泄漏

熟悉C/C++语言的开发人员都知道,C/C++语言的内存泄漏指的是不可回收资源,是纯粹的内存黑洞,除非进程终止后操作系统回收进程所有堆上资源时才会被释放,这是纯粹的内存泄漏;而Java语言的内存泄漏与C/C++语言所指的内存泄漏非同一概念,Java语言所指的内存泄漏是指全局/静态集合持续被持有而导致的无用单元不可回收,是一种逻辑上的“内存泄漏”。


2.3    如何跟踪Java内存泄漏

很多应用服务器厂商都提供了功能强大的GC跟踪工具,用于分析堆上内存分配与收集情况,从而确定内存泄漏位置。本次调查采用的是BEA公司发布的“BEA JRockit(R) Mission Control 2.0”。开发人员试用版本许可可以使用1个小时。
使用BEA JRockit(R) Mission Control 2.0所包含的如下三个工具辅助内存泄漏分析:
BEA JRockit Management Console
 

 
BEA JRockit Runtime Analyzer (JRA)
 

 
BEA Memory Leak Detector
 

 
具体使用方法,参考BEA官方网站说明。

3    调查内容

3.1    环境配置

3.1.1    安装JRockit JDK 1.4

BEA官方网站下载开发人员试用版本的JRocket JDK工具包jrockit-R27.2.0-jdk1.4.2_13,安装后导入试用版本许可文件,使用版本可以免费使用1个小时,重新启动可以继续使用。
导入试用许可证:
<C:\Program Files\Java\jrockit-R27.2.0-jdk1.4.2_13\jre>

<?xml version="1.0" encoding="ISO-8859-1"?>

<bea-licenses>
    <license-group format="1.0" product="JRockit" release="*">
        <license
            component="JRA"
            cpus="unvalued"
            expiration="never"
            hours="1"
            ip="any"
            licensee="BEA Evaluation Customer"
            serial="454493271161-2222564495787"
            type="SDK"
            signature="MC0CFFCnVsUSP96Xd5YtNPTQKXcGoiBgAhUA4yH2/UmqYpJLNzPOPmJUdqPUrNs="
        />
        <license
            component="Memory Leak Detector"
            cpus="unvalued"
            expiration="never"
            hours="1"
            ip="any"
            licensee="BEA Evaluation Customer"
            serial="454493271161-2222564495787"
            type="SDK"
            signature="MCwCFFVySk0b0fwMReywZt4UyBZX7PjEAhQibfVzVVDZgkXgnMxZUfFzAS5gew=="
        />
    </license-group>
</bea-licenses>

 
3.1.2    修改Eclipse默认JRE为JRockit


3.1.3    修改部分源码使其适应JDK1.4标准
  • 关于JDBC的接口定义在1.4标准中增加了若干接口,实现即可。
  • PublicKey验证时从磁盘系统读入序列化后的1.3类时出错,调试时使其跳过,始终返回true。
3.1.4    修改JVM才参数,开放JMX调试服务

 

3.1.5    配置BEA JRockit(R) Mission Control连接

 

3.1.6    跟踪资源使用情况


3.2    模块分析

3.2.1    ThreadLocal缓存对象生命周期跟踪

LoginUser用于提高系统性能的缓存对象,缓存内容包括,用户信息,商品信息,分页信息等。按照设计者的初衷,其生命周期的可控制范围为Session, 当用户注销或Session超时后会被移出,内存资源会被回收。
但是,在LoginUser中引入了ThreadLocal的静态成员,用于缓存当前登录用户的LoginUser对象,其生命周期与当前线程绑定,请求完成后并没有从ThreadLocal中销毁,而滞留于静态存贮区域,当用户注销后,该对象仍然无法被销毁,从而使LoginUser对象生命周期失控,直至该线程再次被分配时才会被新的对象覆盖,使其区域不可达。当同一个用户的请求被多次提交时该对象的引用将会逐渐的产生更多的引用,从而更难于销毁。多用户登录注销后,会导致更多的无效内存无法回收。
跟踪过程:

  • 用户登录,创建LoginUser对象


 

对象引用关系(请放大观看)



 
LoginUser对象被两个集合引用,分别为Session和ThreadLocal。经过若干页面操作后,ThreadLocal集合中的引用会逐渐增多,从而使对象生命周期更加难于控制。

  • 用户注销,企图销毁LoginUser


如上图所示,LoginUser被从Session中清除,但是ThreadLocal中的引用一直存在,并且其引用数目不可控制,可能会很多,引用数目越多其生命命周期可能会更长。从而导致内存泄漏。

3.2.1.1    修改方式

将LoginUser对象与Resource对象的ThreadLocal引用周期控制在Servlet请求周期之内,但此请求完成后,释放其对对象的引用,使其始终保持Session的单一引用,即可严格控制集合对象的生命周期。
Servlet

public void doGet(HttpServletRequest req, HttpServletResponse resp)
 throws ServletException, IOException {
	try
{

License license = new License();
HtmlPage page = null;

.........
.........
.........
}
//      add for clear memory leak /begin
finally
{
LoginUser.setCurrentLoginUser(null);
ResourceManager.setBundle(null);
}
//      add for clear memory leak /end
}
 
3.2.2    Session对象回收周期过长

相同的用户多次登录系统而不注销的情况下,先登录的用户的Session以及LoginUser对象会多次被创建,而不能及时的被清除,这给峰值操作时的资源占用带来了隐患,由于用户基本上没有注销的习惯(通常情况下,用户都是直接关闭浏览器的),Session的超时时间通常是30分钟,那么这部分对象将在30分钟后才能被回收。
由于LoginUser中的对象可能会很大,由此所带来的内存消耗是非常大的,又因为同一个用户多次登录,LoginUser没有必要重复创建。

3.2.2.1    修改方式

1.    将系统主窗口中增加关闭事件,关闭时产生注销操作。
a)    优点:
i.    可以缩短Session中的LoginUser无用生命周期,使资源第一时间被回收。
ii.    用户使用更加安全,不会因为忘记注销而产生安全漏洞。
b)    缺点:
i.    如果用户习惯了关闭主窗口然后使用子窗口进行操作,将会导致Session无效,比如:登陆后用户进入报告登录,然后关闭驻窗口进行报告登录等。
ii.    浏览器关闭时间不可靠,可能不会被调用。
2.    重复用户登录处理Session的销毁
a)    原则上讲,Serviet不允许当前Session销毁其他的Session,但是有一个解决办法,可以使用接口HttpSessionListener编写自己的侦听器,接口方法如下: 

void   sessionCreated(HttpSessionEvent   se)
void   sessionDestroyed(HttpSessionEvent   se)

  通过HttpSessionEvent可以获取每个创建的session信息   
web.xml中定义   
  	<listener>   
<listener-class>loginuser.ContextListener</listener-class>  </listener>   
 

4    参考资料

  • Java的内存泄漏

http://www-128.ibm.com/developerworks/cn/java/l-JavaMemoryLeak/

  • JRockit Memory Leak Detector released

http://dev2dev.bea.com/blog/sla/archive/2005/06/jrockit_memory.html

  • BEA JRockit 1.4.2

http://commerce.bea.com/products/weblogicjrockit/1.4.2/142_x.jsp?

  • Developer license download(This license is free and allows the tools to be used for 1 hour, after which JRockit must be restarted before running the tools again)

http://commerce.bea.com/downloadproduct.jsp?family=JRMC&major=2.0&minor=0&delivery=1&os=All&intent=purchase

  • ThreadLocal

http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ThreadLocal.html

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 内容概要 《计算机试卷1》是一份综合性的计算机基础和应用测试卷,涵盖了计算机硬件、软件、操作系统、网络、多媒体技术等多个领域的知识点。试卷包括单选题和操作应用两大类,单选题部分测试学生对计算机基础知识的掌握,操作应用部分则评估学生对计算机应用软件的实际操作能力。 ### 适用人群 本试卷适用于: - 计算机专业或信息技术相关专业的学生,用于课程学习或考试复习。 - 准备计算机等级考试或职业资格认证的人士,作为实战演练材料。 - 对计算机操作有兴趣的自学者,用于提升个人计算机应用技能。 - 计算机基础教育工作者,作为教学资源或出题参考。 ### 使用场景及目标 1. **学习评估**:作为学校或教育机构对学生计算机基础知识和应用技能的评估工具。 2. **自学测试**:供个人自学者检验自己对计算机知识的掌握程度和操作熟练度。 3. **职业发展**:帮助职场人士通过实际操作练习,提升计算机应用能力,增强工作竞争力。 4. **教学资源**:教师可以用于课堂教学,作为教学内容的补充或学生的课后练习。 5. **竞赛准备**:适合准备计算机相关竞赛的学生,作为强化训练和技能检测的材料。 试卷的目标是通过系统性的题目设计,帮助学生全面复习和巩固计算机基础知识,同时通过实际操作题目,提高学生解决实际问题的能力。通过本试卷的学习与练习,学生将能够更加深入地理解计算机的工作原理,掌握常用软件的使用方法,为未来的学术或职业生涯打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值