جافا ConcurrentMarkSweep جامع القمامة لا إزالة جميع النفايات

StackOverflow https://stackoverflow.com/questions/3873635

سؤال

النموذج القصير:CMS جامع القمامة يبدو أن الفشل في جمع كمية متزايدة من القمامة;في نهاية المطاف ، JVM تملأ و يصبح لا يستجيب التطبيق.مما اضطر GC طريق خارجي أداة (أو JConsole jmap -histo:live) ينظف عنه مرة واحدة.

تحديث:ويبدو أن المشكلة تتعلق JTop المساعد JConsole;إذا لم تشغيل JConsole ، أو تشغيله دون JTop المساعد, سلوك يذهب بعيدا.

(الملاحظات الفنية:نحن تشغيل الشمس JDK 1.6.0_07 ، 32 بت على لينكس 2.6.9 مربع.ترقية نسخة JDK ليست خيارا ، ما لم يكن هناك لا مفر منه, السبب الرئيسي.كما لدينا نظام التوصيل إلى الوصول إليها عبر الإنترنت آلة, لذلك لقطات من 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

مراقبة الذاكرة البياني في JConsole هناك GC الكامل الذي يدير كل ~15 دقيقة أو حتى خلال أول عدة ساعات من التطبيق العمر ؛ بعد كل GC الكامل ، هناك المزيد و المزيد من الذاكرة لا تزال في الاستخدام.بعد ساعات قليلة النظام يضرب حالة مستقرة حيث هناك ما يقرب من 2 غيغابايت من الذاكرة المستخدمة في CMS old gen.

التي تبدو كلاسيكية تسرب الذاكرة, إلا أنه إذا كان لنا أن استخدام أي أداة قوات كامل GC (ضرب "جمع القمامة" زر في JConsole ، أو تشغيل jmap -histo:live, الخ) old gen يسقط فجأة إلى ~500MB تستخدم ، يصبح تطبيق استجابة مرة أخرى على مدار عدة ساعات (خلال الوقت الذي نفس النمط لا يزال - بعد كل GC الكامل أكثر من old gen هو الكامل.)

شيء واحد من ملاحظة:في JConsole ، ذكرت ConcurrentMarkSweep GC العد البقاء في 0 حتى نجبر GC مع jconsole/jmap/الخ.

باستخدام jmap -histo و jmap -histo:live في تسلسل ، أنا قادرة على تحديد ما يبدو غير المحصلة الكائنات تتكون من:

  • عدة ملايين من HashMaps و صفائف HashMap$Entry (في نسبة 1:1)
  • عدة ملايين من Vectors وجوه المصفوفات (نسبة 1:1, و تقريبا نفس عدد HashMaps)
  • عدة ملايين من HashSet, Hashtable, ، com.sun.jmx.remote.util.OrderClassLoaders, وكذلك صفائف Hashtable$Entry (حوالي نفس العدد من كل ؛ حوالي نصف هذا العدد كما HashMaps و ناقلات)

هناك بعض مقتطفات من الإخراج أدناه ؛ تفسيري لهم يبدو أن CMS GC هو الحصول على إحباط دون الفشل إلى توقف العالم GC.أسأت تفسير هذا الإخراج بطريقة أو بأخرى ؟ هل هناك شيء من شأنه أن يسبب هذا ؟

أثناء وقت التشغيل العادي, CMS الإخراج كتل تبدو مثل هذا:

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]
36314.903: [CMS-concurrent-mark: 7.804/11.264 secs] [Times: user=2.13 sys=0.06, real=1.13 secs]
36314.903: [CMS-concurrent-preclean-start]
36314.963: [CMS-concurrent-preclean: 0.037/0.060 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
36314.963: [CMS-concurrent-abortable-preclean-start]
36315.195: [GC 36315.195: [ParNew: 428092K->40832K(471872K), 1.1705760 secs] 2284414K->1897153K(3093312K), 1.1710560 secs] [Times: user=0.13 sys=0.02, real=0.12 secs]
CMS: abort preclean due to time 36320.059: [CMS-concurrent-abortable-preclean: 0.844/5.095 secs] [Times: user=0.74 sys=0.05, real=0.51 secs]
36320.062: [GC[YG occupancy: 146166 K (471872 K)]36320.062: [Rescan (parallel), 1.54078550 secs]36321.603: [weak refs processing, 0.0042640 secs] [1 CMS-remark: 1856321K(2621440K)] 2002488K(3093312K), 1.5456150 secs] [Times: user=0.18 sys=0.03, real=0.15 secs]
36321.608: [CMS-concurrent-sweep-start]
36324.650: [CMS-concurrent-sweep: 2.686/3.042 secs] [Times: uesr=0.66 sys=0.02, real=0.30 secs]
36324.651: [CMS-concurrent-reset-start]
36324.700: [CMS-concurrent-reset: 0.050/0.050 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]

وأن كل ما في الأمر ؛ السطر التالي سوف يكون القادم ParNew GC.

عندما نجبر GC باستخدام jmap -ت:نعيش بدلا من ذلك الحصول على:

48004.088: [CMS-concurrent-mark: 8.012/8.647 secs] [Times: user=1.15 sys=0.02, real=0.87 secs]
(concurrent mode interrupted)

تليها ~125 غرار النموذج أدناه:(بعض GeneratedMethodAccessor بعض GeneratedSerializationConstructoraccessor بعض GeneratedConstructorAccessor, الخ)

[Unloading class sun.reflect.GeneratedMethodAccessor3]

تليها:

: 1911295K->562232K(2621440K), 15.6886180 secs] 2366440K->562232K(3093312K), [CMS Perm: 52729K->51864K(65536K)], 15.6892270 secs] [Times: user=1.55 sys=0.01, real=1.57 secs]

شكرا مقدما!

هل كانت مفيدة؟

المحلول

com.الشمس.jmx.جهاز التحكم عن بعد.util.OrderClassLoader يستخدم في التحكم عن بعد التعرف على طبقة JMX ومراجعة سريعة من قانون يوحي انهم إنشاؤها كجزء من unmarshalling العملية عن بعد الطلبات داخل JVM.عمر تلك classloaders سوف تكون ذات صلة مباشرة إلى عمر الشيء الذي كان unmarshalled مثل هذا مرة واحدة لم يعد هناك أي إشارات إلى هذا الشيء classloader يمكن الافراج عنهم.

لن أكون مندهشا إذا في هذه الحالة وجود هذه الحالات كانت نتيجة مباشرة يمكنك استخدام JConsole لدراسة ما يجري في JVM.و يبدو أنها ستكون مجرد تنظيفها بواسطة GC كجزء من العملية العادية.

أعتقد أنه من الممكن أن يكون هناك خلل في JMX تنفيذ (يبدو من غير المحتمل نسبيا يصل إلى تاريخ JVM) أو ربما لديك بعض مخصص MBeans أو تستخدم بعض مخصص JMX الأدوات التي تسبب المشكلة.ولكن في نهاية المطاف أنا الاشتباه OrderClassLoader وربما الأحمر-الرنجة و المشكلة تكمن في مكان آخر (كسر GC أو تسرب).

نصائح أخرى

الملاحظات الفنية:نحن تشغيل الشمس JDK 1.6.0_07 ، 32 بت على لينكس 2.6.9 مربع.ترقية نسخة JDK لا حقا خيارا إلا إن هناك لا مفر منه ، السبب الرئيسي.

العديد من أحدث إصدارات جافا لديهم تحديثات CMS جامع البيانات المهملة.لا سيما 6u12, 6u14 ، 6u18.

أنا لست خبيرا مع GC الاشياء ولكن انا التخمين preclean إصلاحات في 6u14 قد إصلاح المشكلة ترونه.بالطبع أستطيع أن أقول نفس الشيء عن 6u18 الدرجة تفريغ البق.كما قلت أنا لست خبيرا في GC الأشياء.

هناك إصلاحات:

  • 6u10:(يؤثر 6u4+) CMS لم يوضح مرجعيات عندما -XX:+ParallelRefProcEnabled
  • 6u12:CMS:ترميز غير صحيحة من التحليق فوق كائن المصفوفات خلال المتزامنة precleaning
  • 6u12:CMS:غير صحيحة تجاوز التعامل عند استخدام متوازية متزامنة بمناسبة
  • 6u14:CMS:فشل في تأكيد "is_cms_thread == الموضوع::الحالي()->is_ConcurrentGC_thread()"
  • 6u14:CMS:تحتاج CMSInitiatingPermOccupancyFraction لبيرم ، طلاق من CMSInitiatingOccupancyFraction
  • 6u14:CMS تأكيد:_concurrent_iteration_safe_limit تحديث غاب
  • 6u14:CMS:غير صحيحة تجاوز المناولة خلال precleaning من قوائم المراجع
  • 6u14:SIGSEGV أو (!is_null(v),"oop قيمة لا يمكن أبدا أن يكون صفر") التأكيد عند تشغيل مع CMS و أقفاص
  • 6u14:CMS:Livelock في CompactibleFreeListSpace::block_size().
  • 6u14:جعل CMS العمل مع ضغط عفوا
  • 6u18:CMS:تفريغ الأساسية مع -XX:+UseCompressedOops
  • 6u18:CMS:الأخطاء المتعلقة الدرجة التفريغ
  • 6u18:CMS:ReduceInitialCardMarks غير آمنة في وجود cms precleaning
  • 6u18:[الانحدار] -XX:NewRatio مع -XX:+UseConcMarkSweepGC يسبب خطأ فادح
  • 6u20:بطاقة علامات يمكن تأجيلها طويلا

بالإضافة إلى كل ما سبق ، 6u14 عرض أيضا G1 جامع القمامة ، على الرغم من أنه لا يزال في الاختبار.G1 ويهدف إلى استبدال CMS في جافا 7.

G1 يمكن استخدامها في جافا 6u14 وأحدث مع رموز تبديل سطر الأوامر التالية:

-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC

وأود أن تبدأ مع شيء أبسط بكثير, مثل:

-server -Xms3072m -Xmx3072m -XX:+UseParallelOldGC -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps 

ومعرفة ما إذا كان هذا تلبي الاحتياجات الخاصة بك.

يبدو أنك بناء الأجسام التي تشير إلى أصحابها ( أ إلى نقطة ب نقاط ).هذه النتائج في إشارة التهم المتبقية أكبر من الصفر ، لذلك جامع القمامة لا يمكن تنظيفها.تحتاج إلى كسر دورة عند الإفراج عنهم.إبطال مرجعية إما A أو B سوف يحل المشكلة.يعمل هذا حتى في أكبر مرجع تبدو مثل ( A -> B> C> D> A).ناقلات وجوه المصفوفات يمكن استخدامها من قبل الخاصة بك HashMaps.

على بريسنس البعيد لوادر قد يشير إلى عدم تنظيف وإغلاق مراجع إلى الكائنات التي تم تحميلها عبر JNDI أو الوصول البعيد الأسلوب.

تحرير:أخذت نظرة ثانية في آخر الخط.قد ترغب في زيادة بيرم تخصيص.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top