احتمالية حدوث تسرب للذاكرة في عدد الفئات المحملة في تطبيق Java

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

  •  03-07-2019
  •  | 
  •  

سؤال

لقد بدأت مؤخرًا في إنشاء ملف تعريف لتطبيق osgi java الذي أكتبه باستخدام VisualVM.شيء واحد لاحظته هو أنه عندما يبدأ التطبيق في إرسال البيانات إلى العميل (عبر JMS)، يبدأ عدد الفئات المحملة في الزيادة بمعدل ثابت.ومع ذلك، يبقى حجم الكومة وحجم PermGen ثابتين.لا ينخفض ​​عدد الفئات أبدًا، حتى بعد توقف إرسال البيانات.هل هذا تسرب في الذاكرة؟أعتقد ذلك، لأنه يجب تخزين الفئات المحملة في مكان ما، إلا أن الكومة والتكوين لا يزيدان أبدًا حتى بعد تشغيل التطبيق لعدة ساعات.

للحصول على لقطة شاشة لتطبيق التنميط الخاص بي، اذهب هنا

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

المحلول

<اقتباس فقرة>   

هل حيوي إنشاء فئات جديدة على الطاير بطريقة أو بأخرى؟

وشكرا لمساعدتكم. فكنت أحسب ما هي المشكلة. في واحدة من دروسي، كنت تستخدم JAXB لخلق سلسلة XML. في القيام بذلك، JAXB ueses انعكاس لإنشاء فئة جديدة.

JAXBContext context = JAXBContext.newInstance(this.getClass());

وهكذا على الرغم من أن JAXBContext لم يقل حولها في كومة، تم تحميل الطبقات.

ولقد واجه برنامجي مرة أخرى، وأنا أرى هضبة طبيعية كما كنت تتوقع.

نصائح أخرى

أنا على استعداد للمراهنة على أن مشكلتك مرتبطة بإنشاء الكود الثانوي.

تستخدم العديد من المكتبات CGLib أو BCEL أو Javasist أو Janino لإنشاء كود ثانوي للفئات الجديدة في وقت التشغيل ثم تحميلها من أداة تحميل الفئات التي يتم التحكم فيها.الطريقة الوحيدة لتحرير هذه الفئات هي تحرير كافة المراجع إلى أداة تحميل الفصل.

نظرًا لأن كل فئة تحتفظ بمحمل الفصل، فهذا يعني أيضًا أنه لا يجب عليك إصدار المراجع لجميع الفئات أيضًا [1].يمكنك التقاطها باستخدام ملف تعريف لائق (أنا أستخدم Yourkit - ابحث عن مثيلات متعددة لأداة تحميل الفصل بنفس الحجم المحتفظ به)

إحدى المشاكل هي أن JVM لا يقوم بإلغاء تحميل الفئات بشكل افتراضي (السبب هو التوافق مع الإصدارات السابقة - حيث يفترض الأشخاص (خطأ) أنه سيتم تنفيذ أدوات التهيئة الثابتة مرة واحدة فقط.والحقيقة هي أنه يتم تنفيذها في كل مرة يتم فيها تحميل الفصل.) لتمكين التفريغ، يجب عليك تمرير بعض الخيارات التالية:

-XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled

(تم اختباره باستخدام JDK 1.5)

وحتى في هذه الحالة، لا يعد إنشاء الكود الثانوي المفرط فكرة جيدة، لذا أقترح عليك البحث في الكود الخاص بك للعثور على الجاني وتخزين الفئات التي تم إنشاؤها مؤقتًا.المخالفون المتكررون هم لغات البرمجة النصية، أو الوكلاء الديناميكيون (بما في ذلك تلك التي تم إنشاؤها بواسطة خوادم التطبيقات) أو نموذج السبات الضخم (في هذه الحالة يمكنك فقط زيادة بيرمجين الخاص بك).

أنظر أيضا:

  1. http://blogs.Oracle.com/watt/resource/jvm-options-list.html
  2. http://blogs.Oracle.com/jonthecollector/entry/presenting_the_permanent_generation
  3. http://forums.sun.com/thread.jspa?messageID=2833028

قد تجد بعض إشارات النقاط الساخنة مفيدة في فهم هذا السلوك مثل:

  • -XX:+TraceClassLoading
  • -XX:+TraceClassUnloading

وهذا مرجع جيد:

http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp

ما لم أسيء الفهم، فإننا ننظر هنا إلى الفئات المحملة، وليس المثيلات.

عندما تشير التعليمات البرمجية الخاصة بك إلى فصل دراسي لأول مرة، يقوم JVM بإخراج ClassLoader وجلب المعلومات حول الفصل من ملف .class أو ما شابه.

لست متأكدًا من الظروف التي سيتم فيها تفريغ الفصل الدراسي.بالتأكيد لا ينبغي أبدًا إلغاء تحميل أي فصل بمعلومات ثابتة.

لذلك أتوقع نمطًا مثل نمطك تقريبًا، حيث أنه أثناء تشغيل التطبيق الخاص بك، فإنه ينتقل إلى مناطق ويشير إلى فئات جديدة، وبالتالي فإن عدد الفئات المحملة سيرتفع أكثر فأكثر.

ولكن يبدو لي أمرين غريبين:

  1. لماذا هو خطي جدا؟
  2. لماذا لا هضبة؟

أتوقع أن يتجه نحو الأعلى، ولكن في خط متذبذب، ثم يتضاءل مع الزيادة حيث قام JVM بالفعل بتحميل معظم الفئات التي يشير إليها برنامجك.أعني أن هناك عددًا محدودًا من الفئات المشار إليها في معظم التطبيقات.

هل تقوم بإنشاء فئات جديدة ديناميكيًا أثناء التنقل بطريقة أو بأخرى؟

أود أن أقترح تشغيل تطبيق اختبار أبسط من خلال نفس مصحح الأخطاء للحصول على حالة أساسية.بعد ذلك، يمكنك التفكير في استخدام ClassLoader الخاص بك والذي يقدم بعض معلومات تصحيح الأخطاء، أو ربما تكون هناك أداة للإبلاغ عنه.

تحتاج إلى معرفة ما هي هذه الفئات التي يتم تحميلها.

نعم، انها عادة ما تسرب الذاكرة (لأننا لا نتعامل حقا مع الذاكرة مباشرة، انها أكثر من تسرب مثيل فئة). لقد مرت هذه العملية قبل وعادة انها بعض المستمع إضافة إلى مجموعة أدوات القديمة التي لم إزالته النفس.

في كود كبار السن، ويسبب وجود علاقة المستمع "المستمع" الكائن على البقاء حولها. وأود أن ننظر في الأدوات القديمة أو تلك التي لم تكن من خلال العديد من الدورات. ومن شأن أي مكتبة موجودة منذ فترة طويلة يعمل على JDK لاحق معرفة الأشياء إشارة الذي يزيل الحاجة إلى "إزالة المستمع".

وبالإضافة إلى ذلك، استدعاء التخلص على ويندوز الخاص بك إذا كنت إعادة لهم في كل مرة. أنا لا أعتقد أنهم أي وقت مضى الذهاب بعيدا إذا لم تفعل ذلك (في الواقع هناك أيضا التصرف على إعداد وثيقة).

لا تقلق بشأن سوينغ أو المستمعين JDK، وينبغي أن جميع الإشارات استخدام لذلك يجب أن يكون بخير.

واستخدم الكسوف الذاكرة محلل للتحقق من وجود الطبقات المكررة وتسرب الذاكرة. قد يحدث أن نفس الفئة يحصل على تحميل أكثر من مرة.

والتحيات، ماركوس

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