[Java] كيفية إجبار جمع القمامة في جاوة؟


Answers

تحتوي مكتبة jlibs على فئة فائدة جيدة لجمع البيانات المهملة . يمكنك إجبار مجموعة البيانات المهملة باستخدام خدعة صغيرة WeakReference باستخدام كائنات WeakReference .

RuntimeUtil.gc() من jlibs:

   /**
    * This method guarantees that garbage collection is
    * done unlike <code>{@link System#gc()}</code>
    */
   public static void gc() {
     Object obj = new Object();
     WeakReference ref = new WeakReference<Object>(obj);
     obj = null;
     while(ref.get() != null) {
       System.gc();
     }
   }
Question

هل من الممكن إجبار جمع البيانات المهملة في Java ، حتى إذا كان من الصعب القيام بذلك؟ وأنا أعلم عن System.gc(); و Runtime.gc(); لكنهم يقترحون فقط القيام GC. كيف يمكنني فرض GC؟




هناك بعض الطرق غير المباشرة لإجبار جامع القمامة. تحتاج فقط إلى تعبئة كومة الذاكرة المؤقتة مع الكائنات المؤقتة حتى النقطة عند تنفيذ أداة تجميع مجمعي البيانات المهملة. لقد صنعت فصلا الذي يجبر جامع القمامة بهذه الطريقة:

class GarbageCollectorManager {

    private static boolean collectionWasForced;
    private static int refCounter = 0;

    public GarbageCollectorManager() {
        refCounter++;
    }

    @Override
    protected void finalize() {
        try {
            collectionWasForced = true;
            refCounter--;
            super.finalize();   
        } catch (Throwable ex) {
            Logger.getLogger(GarbageCollectorManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public int forceGarbageCollection() {
        final int TEMPORARY_ARRAY_SIZE_FOR_GC = 200_000;
        int iterationsUntilCollected = 0;
        collectionWasForced = false;

        if (refCounter < 2) 
            new GarbageCollectorManager();

        while (!collectionWasForced) {
            iterationsUntilCollected++;
            int[] arr = new int[TEMPORARY_ARRAY_SIZE_FOR_GC];
            arr = null;
        }

        return iterationsUntilCollected;
    }

}

الاستعمال:

GarbageCollectorManager manager = new GarbageCollectorManager();
int iterationsUntilGcExecuted = manager.forceGarbageCollection();

لا أعرف مدى فائدة هذه الطريقة ، لأنها تملأ الكومة باستمرار ، ولكن إذا كان لديك تطبيق مهم للمهمة والذي يجب أن يجبر GC - عندما يكون هذا هو طريقة جافا المحمولة لإجبار GC.







مفيدة للدفعة / crontab:

jdk1.7.0 / bin / jcmd GC.run




يتم أخذ الرمز التالي من أسلوب assertGC (...). يحاول إجبار جامع القمامة nondeterministic على جمع.

   List<byte[]> alloc = new ArrayList<byte[]>();
   int size = 100000;
   for (int i = 0; i < 50; i++) {
        if (ref.get() == null) {
             // Test succeeded! Week referenced object has been cleared by gc.
             return;
        }
        try {
             System.gc();
        } catch (OutOfMemoryError error) {
             // OK
        }
        try {
             System.runFinalization();
        } catch (OutOfMemoryError error) {
             // OK
        }

        // Approach the jvm maximal allocatable memory threshold
        try {
             // Allocates memory.
             alloc.add(new byte[size]);

             // The amount of allocated memory is increased for the next iteration.
             size = (int)(((double)size) * 1.3);
        } catch (OutOfMemoryError error) {
             // The amount of allocated memory is decreased for the next iteration.
             size = size / 2;
        }

        try {
             if (i % 3 == 0) Thread.sleep(321);
        } catch (InterruptedException t) {
             // ignore
        }
   }

   // Test failed! 

   // Free resources required for testing
   alloc = null;

   // Try to find out who holds the reference.
   String str = null;
   try {
        str = findRefsFromRoot(ref.get(), rootsHint);
   } catch (Exception e) {
        throw new AssertionFailedErrorException(e);
   } catch (OutOfMemoryError err) {
        // OK
   }
   fail(text + ":\n" + str);

المصدر (أضفت بعض التعليقات للوضوح): NbTestCase مثال




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

من المفترض أن يكون السؤال الذي تريد أن تطرحه هو "كيف يمكنني استعادة الذاكرة التي أعتقد أنني يجب أن أقوم باستردادها عن طريق جمع القمامة؟"




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




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

هذا صحيح ، فقط لفتة. لديك إلى حد كبير الإجابات القياسية التي قدمتها بالفعل العديد من الملصقات. لنأخذ هذا واحدا تلو الآخر:

  1. لم أستطع الحصول على هذه الشفرة في الواقع

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

  1. بعض قطعة من التعليمات البرمجية في النظام الكبير الخاص بي القيام بإنشاء الكائنات

ستفترض معظم الملصقات هنا أنك تقول إنك تعمل على واجهة ، وإذا كان الأمر كذلك ، فسيتعين علينا معرفة ما إذا كان يتم تسليم الكائن بأكمله أو عنصر واحد في كل مرة.

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

في أي وقت تحصل أنت أو أنا أو أي شخص آخر: " أرجوك أحتاج إلى ذلك بشكل فظيع. " هو تقريبا مقدمة عامة للتدمير شبه الكامل لما تحاول العمل عليه .... اكتب لنا رمز عينة صغير ، تطهير منه الشفرة الفعلية المستخدمة وتبين لنا سؤالك.

لا تشعر بالإحباط. غالباً ما يقرر ذلك أن dB الخاص بك يستخدم حزمة تم شراؤها في مكان ما ولا يتم تعديل التصميم الأصلي لهياكل البيانات الهائلة.

هذا شائع جدا.




.gc مرشح للتخلص في الإصدارات المستقبلية - علّق أحد مهندسي الشمس ذات مرة على أن أقل من عشرين شخصًا في العالم يعرفون كيف يستخدمون .gc () - لقد قمت ببعض العمل الليلة الماضية لبضع ساعات في وسط / حرج بنية البيانات باستخدام بيانات SecureRandom المولدة ، في مكان ما يتجاوز 40000 كائن ، قد يبطئ جهاز vm كما لو كان قد نفد من المؤشرات. ومن الواضح أنه كان يخنق على جداول مؤشر 16 بت وعرض سلوك "الآلية الفاشلة" الكلاسيكية.

حاولت -Xms وهلم جرا ، أبقى قليلا تويدل حتى أنها سوف تستمر نحو 57 ، شيء ما. ثم سيعمل gc الذهاب من القول 57،127 إلى 57،128 بعد gc () - حول سرعة وتيرة الشفرة في مخيم Easy Money.

يحتاج التصميم الخاص بك إلى إعادة عمل أساسية ، ربما نهج نافذة انزلاق.




(آسف ، لا يمكنني إضافة هذا كتعليق لأنني لا أملك نقاط سمعة كافية).

أنا مرة واحدة في مقابلة مع شركة معالجة الصور لوظيفة جافا (على الرغم من أنني لم يكن لديك أي تجربة جافا الكثير).

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

على ما أذكر ، انتهى بهم الأمر إلى إعادة تدوير الذاكرة بأنفسهم.