问题描述
如何编写一些代码将对象分配到 Old Gen 中,导致 Full GC 时间超过三五秒?
How to write some code to allocate the objects into Old Gen that will cause the full GC time longer than three or five seconds?
推荐答案
将对象分配到 Old Gen"和长时间的 GC 暂停"很难结合起来,因为你可以对垃圾收集器做的最糟糕的事情就是创建许多小的、链接的、活动的对象,形成垃圾收集器必须遍历的图.
"Allocate the objects into Old Gen" and "long GC pauses" are hard to combine, as the worst thing you could do to the garbage collector, is to create lots of small, linked, live objects forming a graph that the garbage collector must traverse.
但是小对象不会分配到旧代中.只有大对象,例如数组,直接分配到旧代中,但这些不会对 GC 造成太大压力.尤其是您在第一次尝试中使用的原始类型数组并不具有挑战性,因为它们通常不能包含对象引用.
But small objects are not allocated into the Old Gen. Only large objects, e.g. arrays, are allocated directly into the Old Gen, but these do not stress the GC that much. Especially primitive type arrays, which you stated to have been used in your first attempt, are no challenge, as they can not contain object references in general.
所以,为了强调 GC,你必须创建大量的小链接对象,足以让它们最终提升到 Old Gen,然后修改旧对象以强制执行 Full GC,分别.受影响卡片记忆组的更新.
So, to stress the GC, you have to create lots of small linked objects, enough to get them eventually promoted to the Old Gen, followed by modifying the old objects to enforce Full GC, resp. updates of the remembered sets of the affected cards.
如果这听起来像熟悉的模式,那你是对的.我们在这里讨论的是 LinkedList
.
If that’s sounds like familiar pattern, you’re right. We’re talking about LinkedList
here.
LinkedList<Object> list = new LinkedList<>();
for(ListIterator<Object> it = list.listIterator();;) {
for(;;) {
it.add(new Object());
if(!it.hasNext()) break;
it.next();
}
while(it.hasPrevious()) {
it.previous();
it.add(new Object());
it.previous();
}
}
这在列表上来回迭代,在旧对象之间插入新对象,这意味着修改 next
指针和 prev
后续列表节点的指针.我们必须通过 ListIterator
来做到这一点,因为尝试使用 add(int index, E element)
对于不断增长的链表来说会变得太慢,无法创建足够的对象来强调GC.
This iterates over the list back and forth, inserting new objects between the old ones, which implies modifying the next
pointer of the preceding and the prev
pointer of the succeeding list node. We have to do this via ListIterator
, as trying to use add(int index, E element)
would become too slow for a growing linked list, not creating enough objects to stress the GC.
使用 -Xmx7G -Xlog:gc
在 Java 9.0.4 上运行给了我
Running on Java 9.0.4 with -Xmx7G -Xlog:gc
gave me
[0.023s][info][gc] Using G1
[0.230s][info][gc] GC(0) Pause Young (G1 Evacuation Pause) 24M->22M(256M) 60.748ms
[0.263s][info][gc] GC(1) Pause Young (G1 Evacuation Pause) 34M->36M(256M) 21.686ms
[0.299s][info][gc] GC(2) Pause Young (G1 Evacuation Pause) 46M->47M(256M) 18.848ms
[0.336s][info][gc] GC(3) Pause Young (G1 Evacuation Pause) 57M->58M(256M) 20.904ms
[0.391s][info][gc] GC(4) Pause Young (G1 Evacuation Pause) 68M->68M(768M) 31.420ms
[0.521s][info][gc] GC(5) Pause Young (G1 Evacuation Pause) 104M->105M(768M) 56.681ms
[0.620s][info][gc] GC(6) Pause Young (G1 Evacuation Pause) 138M->140M(768M) 46.616ms
[0.737s][info][gc] GC(7) Pause Young (G1 Evacuation Pause) 173M->174M(768M) 58.947ms
[0.906s][info][gc] GC(8) Pause Young (G1 Evacuation Pause) 207M->209M(2304M) 100.361ms
[1.272s][info][gc] GC(9) Pause Young (G1 Evacuation Pause) 319M->321M(2304M) 142.440ms
[1.656s][info][gc] GC(10) Pause Young (G1 Evacuation Pause) 421M->423M(2304M) 162.770ms
[1.992s][info][gc] GC(11) Pause Young (G1 Evacuation Pause) 523M->525M(2304M) 145.804ms
[2.404s][info][gc] GC(12) Pause Young (G1 Evacuation Pause) 625M->627M(4250M) 221.090ms
[3.088s][info][gc] GC(13) Pause Young (G1 Evacuation Pause) 824M->826M(4250M) 302.307ms
[3.721s][info][gc] GC(14) Pause Young (G1 Evacuation Pause) 1011M->1013M(4250M) 250.395ms
[4.421s][info][gc] GC(15) Pause Young (G1 Evacuation Pause) 1198M->1199M(4250M) 304.642ms
[5.179s][info][gc] GC(16) Pause Young (G1 Evacuation Pause) 1384M->1386M(5418M) 334.825ms
[6.134s][info][gc] GC(17) Pause Young (G1 Evacuation Pause) 1629M->1631M(5418M) 381.155ms
[6.897s][info][gc] GC(18) Pause Young (G1 Evacuation Pause) 1867M->1868M(5418M) 309.688ms
[7.670s][info][gc] GC(19) Pause Young (G1 Evacuation Pause) 2104M->2106M(5418M) 399.689ms
[8.498s][info][gc] GC(20) Pause Young (G1 Evacuation Pause) 2342M->2344M(6118M) 388.430ms
[9.515s][info][gc] GC(21) Pause Young (G1 Evacuation Pause) 2615M->2617M(6118M) 439.557ms
[10.477s][info][gc] GC(22) Pause Young (G1 Evacuation Pause) 2883M->2884M(6118M) 451.488ms
[11.489s][info][gc] GC(23) Pause Initial Mark (G1 Evacuation Pause) 3150M->3152M(6118M) 443.329ms
[11.489s][info][gc] GC(24) Concurrent Cycle
[12.660s][info][gc] GC(25) Pause Young (G1 Evacuation Pause) 3418M->3419M(6538M) 467.964ms
[14.124s][info][gc] GC(26) Pause Young (G1 Evacuation Pause) 3706M->3708M(6538M) 454.921ms
[15.538s][info][gc] GC(27) Pause Young (G1 Evacuation Pause) 3993M->3995M(6538M) 465.929ms
[16.945s][info][gc] GC(28) Pause Young (G1 Evacuation Pause) 4280M->4281M(6538M) 460.913ms
[18.490s][info][gc] GC(29) Pause Young (G1 Evacuation Pause) 4566M->4568M(6790M) 493.803ms
[20.083s][info][gc] GC(30) Pause Young (G1 Evacuation Pause) 4866M->4868M(6790M) 491.910ms
[21.516s][info][gc] GC(31) Pause Young (G1 Evacuation Pause) 5164M->5166M(6790M) 486.847ms
[22.895s][info][gc] GC(32) Pause Young (G1 Evacuation Pause) 5462M->5464M(6790M) 443.031ms
[24.342s][info][gc] GC(33) Pause Young (G1 Evacuation Pause) 5760M->5762M(6942M) 475.235ms
[25.258s][info][gc] GC(24) Pause Remark 5988M->5988M(6942M) 0.794ms
[25.827s][info][gc] GC(34) Pause Young (G1 Evacuation Pause) 6066M->6067M(6942M) 458.463ms
[27.021s][info][gc] GC(35) Pause Young (G1 Evacuation Pause) 6370M->6372M(6942M) 448.794ms
[27.485s][info][gc] GC(24) Pause Cleanup 6484M->6484M(6942M) 28.631ms
[27.490s][info][gc] GC(24) Concurrent Cycle 16000.856ms
[28.250s][info][gc] GC(36) Pause Young (G1 Evacuation Pause) 6675M->6676M(7024M) 481.748ms
[29.651s][info][gc] GC(37) To-space exhausted
[29.651s][info][gc] GC(37) Pause Initial Mark (G1 Evacuation Pause) 6983M->7127M(7168M) 751.288ms
[29.651s][info][gc] GC(38) Concurrent Cycle
[30.135s][info][gc] GC(39) To-space exhausted
[30.135s][info][gc] GC(39) Pause Young (G1 Evacuation Pause) 7168M->7168M(7168M) 203.578ms
[30.205s][info][gc] GC(40) Pause Young (G1 Evacuation Pause) 7168M->7168M(7168M) 69.831ms
[53.924s][info][gc] GC(41) Pause Full (Allocation Failure) 7168M->6955M(7168M) 23719.072ms
[53.924s][info][gc] GC(38) Concurrent Cycle 24273.544ms
[54.654s][info][gc] GC(42) To-space exhausted
[54.654s][info][gc] GC(42) Pause Young (G1 Evacuation Pause) 7167M->7167M(7168M) 484.771ms
[54.811s][info][gc] GC(43) Pause Initial Mark (G1 Evacuation Pause) 7167M->7167M(7168M) 156.984ms
[54.811s][info][gc] GC(44) Concurrent Cycle
[75.187s][info][gc] GC(45) Pause Full (Allocation Failure) 7167M->7166M(7168M) 20375.807ms
[75.187s][info][gc] GC(44) Concurrent Cycle 20375.993ms
[75.197s][info][gc] GC(46) To-space exhausted
[75.197s][info][gc] GC(46) Pause Young (G1 Evacuation Pause) 7167M->7167M(7168M) 8.585ms
[75.199s][info][gc] GC(47) Pause Initial Mark (G1 Evacuation Pause) 7167M->7167M(7168M) 1.773ms
[75.199s][info][gc] GC(48) Concurrent Cycle
[95.382s][info][gc] GC(49) Pause Full (Allocation Failure) 7167M->7167M(7168M) 20183.050ms
[115.575s][info][gc] GC(50) Pause Full (Allocation Failure) 7167M->7167M(7168M) 20192.989ms
[115.575s][info][gc] GC(48) Concurrent Cycle 40376.227ms
[115.581s][info][gc] GC(51) Pause Young (G1 Evacuation Pause) 7167M->7167M(7168M) 2.649ms
[115.613s][info][gc] GC(52) Pause Initial Mark (G1 Evacuation Pause) 7167M->7167M(7168M) 0.629ms
[115.613s][info][gc] GC(53) Concurrent Cycle
[119.694s][info][gc] GC(54) Pause Full (Allocation Failure) 7167M->0M(8M) 4080.414ms
[119.694s][info][gc] GC(53) Concurrent Cycle 4080.622ms
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.base/java.util.LinkedList.linkBefore(LinkedList.java:162)
at java.base/java.util.LinkedList$ListItr.add(LinkedList.java:952)
at test.Tmp.main(Tmp.java:32)
注意报告的暂停在 [53.924s]
、[75.187s]
、[95.382s]
和 [115.575s]
超过 20 秒…
Note the reported pauses at [53.924s]
, [75.187s]
, [95.382s]
, and [115.575s]
of over 20seconds each…
这篇关于如何在 Java 中手动进行长时间的 Full GC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!