如何处理频繁创建对象然后丢弃导致频繁GC的情况

如何处理频繁创建对象然后丢弃导致频繁GC的情况

应用场景:

程序主动去请求第三方系统,该系统返回xml文件。

程序通过dom4j来解析xml文件,并定义了一些bean来存储xml中的信息。

以方便供程序使用。

但在系统的运行过程中,访问次数相当频繁,上万次,这样导致,创建了大量的bean用于储存xml中的信息。

然后bean用完丢弃,导致GC比较频繁。

像这种情况下,有什么好的建议吗。对这些bean的处理

2011年10月30日 11:17 "@banq"的内容
比如建立一个Pool池,设定池中有空Bean 1000个,需要转换XML拿出来,转换完成放回Pool中 ...


您提的建立一个pool池,以前我没想到,因为我觉得这些bean每次请求的数据都不一样,即

可以说都是有状态的。所以一直没有想用池或缓存来处理他们。

建立pool池,里没有1000个空bean,用完后在把bean中的数据清空,在放回pool池中。

这样理解对吗?

谢谢 banq

2011年11月03日 08:57 "@iluguo"的内容
您提的建立一个pool池,以前我没想到,因为我觉得这些bean每次请求的数据都不一样,即

可以说都是有状态的。所以一直没有想用池或缓存来处理他们。

建立pool池,里没有1000个空bean,用完后在把bean中的数据清空,在放 ...

我觉得设置为null,就可以让GC自动回收了

2011年11月04日 11:51 "@docsun"的内容
我觉得设置为null,就可以让GC自动回收了...

GC是回收这些内存了,但是GC太频繁。

2011-10-28T13:50:45.062+0800: 158.233: [GC 158.233: [DefNew: 237897K->5619K(245760K), 0.0870050 secs] 267424K->48443K(791936K), 0.0871725 secs] [Times: user=0.09 sys=0.00, real=0.09 secs]
2011-10-28T13:50:54.125+0800: 167.304: [GC 167.304: [DefNew: 224115K->7915K(245760K), 0.0334763 secs] 266939K->50739K(791936K), 0.0336511 secs] [Times: user=0.05 sys=0.00, real=0.05 secs]
2011-10-28T13:50:59.203+0800: 172.378: [GC 172.378: [DefNew: 226411K->7954K(245760K), 0.0239013 secs] 269235K->50778K(791936K), 0.0240657 secs] [Times: user=0.03 sys=0.00, real=0.03 secs]
2011-10-28T13:51:23.812+0800: 196.983: [GC 196.983: [DefNew: 226450K->6298K(245760K), 0.0222406 secs] 269274K->49122K(791936K), 0.0224050 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]
2011-10-28T13:51:53.296+0800: 226.471: [GC 226.471: [DefNew: 224794K->6791K(245760K), 0.0225674 secs] 267618K->49615K(791936K), 0.0227340 secs] [Times: user=0.03 sys=0.00, real=0.03 secs]
2011-10-28T13:52:25.171+0800: 258.338: [GC 258.338: [DefNew: 225287K->6223K(245760K), 0.0218760 secs] 268111K->49047K(791936K), 0.0220617 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]
2011-10-28T13:52:56.765+0800: 289.945: [GC 289.945: [DefNew: 224719K->6322K(245760K), 0.0211256 secs] 267543K->49146K(791936K), 0.0212925 secs] [Times: user=0.03 sys=0.00, real=0.03 secs]
2011-10-28T13:53:12.062+0800: 305.239: [GC 305.239: [DefNew: 224818K->6580K(245760K), 0.0214838 secs] 267642K->49404K(791936K), 0.0216502 secs] [Times: user=0.03 sys=0.00, real=0.03 secs]
2011-10-28T13:53:37.593+0800: 330.771: [GC 330.771: [DefNew: 225076K->6486K(245760K), 0.0213408 secs] 267900K->49310K(791936K), 0.0215129 secs] [Times: user=0.03 sys=0.00, real=0.03 secs]
。。。

[该贴被billows于2011-11-04 23:08修改过]

2011年11月04日 23:06 "@billows"的内容
建立pool池,里没有1000个空bean,用完后在把bean中的数据清空,在放回pool池中。

这样理解对吗? ...

在Twitter的那个PPT中,首先提到的方案也是Cache和Pool,至于使用具体哪一个,根据你的功能,如果Bean是保存数据,那么使用Cache,如果Bean是带处理功能的很大的类,使用Pool。

不过,根据你说要把Bean中数据清空,好像Bean是含有数据或状态的,那么就要使用Cache了。

总体来说:为了避免大量对象创建销毁,耗费了JVM的新生代内存,频繁触发垃圾回收机制,导致系统暂停,那么就要控制这种对象大量创建,变成循环反复利用,Pool或Cache是一种好的方式,因为他们都有最大值限制;当然还有JVM的内存调优。

如何驯服java GC导致暂停? 使用16GiB以上heap

[该贴被banq于2011-11-05 08:32修改过]

2011年11月05日 07:45 "@banq"的内容
好像Bean是含有数据或状态的,那么就要使用Cache了 ...

cache一般是缓存那些不经常变化的数据,但我这些bean里面含有数据,

类似一些集合,且每次访问接口数据都不一样,如何缓存?如何控制

不同的请求避免因为缓存而导致数据出错,一直没有眉目,还望指教:)

bean类似于

public class RSWrapper{
private List<HotelBO> hotelinfoList;

public List<HotelBO> getHotelInfoList(){
return hotelinfoList();
}

public void disassembleXML(){

...

}
}

个人观点: 用pool

cache的“缓”是 “用”--“暂停”--“再用”

pool 是 “用” ,用完了就直接回pool里,省new了(bean类大/n多bean对象 都是很消耗资源的)。

从xml到bean再到后续business logic, 一直与这个bean相关,当business 完事后就把bean回pool,别忘了“init bean”就行。

pool的size 要去env中调了。

2011年11月04日 23:06 "@billows"的内容
GC是回收这些内存了,但是GC太频繁。 ...

可以找一下微调JVM的帖子,尝试一下

2011年11月06日 20:46 "@docsun"的内容
微调JVM的帖子,尝试一下 ...

正在找一些JVM微调的帖子学习。:)


S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT
27264.0 27264.0 0.0 111.9 218496.0 90825.8 546176.0 39700.2 131072.0 7 6441.5 1151 8.462 9 5.079 13.541
[该贴被billows于2011-11-06 23:02修改过]

2011年11月06日 20:46 "@docsun"的内容
可以找一下微调JVM的帖子,尝试一下 ...

如果数据量很大,微调效果是否显著, 没有做过, 不是太清楚。
我觉得donglangjohn的说法不错, 用Pool

YGC : 1151

在将近 3个小时内 monitor gc 1151次,是否频繁?

虽然 YGCT 只有 8.462 S

在程序运行期间,用jconsole查看内存使用情况时,看见 survivor space 频繁跳动。

微调会尝试做一下,即使是学习。

pool或cache在代码重构的时候可以具体分析一下。


[该贴被billows于2011-11-08 20:39修改过]

2011年11月08日 17:20 "@PCzhang"的内容
如果数据量很大,微调效果是否显著, 没有做过, 不是太清楚。
我觉得donglangjohn的说法不错, 用Pool ...

看帖子说的好像是因为GC回收的过于频繁造成的,这样只能去微调JVM,让GC的回收机制发生变化才能减少这样的回收发生吧

2011年11月09日 14:10 "@docsun"的内容
看帖子说的好像是因为GC回收的过于频繁造成的,这样只能去微调JVM,让GC的回收机制发生变化才能减少这样的回收发生吧 ...

回收过于频繁是因为始终创建新对象。

2011年11月08日 20:32 "@billows"的内容
YGC : 1151

在将近 3个小时内 monitor gc 1151次,是否频繁?

虽然 YGCT 只有 8.462 S ...


8.46/3*3600=0.0007....,大概占用时间是7%,其实你这个还好了。不算gc频繁的那种,关键要看full gc有多少,gc耗费的时间占整个系统运行时间的百分比。而且我看到你们现在貌似整个jvm才分配了1g的内存,还是分配的比较少的。