![](/img/trans.png)
[英]how to solve 'java.lang.OutOfMemoryError: GC overhead limit exceeded'
[英]How to reproduce Java OutOfMemoryError - GC overhead limit exceeded
我的方法是創建十萬個本地集合並用隨機字符串填充它們,如下所示:
SecureRandom random = new SecureRandom();
for(int i = 0 ; i < 100000 ; i++){
HashMap<String, String> map = new HashMap<String, String>();
for(int j = 0 ; j < 30 ; j++){
map.put(new BigInteger(130, random).toString(32), new BigInteger(130, random).toString(32));
}
}
我也提供了-XX:+ UseGCOverheadLimit jvm參數,但無法獲取錯誤。 是否有任何簡單可靠的方法/黑客來獲取此錯誤?
既然你沒有接受任何答案,我會假設他們都沒有為你工作。 這是一個會。 但首先,審查觸發此錯誤的條件 :
如果在垃圾收集中花費了太多時間,則並行收集器將拋出OutOfMemoryError:如果超過98%的總時間用於垃圾收集並且回收的堆少於2%
因此,您必須消耗幾乎所有的堆,保持分配,然后分配大量垃圾。 將大量內容放入Map
並不會為您做到這一點。
public static void main(String[] argv)
throws Exception
{
List<Object> fixedData = consumeAvailableMemory();
while (true)
{
Object data = new byte[64 * 1024 - 1];
}
}
private static List<Object> consumeAvailableMemory()
throws Exception
{
LinkedList<Object> holder = new LinkedList<Object>();
while (true)
{
try
{
holder.add(new byte[128 * 1024]);
}
catch (OutOfMemoryError ex)
{
holder.removeLast();
return holder;
}
}
}
consumeAvailableMemory()
方法用相對較小的內存塊填充堆。 “相對較小”很重要,因為JVM會將“大”對象(我的經驗中為512k字節)直接放入終身代,讓年輕一代空着。
在我消耗了大部分堆之后,我只是分配並丟棄。 這個階段較小的塊大小很重要:我知道我將有足夠的內存用於至少一次分配,但可能不超過兩次。 這將使GC保持活動狀態。
運行它會在一秒鍾內產生所需的錯誤:
> java -Xms1024m -Xmx1024m GCOverheadTrigger
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
at GCOverheadTrigger.main(GCOverheadTrigger.java:12)
而且,為了完整性,這里是我正在使用的JVM:
> java -version
java version "1.6.0_45"
Java(TM) SE Runtime Environment (build 1.6.0_45-b06)
Java HotSpot(TM) 64-Bit Server VM (build 20.45-b01, mixed mode)
現在我的問題是你:為什么你想在世界上做這個?
這個:
HashMap<String, String> map = new HashMap<String, String>();
在循環中作用域,並且在循環迭代時沒有創建對映射的外部(長期)引用。 因此,每個循環迭代結束時,每個映射都有資格進行垃圾收集。
您需要在循環外創建一個對象集合,並使用循環來填充該集合。
我認為這應該可以解決問題......如果你跑的時間足夠長:
HashMap<Long, String> map = new HashMap<Long, String>();
for (long i = 0; true; i++) {
for (int j = 0; j < 100; j++) {
String s = "" + j;
map.put(i, s);
}
}
我正在做的是慢慢增加非垃圾量,同時創造大量垃圾。 如果運行此操作直到非垃圾填滿幾乎所有堆,則GC將達到垃圾收集所花費的時間百分比超過閾值的點。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.