خطأ java.lang.outofmemoryerror: الحد الأدنى النفقات العامة GC
-
21-09-2019 - |
سؤال
أحصل على رسالة الخطأ هذه أثناء تنفيذ اختبارات Junit الخاصة بي:
java.lang.OutOfMemoryError: GC overhead limit exceeded
أنا أعرف ما OutOfMemoryError
هل ، لكن ماذا يعني حد GC النفقات العامة؟ كيف يمكنني حل هذا؟
المحلول
تعني هذه الرسالة أنه لسبب ما ، يستغرق جامع القمامة قدرًا مفرطًا من الوقت (افتراضيًا 98 ٪ من وقت وحدة المعالجة المركزية للعملية) ويسترد القليل جدًا من الذاكرة في كل تشغيل (افتراضيًا 2 ٪ من الكومة).
هذا يعني بشكل فعال أن برنامجك يتوقف عن القيام بأي تقدم وهو مشغول بتشغيل مجموعة القمامة فقط في جميع الأوقات.
لمنع طلبك من امتصاص وقت وحدة المعالجة المركزية دون إنجاز أي شيء ، يلقي JVM هذا Error
بحيث يكون لديك فرصة لتشخيص المشكلة.
الحالات النادرة التي رأيت فيها يحدث ذلك هي المكان الذي كانت فيه بعض التعليمات البرمجية تنشئ الكثير من الكائنات المؤقتة وأطنان من الكائنات المرجعية بشكل ضعيف في بيئة مخصصة للذاكرة بالفعل.
الدفع هذه المقالة للحصول على التفاصيل (على وجه التحديد هذا الجزء).
نصائح أخرى
يلقي GC هذا الاستثناء عندما يتم قضاء الكثير من الوقت في مجموعة القمامة لعودة قليلة للغاية ، على سبيل المثال. يتم إنفاق 98 ٪ من وقت وحدة المعالجة المركزية على GC ويتم استرداد أقل من 2 ٪ من الكومة.
تم تصميم هذه الميزة لمنع التطبيقات من الركض لفترة طويلة من الزمن مع إحراز تقدم ضئيل أو معدوم لأن الكومة صغيرة جدًا.
يمكنك إيقاف تشغيل هذا مع خيار سطر الأوامر-XX:-UseGCOverheadLimit
مزيد من المعلومات هنا
تحرير: يبدو أن شخصًا ما يمكنه الكتابة بشكل أسرع مني :)
إذا كنت متأكدًا من أنه لا يوجد تسريبات الذاكرة في برنامجك ، حاول:
- زيادة حجم الكومة ، على سبيل المثال
-Xmx1g
. - تمكين جامع التوقف المؤقت المتزامن
-XX:+UseConcMarkSweepGC
. - أعد استخدام الكائنات الموجودة عندما يكون ذلك ممكنًا لحفظ بعض الذاكرة.
إذا لزم الأمر ، فحص الحد يمكن تعطيلها بإضافة الخيار -XX:-UseGCOverheadLimit
إلى سطر الأوامر.
عادة ما يكون الرمز. هذا مثال بسيط:
import java.util.*;
public class GarbageCollector {
public static void main(String... args) {
System.out.printf("Testing...%n");
List<Double> list = new ArrayList<Double>();
for (int outer = 0; outer < 10000; outer++) {
// list = new ArrayList<Double>(10000); // BAD
// list = new ArrayList<Double>(); // WORSE
list.clear(); // BETTER
for (int inner = 0; inner < 10000; inner++) {
list.add(Math.random());
}
if (outer % 1000 == 0) {
System.out.printf("Outer loop at %d%n", outer);
}
}
System.out.printf("Done.%n");
}
}
باستخدام Java 1.6.0_24-B07 على Windows7 32 بت.
java -xloggc: gc.log garbagecollector
ثم انظر إلى gc.log
- نشأ 444 مرة باستخدام طريقة سيئة
- أدى 666 مرة باستخدام طريقة أسوأ
- نشأ 354 مرة باستخدام طريقة أفضل
منحت الآن ، هذا ليس هو أفضل اختبار أو أفضل تصميم ، ولكن عندما تواجه موقفًا ليس لديك فيه خيار سوى تنفيذ مثل هذه الحلقة أو عند التعامل مع التعليمات البرمجية الحالية التي تتصرف بشكل سيء ، فإن اختيار إعادة استخدام الكائنات بدلاً من إنشاء واحدة جديدة يمكن أن تقلل عدد المرات التي يحصل فيها جامع القمامة في الطريق ...
سبب ل خطأ
الحد الأدنى النفقات العامة لـ GC "يشير إلى أن جامع القمامة يعمل طوال الوقت وأن برنامج Java يحرز تقدماً بطيئًا للغاية.
بعد مجموعة القمامة ، إذا كان تنفق عملية Java أكثر من 98 ٪ تقريبًا من وقتها في جمع القمامة وإذا كان يتعافى أقل من 2 ٪ من الكومة وكان يعمل حتى الآن في مجموعات القمامة الخمسة الأخيرة (ثابتة الترجمة) على التوالي ، ثم أ java.lang.outofmemoryerror هذا خطئ
- زيادة حجم الكومة إذا كان الكومة الحالية لا يكفي.
- إذا كنت لا تزال تحصل على هذا الخطأ بعد زيادة ذاكرة الكومة ، استخدم الذاكرة أدوات التنميط مثل حصيرة (أداة محلل الذاكرة) ، VIST VM الخ وإصلاح تسرب الذاكرة.
- ترقية إصدار JDK إلى أحدث إصدار (1.8.x) أو ما لا يقل عن 1.7.x واستخدم خوارزمية G1GC. . هدف الإنتاجية لـ G1 GC هو وقت التطبيق بنسبة 90 في المائة و 10 في المائة من وقت جمع القمامة
بصرف النظر عن وضع ذاكرة الكومة مع -
Xms1g -Xmx2g
، محاولة-XX:+UseG1GC -XX:G1HeapRegionSize=n -XX:MaxGCPauseMillis=m -XX:ParallelGCThreads=n -XX:ConcGCThreads=n
ألق نظرة على بعض الأسئلة ذات الصلة المتعلقة بخصوص G1GC
Java 7 (JDK 7) مجموعة القمامة والوثائق على G1
فقط قم بزيادة حجم الكومة قليلاً من خلال تحديد هذا الخيار في
تشغيل → قم بتشغيل التكوينات ← وسيطات → VM وسيطات
-Xms1024M -Xmx2048M
XMS - للحصول على الحد الأدنى
XMX - للحصول على الحد الأقصى
بالنسبة لي ، عملت الخطوات التالية:
- افتح ال
eclipse.ini
ملف يتغيرون
-Xms40m -Xmx512m
ل
-Xms512m -Xmx1024m
إعادة تشغيل الكسوف
جرب هذا
افتح ال build.gradle
ملف
android {
dexOptions {
javaMaxHeapSize = "4g"
}
}
ما يلي عمل بالنسبة لي. فقط أضف المقتطف التالي:
android {
compileSdkVersion 25
buildToolsVersion '25.0.1'
defaultConfig {
applicationId "yourpackage"
minSdkVersion 10
targetSdkVersion 25
versionCode 1
versionName "1.0"
multiDexEnabled true
}
dexOptions {
javaMaxHeapSize "4g"
}
}
زيادة javamaxheapsize في ملف build.gradle (الوحدة النمطية: التطبيق)
dexOptions {
javaMaxHeapSize "1g"
}
إلى (إضافة هذا الخط في Gradle)
dexOptions {
javaMaxHeapSize "4g"
}
يمكنك أيضًا زيادة تخصيص الذاكرة وحجم الكومة عن طريق إضافة هذا إلى gradle.properties
ملف:
org.gradle.jvmargs=-Xmx2048M -XX\:MaxHeapSize\=32g
لا يجب أن يكون 2048 مترًا و 32 جرامًا ، مما يجعله كبيرًا كما تريد.
تحتاج إلى زيادة حجم الذاكرة في JDeveloper اذهب إلى setdomainenv.cmd.
set WLS_HOME=%WL_HOME%\server
set XMS_SUN_64BIT=**256**
set XMS_SUN_32BIT=**256**
set XMX_SUN_64BIT=**3072**
set XMX_SUN_32BIT=**3072**
set XMS_JROCKIT_64BIT=**256**
set XMS_JROCKIT_32BIT=**256**
set XMX_JROCKIT_64BIT=**1024**
set XMX_JROCKIT_32BIT=**1024**
if "%JAVA_VENDOR%"=="Sun" (
set WLS_MEM_ARGS_64BIT=**-Xms256m -Xmx512m**
set WLS_MEM_ARGS_32BIT=**-Xms256m -Xmx512m**
) else (
set WLS_MEM_ARGS_64BIT=**-Xms512m -Xmx512m**
set WLS_MEM_ARGS_32BIT=**-Xms512m -Xmx512m**
)
و
set MEM_PERM_SIZE_64BIT=-XX:PermSize=**256m**
set MEM_PERM_SIZE_32BIT=-XX:PermSize=**256m**
if "%JAVA_USE_64BIT%"=="true" (
set MEM_PERM_SIZE=%MEM_PERM_SIZE_64BIT%
) else (
set MEM_PERM_SIZE=%MEM_PERM_SIZE_32BIT%
)
set MEM_MAX_PERM_SIZE_64BIT=-XX:MaxPermSize=**1024m**
set MEM_MAX_PERM_SIZE_32BIT=-XX:MaxPermSize=**1024m**
أنا أعمل في Android Studio وواجهت هذا الخطأ عند محاولة إنشاء APK موقّع للإصدار. تمكنت من بناء واختبار تصحيح أخطاء APK دون أي مشكلة ، ولكن بمجرد أن أرغب في إنشاء إصدار APK ، سيتم تشغيل عملية الإنشاء لمدة دقائق متتالية ، ثم تنتهي أخيرًا مع "خطأ java.lang.outofmemoryror: GC تجاوز الحد العلوي ". لقد قمت بزيادة أحجام الكومة لكل من VM و Android Dex برنامج التحويل البرمجي ، لكن المشكلة استمرت. أخيرًا ، بعد عدة ساعات وأكواب قهوة ، اتضح أن المشكلة كانت في ملف "build.gradle" على مستوى التطبيق - كان لدي المعلمة "MinifyEnabled" لنوع بناء الإصدار إلى "False" ، وبالتالي تشغيل المواد البروغوارد على الرمز الذي لم يمر من خلال عملية تقسيم الكود (انظر https://developer.android.com/studio/build/shrink-code.html). لقد غيرت المعلمة "MinifyEnabled" إلى "True" وتم تنفيذ بناء الإصدار كحلم :)
باختصار ، اضطررت إلى تغيير ملف "build.gradle" على مستوى التطبيق من: // ...
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.sign_config_release
}
debug {
debuggable true
signingConfig signingConfigs.sign_config_debug
}
}
//...
ل
//...
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.sign_config_release
}
debug {
debuggable true
signingConfig signingConfigs.sign_config_debug
}
}
//...
لزيادة حجم الكومة في فكرة Intellij اتبع التعليمات التالية. عملت معي.
لمستخدمي Windows ،
انتقل إلى الموقع حيث يتم تثبيت IDE والبحث عن المتابعة.
idea64.exe.vmoptions
تحرير الملف وإضافة ما يلي.
-Xms512m
-Xmx2024m
-XX:MaxPermSize=700m
-XX:ReservedCodeCacheSize=480m
هذا هو !!
إعادة تشغيل جهاز MacBook الخاص بي إصلاح هذه المشكلة بالنسبة لي.
في Netbeans ، قد يكون من المفيد تصميم حجم كومة أقصى. اذهب إلى يركض => تعيين تكوين المشروع => يعدل أو يكيف. في ال يركض من نافذتها ، انتقل إلى خيار VM, ، أملأ -Xms2048m -Xmx2048m
. يمكن أن يحل مشكلة حجم الكومة.