我目前遇到很长时间的垃圾收集问题.请参阅以下内容.我目前的设置是我使用-Xms1g和-Xmx3g.我的应用程序使用的是java 1.4.2.我没有设置任何垃圾收集标志.从它的外观来看,3gb是不够的,我真的有很多垃圾收集对象.
题:
我应该改变我的垃圾收集算法吗?我应该用什么?是否更好用-XX:+UseParallelGC or -XX:+UseConcMarkSweepGC
或者我应该使用这种组合
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC
Run Code Online (Sandbox Code Playgroud)
占用内存的主要是报告数据而不是缓存数据.此外,该机器有16GB的内存,我打算将堆增加到8GB.
这两个选项有什么区别,因为我仍然觉得很难理解.该机器有多个处理器.我可以接受长达5秒的点击,但30到70秒真的很难.
谢谢您的帮助.
Line 151493: [14/Jan/2012:11:47:48] WARNING ( 8710): CORE3283: stderr: [GC 1632936K->1020739K(2050552K), 1.2462436 secs]
Line 157710: [14/Jan/2012:11:53:38] WARNING ( 8710): CORE3283: stderr: [GC 1670531K->1058755K(2050552K), 1.1555375 secs]
Line 163840: [14/Jan/2012:12:00:42] WARNING ( 8710): CORE3283: stderr: [GC 1708547K->1097282K(2050552K), 1.1503118 secs]
Line 169811: [14/Jan/2012:12:08:02] WARNING ( 8710): CORE3283: stderr: [GC 1747074K->1133764K(2050552K), 1.1017273 secs]
Line 175879: [14/Jan/2012:12:14:18] WARNING ( 8710): CORE3283: stderr: [GC 1783556K->1173103K(2050552K), 1.2060946 secs]
Line 176606: [14/Jan/2012:12:15:42] WARNING ( 8710): CORE3283: …
Run Code Online (Sandbox Code Playgroud) java performance garbage-collection g1gc concurrent-mark-sweep
有没有人设法在Hotspot中使用超过120GB RAM的Concurrent Mark Sweep垃圾收集器(UseConcMarkSweepGC)?
如果我将-ms和-mx设置为120G,JVM就会正常启动,但是如果我将它们设置为130G,则JVM会在启动时崩溃.JVM使用并行和G1收集器启动良好(但它们有自己的问题).
有没有人设法使用超过120GB堆的Concurrent Mark Sweep收集器?如果是这样,你有什么特别的,或者我只是在这里不走运?
来自JVM错误转储的堆栈如下:
Stack: [0x00007fbd0290d000,0x00007fbd02a0e000], sp=0x00007fbd02a0c758, free space=1021k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [libc.so.6+0x822c0] __tls_get_addr@@GLIBC_2.3+0x822c0
V [libjvm.so+0x389c01] CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray*, MemRegion, bool, FreeBlockDictionary::DictionaryChoice)+0xc1
V [libjvm.so+0x3d1ae0] ConcurrentMarkSweepGeneration::ConcurrentMarkSweepGeneration(ReservedSpace, unsigned long, int, CardTableRS*, bool, FreeBlockDictionary::DictionaryChoice)+0x100
V [libjvm.so+0x49d922] GenerationSpec::init(ReservedSpace, int, GenRemSet*)+0xf2
V [libjvm.so+0x48d0b9] GenCollectedHeap::initialize()+0x2e9
V [libjvm.so+0x824098] Universe::initialize_heap()+0xb8
V [libjvm.so+0x82657d] universe_init()+0x7d
V [libjvm.so+0x4cf0dd] init_globals()+0x5d
V [libjvm.so+0x80f462] Threads::create_vm(JavaVMInitArgs*, bool*)+0x1e2
V [libjvm.so+0x51fac4] JNI_CreateJavaVM+0x74
C [libjli.so+0x31b7] JavaMain+0x97
Run Code Online (Sandbox Code Playgroud)
我已经用Oracle(http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7175901)为此提出了一个错误,但我想知道是否有其他人见过它.
java garbage-collection jvm jvm-hotspot concurrent-mark-sweep
我看到许多类的卸载,我的整个系统将在这段时间内挂起..
[Unloading class sun.reflect.GeneratedMethodAccessor117]
[Unloading class sun.reflect.GeneratedConstructorAccessor1896]
[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor485]
[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor579]
.... // about 1700 of them
Run Code Online (Sandbox Code Playgroud)
与此同时,我没有看到烫发空间出现峰值,所以它似乎不是GC事件.
我想知道以下内容
IS Concurrent Mark Sweep收集了一个停止世界事件?
即使烫发空间不满也会发生吗?
我的一台生产机器有一个奇怪的问题.它托管一个执行CMS(并发标记和扫描)的Java应用程序,但它只清理了旧一代的一小部分.我怀疑内存泄漏并尝试了堆转储.但堆转储之前的Full GC几乎清除了所有旧代.发生了什么?我从未见过Java垃圾收集的这种行为.通常CMS和Full GC应该收集大约相同数量的垃圾,现在CMS保持大约10GB以上.
GC日志:
**2016-01-04T07:37:40.196+0000: 431200.698: [GC [1 CMS-initial-mark: 21633423K(27336704K)] 22826703K(30101504K), 4.3910840 secs] [Times: user=4.40 sys=0.01, real=4.39 secs]
2016-01-04T07:37:44.588+0000: 431205.090: [CMS-concurrent-mark-start]
2016-01-04T07:38:08.718+0000: 431229.220: [CMS-concurrent-mark: 18.213/24.131 secs] [Times: user=126.00 sys=2.22, real=24.13 secs]
2016-01-04T07:38:08.718+0000: 431229.220: [CMS-concurrent-preclean-start]
2016-01-04T07:38:08.843+0000: 431229.345: [CMS-concurrent-preclean: 0.118/0.125 secs] [Times: user=0.29 sys=0.00, real=0.12 secs]
2016-01-04T07:38:08.843+0000: 431229.345: [CMS-concurrent-abortable-preclean-start]
CMS: abort preclean due to time 2016-01-04T07:38:13.906+0000: 431234.408: [CMS-concurrent-abortable-preclean: 4.975/5.063 secs] [Times: user=10.18 sys=0.03, real=5.06 secs]
2016-01-04T07:38:14.001+0000: 431234.503: [GC[YG occupancy: 1312993 K (2764800 K)]2016-01-04T07:38:14.001+0000: 431234.503: [Rescan (parallel) …
Run Code Online (Sandbox Code Playgroud) 据我所知,我们可以使用下一个选项运行JVM:
-XX:+UseConcMarkSweepGC
-XX:-UseParNewGC
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我们将为年轻一代提供Serial(DefNew)垃圾收集器,为旧一代提供Concurrent Mark Sweep垃圾收集器.
那么,我们-XX:+UseConcMarkSweepGC
可以只选择运行JVM 吗?我的意思是没有任何描述年轻一代垃圾收集器的选项.如果我们能做到这一点,哪个垃圾收集器将用于老一代?
我在使用Concurrent Mark-Sweep收集器的应用程序的GC日志文件中看到以下症状:
4031.248: [CMS-concurrent-preclean-start]
4031.250: [CMS-concurrent-preclean: 0.002/0.002 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
4031.250: [CMS-concurrent-abortable-preclean-start]
CMS: abort preclean due to time 4036.346: [CMS-concurrent-abortable-preclean: 0.159/5.096 secs] [Times: user=0.00 sys=0.01, real=5.09 secs]
4036.346: [GC[YG occupancy: 55964 K (118016 K)]4036.347: [Rescan (parallel) , 0.0641200 secs]4036.411: [weak refs processing, 0.0001300 secs]4036.411: [class unloading, 0.0041590 secs]4036.415: [scrub symbol & string tables, 0.0053220 secs] [1 CMS-remark: 16015K(393216K)] 71979K(511232K), 0.0746640 secs] [Times: user=0.08 sys=0.00, real=0.08 secs]
Run Code Online (Sandbox Code Playgroud)
预清洁过程不断中止.我已经尝试将CMSMaxAbortablePrecleanTime从默认值5调整为15秒,但这没有帮助.当前的JVM选项如下......
Djava.awt.headless=true
-Xms512m
-Xmx512m
-Xmn128m
-XX:MaxPermSize=128m
-XX:+HeapDumpOnOutOfMemoryError
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:BiasedLockingStartupDelay=0
-XX:+DoEscapeAnalysis …
Run Code Online (Sandbox Code Playgroud) 简短形式:CMS垃圾收集器似乎未能收集到越来越多的垃圾; 最终,我们的JVM填满了,应用程序变得没有响应.通过外部工具(JConsole或jmap -histo:live
)强制GC 清除它一次.
更新:问题似乎与JConsole的JTop插件有关; 如果我们不运行JConsole,或者在没有JTop插件的情况下运行它,行为就会消失.
(技术说明:我们在Linux 2.6.9盒子上运行Sun JDK 1.6.0_07,32位.升级JDK版本并不是一个选择,除非有一个不可避免的主要原因.另外,我们的系统不是连接到可访问Internet的计算机,因此JConsole等的屏幕截图不是一个选项.)
我们当前正在运行带有以下标志的JVM:
-server -Xms3072m -Xmx3072m -XX:NewSize=512m -XX:MaxNewSize=512m
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled
-XX:CMSInitiatingOccupancyFraction=70
-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
-XX:+DisableExplicitGC
Run Code Online (Sandbox Code Playgroud)
在JConsole中观察内存图,有一个完整的GC,在我们的应用程序生命周期的前几个小时内每隔约15分钟运行一次; 在每个完整的GC之后,仍然有越来越多的内存在使用中.几个小时后,系统达到稳定状态,CMS旧版中大约有2GB的已用内存.
这听起来像是经典的内存泄漏,除非我们使用强制完整GC的任何工具(点击JConsole中的"收集垃圾"按钮,或运行jmap -histo:live
等),旧版本突然降至~500MB使用,我们的应用程序在接下来的几个小时内再次响应(在此期间相同的模式继续 - 在每个完整的GC之后,越来越多的旧版本已经满了.)
需要注意的一点是:在JConsole中,报告的ConcurrentMarkSweep GC计数将保持为0,直到我们使用jconsole/jmap/etc强制GC.
使用jmap -histo
并按jmap -histo:live
顺序,我能够确定明显未收集的对象包括:
HashMap
s和阵列HashMap$Entry
(以1:1的比例)Vector
s和Object数组(1:1的比例,与HashMaps的数量大致相同)HashSet
,Hashtable
和com.sun.jmx.remote.util.OrderClassLoader
s,以及数组Hashtable$Entry
(大约相同数量;大约是HashMaps和Vectors的一半)下面的GC输出中有一些摘录; 我对它们的解释似乎是CMS GC中止而没有故障转移到世界各地的GC.我是否以某种方式误解了这个输出?有什么东西会导致这种情况吗?
在正常运行时期间,CMS GC输出块看起来像这样:
36301.827: [GC [1 CMS-initial-mark: 1856321K(2621330K)] 1879456K(3093312K), 1.7634200 secs] [Times: user=0.17 sys=0.00, real=0.18 secs]
36303.638: [CMS-concurrent-mark-start] …
Run Code Online (Sandbox Code Playgroud) 我很困惑可能控制CMS收集器何时启动的两个参数:
MaxHeapFreeRatio
(默认为70%)
CMSInitiatingOccupancyFraction
(默认超过90%)
这些参数对每个参数意味着什么?收集器何时开始(标记阶段),并收集(扫描阶段)?
我有一个使用CMS垃圾收集的Java应用程序,每天都有几次"ParNew(促销失败)"完整的GC(见下面的例子).我知道当垃圾收集在旧一代中找不到足够的(连续的)空间来从新一代中提升对象时,会发生促销失败.在这一点上,它被迫做一个昂贵的世界末日GC.我想避免这种事件.
我已经阅读了几篇提出可行解决方案的文章,但我想在这里澄清/巩固它们:
如果它是相关的,这里是我当前的GC选项和促销失败事件之前的日志样本.
-Xmx4g -XX:+UseConcMarkSweepGC -XX:NewRatio=1
2014-12-19T09:38:34.304+0100: [GC (Allocation Failure) [ParNew: 1887488K->209664K(1887488K), 0.0685828 secs] 3115998K->1551788K(3984640K), 0.0690028 secs] [Times: user=0.50 sys=0.02, real=0.07 secs]
2014-12-19T09:38:35.962+0100: [GC (Allocation Failure) [ParNew: 1887488K->208840K(1887488K), 0.0827565 secs] 3229612K->1687030K(3984640K), 0.0831611 secs] [Times: user=0.39 sys=0.03, real=0.08 secs]
2014-12-19T09:38:39.975+0100: [GC (Allocation Failure) [ParNew: 1886664K->114108K(1887488K), 0.0442130 secs] 3364854K->1592298K(3984640K), 0.0446680 secs] [Times: user=0.31 sys=0.00, real=0.05 secs]
2014-12-19T09:38:44.818+0100: …
Run Code Online (Sandbox Code Playgroud) 我需要一些关于次要gc集合行为的澄清。调用a()
或调用b()
寿命长的应用程序,如果它们在旧空间变大时表现最差
//an example instance lives all application life cycle 24x7
public class Example {
private Object longLived = new Object();
public void a(){
var shortLived = new ShortLivedObject(longLived); // longLived now is attribute
shortLived.doSomething();
}
public void b(){
new ShortLivedObject().doSomething(new Object()); // actually now is shortlived
}
}
Run Code Online (Sandbox Code Playgroud)
我的疑惑来自何处?我发现,在使用的使用权空间变大的应用程序中,gc暂停次数增加了。
做一些测试,我发现如果我强迫jvm使用option,a()
而另一个jvm使用option b()
,则b()
当旧空间变大时,带有option的jvm的暂停持续时间较短,但我不知道为什么。
我使用4096中的此属性XX:ParGCCardsPerStrideChunk在应用程序中解决了该问题,但我想知道上述情况是否会导致gctimes增大,从而导致gccard表中的扫描速度变慢或我不知道或正在完全没有关系。
cms 和 g1 垃圾收集器之间有什么区别,这使得 g1 更好?
大多数地方都说这是因为在 G1 中,堆被分为多个区域,然后区域的集合被标记为年轻/年老代,并且 gc 在少数区域上运行,而不是在整个堆上运行。我正在尝试进一步了解这一点,并且还有几个问题:
当 young gc 运行时(即 stop the world),它会在所有年轻代区域上运行,这意味着堆的整个年轻部分以及不少年轻代区域。那么它与 CMS 所需的时间相同吗?
增量压缩 - 混合收集 - 现在我认为 G1 具有优势,因为整个堆的并发标记不断发生,并且存在在所有年轻区域 + 少数旧区域上运行的混合 gc 周期(首先是大多数垃圾)。因此它也会继续从老一代中删除垃圾,而不是等待 Full gc 发生。这是对的吗 ?
上述几点是否正确?还有哪些其他差异使 g1 更好?
我想知道为什么CMS需要两个阶段(以及两个暂停)的标记:即初始标记和备注.我们可以简单地做一个标记然后执行扫描吗?我想这可能是一个更快的停顿.有人可以帮助解释第二个标记的主要目的是什么以及我们为什么需要它?谢谢!
我正在运行 Oracle 的 64 位 Java 1.8 Hotspot JVM。当使用不同的 GC 机制时,我一直试图理解 JVM 的行为差异,以启动压缩对象指针。例如:
$ java -XX:+UseConcMarkSweepGC -XX:+PrintFlagsFinal -Xms32766m -Xmx32766m
bool UseCompressedClassPointers := true {lp64_product}
bool UseCompressedOops := true {lp64_product}
$ java -XX:+UseConcMarkSweepGC -XX:+PrintFlagsFinal -Xms32767m -Xmx32767m
bool UseCompressedClassPointers = false {lp64_product}
bool UseCompressedOops = false {lp64_product}
$ java -XX:+UseG1GC -XX:+PrintFlagsFinal -Xms32736m -Xmx32736m
bool UseCompressedClassPointers := true {lp64_product}
bool UseCompressedOops := true {lp64_product}
$ java -XX:+UseG1GC -XX:+PrintFlagsFinal -Xms32737m -Xmx32737m
bool UseCompressedClassPointers = false {lp64_product}
bool UseCompressedOops = false {lp64_product}
Run Code Online (Sandbox Code Playgroud)
我尝试更改其他一些 G1GC 旋钮,但无法获得压缩指针优化来启动 …