篡霎Ⅵ渊黛疆
J ava虚拟机垃圾回收算法分析与性能调优
宿敬肖杨志云张燕
(石家庄法商职业学院信息科学系河北石家庄050091)
【摘要】阐述Java垃圾回收的作用。介绍垃圾同收算法的优缺点,基于垃圾回收提出调优方法。最后给出编码建议。
【关键词]Java虚拟机垃圾回收性能调优
中图分类号:TP309.05文献标识码:^文章编号:1671—7597(2008)0910044—0l
垃圾回收(G ar bage c011e ct i on,G c)是Java程序设计中内存管理的核心概念,J ava虚拟机(JⅧ)的内存管理机制被称为垃圾回收机制,用以跟踪正在使用的对象和发现并回收不再使用的对象。该机制可以有效防范动态内存分配中可能发生的两个危险:因内存垃圾过多而引发的内存耗尽,以及不恰当的内存释放所造成的内存非法引用。
垃圾回收机制的。I=作原理是:垃圾回收器通过监控每一个对象的运行状态(包括申请、引用、被引用、赋值等),准确及时地释放对象,释放对象的根本原则是该对象不再被引用。Java采用有向图的方式进行内存管理,垃圾I口】收器从有向图的根接点(Ja va程序中整个生存周期始终存在的那些类)开始,遍历被引用的所有接点,判断哪些接点符合垃圾收集的条件(即根接点不可达),然后把符合条件的对象删除,释放内存。垃圾回收算法的选择和垃圾回收系统参数的合理调节直接影响着系统性能,因此需要开发人员做比较深入的了解。
一、垃圾回收算法分析
Ja va虚拟机可以使用多种垃圾回收算法。任何一种垃圾回收算法都具备如下两种功能:发现无用信息对象;回收被无用对象占用的内存空间,使得该宅间可被程序再次使用。
(一)垃圾回收的基本算法
引用计数法、标记清除法和节点复制法是3种基本的垃圾收集算法。
引用计数是一种简单但速度很慢的垃圾同收技术。每一个对象都含有一个引用计数器。当有引用连接到对象时。引用计数加l,当原有的引用离开作用域或置nul l时,引用计数减1,当某个对象的引用计数减为O时,就可以认为该对象为垃圾对象,可以予以回收。基于引用计数的垃圾收集算法运行速度较快,
不会长时间中断程序执行,适合必须实时运行的程序。但为了维护引用计数的不变式,每次改写一个指针,它的旧目标单元和新目标单元的引用计数都要进行调整。而该算法最主要的缺陷在于它无法回收环形的数据结构。
在标记清除法中。收集器从根部对象开始对堆窄间中的对象进行标记,所有可到达的对象被认为是存活对象,其余的则是垃圾对象,如图1所示。
图l Jav a对象逻辑分布图
算法一般分为两个步骤:垃圾检测和垃圾回收。标记清除算法的优点是可以非常自然的处理环形结构,同时操作指针没有额外的开销。但该算法是一种“停止一启动”算法。在垃圾收集器运行时,用户程序的运行必须暂停,而且这种中断可能是巨大的。关键性的安全系统,实时系统都不可能接受这么长的停顿。在节点复制算法中,收集器将整个堆等分成为两个半区,在通常程序运行时,只使用其中的一个。当运行中的程序无法获得所要求的内存时,系统就暂停当前运行的程序,启动垃圾回收程序,将当前半区中所有的活动对象拷贝到另一个半区中,拷贝完成的半区作为新
匝刃的当前半区,原来被暂停的程序在新的半区内恢复运行。这样通过两个半区的角切换,实现了垃圾对象的收集。节点复制式垃圾收集最直接的代价就是使用两个半区,因而它所需要的地址空间是非复制式的两倍。并且它同样会引起应用程序暂停。
(二)H ot s pot JV M的垃圾回收算法
在H ot spot JvM中,使用“分代”方式来管理堆空间,将整个堆空间分成了四部分:保存JvM中类和方法对象的永久代(Per m anent G en er ati on):
存放存活时间较长对象的年老代(O l d G e ne r at i on又称为Tenur e d G en er at i on);存放新建对象的年轻对象空间E den;两个存放尚未被转移到0l d G e ner a t i on中的年轻对象的存活(sur vi vor)空间(ss#l和sS#2)。其中E den和两个Sur v i vor space合称为年轻代(Y oLH l g G ener at i on)。如图2所示。
卜{I-£代—k一,I扣代—一
f岫’VM————..{.一Ja¨n蹦眭n内打卜———一卜————————一J“4堆——————————叫
图2Jav a内存堆分布图
其中年老代区存放生存期比较长的对象,年轻代区存放新建的且生存期短暂的对象.而存活宅间存放生存时间介于它们两者之『日j的对象,在SS#l中的对象比ss#2中的对象生存时问要短,存活空间中的对象可能会被移到年老代区。一个永久对象最后会被移到旧世代区,移动路径是:E den—SS#l—SS#2一01d。
=、G C性能调优
Ja va规范并没有对Gc的行为进行严格的规定,例如。对于采用什么类型的收集算法、什么时候进行收集等重要问题都没有明确的规定。因此不同的JvI I往往有不同的垃圾回收实现算法,优化配置Gc的前提是必须了解选用的JV M使用了那种垃圾回收策略。然后根据不同的应用,有针对性地调节JvM的运行参数:同时还要对应用程序编码进行优化。
(一)选用更优的JV_
Ja va垃圾同收器在不断地改进,其效率和稳定性都在不断提高。例如在J2sE l_4.2中默认使用串行收集器进行垃圾回收,但在J2s E5.O中作了调整,在服务器级的机器上,默认收集器改为并行收集器,而在客户端机器上,采取与J2SEl.4.2中同样的做法。采用更优的JVM是改进G c最直接和最省力的办法。
(二)调整堆空间
G c受系统内存运行环境影响很大,所以可根据实际应用环境进行参数的测试、调整,确定最优的参数值。主要参数及其缺省值如表l所示。
表1JV M堆参数的缺省值
参数说明缺省值
一Xm s堆的初始值2M
.X m堆的虽人值16M
.X n m Ede n对象空间的考u始值640K
.X X:N e w R ano年耔代与年老代的比例12
-X X:N ew Si扯年轻代的初始值640K
—X X:M a xN c w s i∞年轻代的最人值2.5M
—X X:S u rvi vo rRa60Ed蛐与s u“i vo r的比例8
一X X:M a x PcnnS l zc永久代的大小4M
(下转第40页)
薯耋Ⅵ渊_籀
conn.execut e(sql)
s ql=”upda t e new s s et con t ent:bbb”
conn.exec ut e(s ql)
(五)释放环境变量
使用A D0对象之后,可以通过调用方法cl ose实现关闭,然后再释放它。例如;
<%r s.cl ose
s et r s=not hi ng
co nn.cl os e
s et c o nn=no t h i ng%>
五、应用实倒
下面这段示例程序是访问s Q L sE RV E R数据库的si gn al t ab表,表中有三个字段:cod e(代码字段,
字符型。3位),cl as s(分类字段,字符型,10位),m e m o(备注字段,字符型,20位)。程序中数据源D SN:H T,用户名:cl i ent,口令:passw or d。屏幕输入页面i nput.asp
<%@l an guag e=j av ascr i pt%>
jvm调优参数<ht m l>
<f om act i on=s hot quer y.a s p M ET H O D=“p os t”
t ar g et=“一s el f”>
<i nput T Y P E=“t ex t”N A M E=s i g na l c od e V A L U E=“代码”>
<i nput T Y PE:“t ext”N A娅=si gnal code V A L U E=“代码”>
<i nput L A N G uA G E“=j a va scr i pt”T1『P E=“s ubm i t”V A LuE=。确认”N A M E=“B l”>
</f or m>
</ht m l>
数据库处理程序s hot quer y.asp
<s cr i pt l anguage。j avas cr i pt
r u矗台t=s er ver>
v a r si gI l al C ode=R equest.Fom“(si gna l C ode”):
dbC onn=Ser●er.C r eat eO bj e“ct(A D oD B.connect i on”):
曲conn.ope“n(D s N=H T:uI D:cl i ent:P帅=pas s们r d”):
r s=ser ver.C r eat eO bj ect“(A D oD B.R ecor dSet”):
V a r sql St r2“sel ect幸f r om s i gna l t ab w he r e code=li ke”+“‘%”+s igna l C ode+“%’”:
r s.open(s q l St r。db C on n,1):
i f(r s.Rec or dCount<1){
R esponse.耵i t e“(<p>无符合条件记录</p>”):
}
el se{
f o r(v a r i=1:i<=r s.P ages i ze:i++){
i f(!r s.E o f){R e spo nse.W r i t e(r s“(code”)+r s“(cl a ss”)+r s“(m e∞”)):
r s.M o veN ex t():
el s e br eak:)
r s.cl os e():
dbC onn.cl o s e():
</s cr i p t>
六、结束语
构建基于A sP与A D0的w eb数据库动态连接,利用A sP实现对w e b数据库的各种访问,真正体现了A s P的实质服务器端动态网页。A sP技术开发成本低、维护简单、功能强大、占用服务器资源少、响应快,使用A SP访『廿J数据库确实是理想的选择。随着网络应用范围的日益扩大,利用A sP对数据库的
操作技术将会得到广泛的应用。
参考文献:
[1]谭浩强,动态网页制作A s P[岫.电子工业出版社,2001.4.
[2]振林主编,A s p程序设计与应用[M].北京:机械工业出版杜,2005.
作者简介:
李艳丽,女。汉,河南商丘,商丘职业技术学院,学士,讲师,主要研究方向:计算机软件开发及应用。
(上接第44页)
调整堆空间时,首先要对堆日志进行详细分析,若应用程序的暂停时间比较长,则需要减少堆空间:若发现大量的垃圾没有及时【壁l收,则可能是总体的堆空间或年老代的空间不足;若想得到更快的启动时间,需要调整年轻代的初始值,可以通过参数一)【】(:N e瞒i ze或参数一xm来设置:如果应用程序经常出现out of m e m or y错误而无法运行,可以增加年老代的大小,或者通过参数一xx:N ewR at i o来调整年轻代与年老代大小的比例。实际上,除非遇到了过长的应用程序暂停.否则都建议增大堆空间,
这样几乎总是能够提高G c的总体性能,可通过设置参数一)(I ns和一X眦把应用程序的初始堆大小和最大堆大小设置为同样的值,这样不需要J v^I在运行时去决定什么时候重新设置堆空间的大小,可以让应用程序运行起来更优预测性更加稳定,当然它的代价足增加启动时占用的内存。
(三)编码建议
虽然G c使得程序员不必担心内存漏洞的问题,但并不是说程序员不用再考虑内存管理的问题了。根据上述G c的机制,程序的运行会直接影响系统环境的变化,从而影响G c的触发.若不针对G c的特点进行设计和编码,就会出现内存驻留等一系列负面影响。为了避免这些影响,基本的原则就是尽可能地减少垃圾和减少G c过程中的开销。具体措施如下:
不要显式调用syst em.gc()。此方法建议Jvl I进行主Gc,虽然只是建议而非一定,但很多情况下它会触发主G c,从而增加主G c的频率,也即增加了间歇性停顿的次数;尽量减少临时对象的使用。临时对象在跳出函数调用后,会成为垃圾,少用临时变量就相当于减少了垃圾的产生,从而延长了触发条件出现的时间,减少了乇G c的机会;对象不用时最好显式置为nul l。一般而言,为nul l的对象都会被作为垃圾处理,所以将不用的对象显式地置为nul l,有利于G c收集器判定垃圾。从而提高了G c的效率;尽量使用st r i ngB u f f er。而不用St r i ng来累加字符串。减少中间对象的产生;
Ⅲ习能用基本类_辈!如I n t、L o ng,就不用I nt ege r、L o ng对象。基本类型变量占用的内存资源比相
应对象占用的少得多,如果没有必要,最好使用摹本变量:尽量少用静态对象变量。静态变量属于全局变量,不会被G c回收,它们会一直占用内存;尽量少用f i nal i ze方法。Gc在回收每个垃圾对象时,都会调用该对象的f i nal i ze方法,在f i na l i z e方法中的任何操作都会增加
G C的开销。
三、结束语
Ja va的垃圾回收机制对应用程序的性能有着非常重要的影响,为避免性能瓶颈的出现,Jav a开发人员有必要了解JⅧ的垃圾回收机制及其调节方法。这样才有可能最小化垃圾回收对系统性能的负面影响。本文阐述了Ja va垃圾回收的作用,对垃圾回收机制进行了分析,最后就如何避免G c的负面影响提出了调优的办法,希望能给Ja va开发人员提供一些参考。
参考文献:
[1]B nl ce Ec k e l。T hi nking i n J ava(3r d Edi t ion)[M].北京:机械工业出版社,2005.
[2]R i ch”d Jone s,Jl af∞l Lins.垃圾收集[M].北京:人民邮电出版社,2004.
[3]Sun M i cr os yst em s.J avaT M hot s pot V M opti ons[EB/0L].2002.ht t p://j a va.sun.c om/doc s/hot spot/vM0pt i ons.ht m l.
[4]林胜利、王坤茹,孟海利.Java优化编程[M].北京:电子工业出版杜,2005.
作者简介:
宿敬肖,女,河北晋州人。教师。硕士研究生,研究向为系统优化:杨志云,女,枫北石家庄人,讲师,本科;张燕,女t舅北人,助教本科