`
ouyida3
  • 浏览: 47952 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

关于java内存

    博客分类:
  • java
阅读更多
最近系统偶尔抛出错误:
Caused by: java.lang.OutOfMemoryError: GC overhead limit exceeded

于是简单研究了一下内存的配置。

-XX:PermSize=64m -XX:MaxPermSize=64m
这个是非堆内存配置,初始与最大。64兆系统启动没有问题,如果设置为32兆,则会报错:
java.lang.OutOfMemoryError: PermGen space,并且系统启动失败。

-XX:PermSize=64m -XX:MaxPermSize=32m
不要以为最大设为32就可以控制非堆为32兆,实践证明这样还是以64兆初始的,启动成功。

非堆主要用于反射等,所以不用太大,够用就行。

-Xms128m -Xmx128m
这个是堆,也就是heap。要设置大一些。一般初始和最大设为一样,减少变化时的开销。
如果设置过小,比如32m,也是可以启动成功,也可以访问页面,但是会输出日志:
[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor3]

有generation机制。heap分为young和old。
-Xmn是控制young的。一般分配四分之一。
-Xmn32m
所以,很自然的,Xmx-Xmn就是old。当jvm有一个线程,会在不足时把young升级为old的。

网上说Xmx不要超过物理内存,否则会报错:
“Error occurred during initialization of VM Could not reserve enough space for object heap”

也就是说本文第一句的系统报错不是别的应用占用了内存导致,而是本身分配给应用的内存不够导致。
系统组跟我说杀掉其他应用就解决了这个说法是错误的。

同时,网上说web应用的heap值可以比gui的大。也就是说heap与吞吐量有关。

可以增加日志观察GC的情况:
-XX:+PrintGCDetails -Xloggc:d:\gc.log
+号是开,-号是关。

看gc.log文件:
3.784: [GC 3.784: [DefNew: 26240K->3264K(29504K), 0.0409710 secs] 26240K->3677K(521024K), 0.0411614 secs] [Times: user=0.05 sys=0.00, real=0.05 secs]
15.576: [Full GC 15.576: [Tenured: 0K->12588K(349568K), 0.3585221 secs] 70393K->12588K(506816K), [Perm : 36863K->36863K(36864K)], 0.3587096 secs] [Times: user=0.31 sys=0.03, real=0.36 secs]

DefNew是young,Tenured是old。
young里存活久的对象会自动移到old。old里回收并不频繁。

同样一个操作,如果Xms过小,jvm需要频繁的回收对象,log日志就会很多;
相反,Xms设置大,log日志会少很多。

如果PermSize设置大,DefNew会多,Tenured少。比如
-XX:PermSize=64m -XX:MaxPermSize=64m
基本没有Tenured。

Minor收集young,Major收集old,
-XX:+UseParNewGC调节Minor,-XX:+UseConcMarkSweepGC调节Major,没时间尝试,先不管。

解决方案:
1 增加gc.log日志
2 调大Xms和Xmx为4G试试,现在是2G


============

2013.7.19
增加一种方案:增加选项:-XX:-UseGCOverheadLimit

if too much time is being spent in garbage collection: if more than 98% of the total time is spent in garbage collection and less than 2% of the heap is recovered, an OutOfMemoryError will be thrown.

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics