Как заставить сборку мусора на Java?

Можно ли принудительно вывести сборку мусора на Java, даже если это сложно? Я знаю о System.gc(); и Runtime.gc(); но они предлагают только GC. Как я могу заставить GC?

Ответ 1

Ваш лучший вариант - позвонить System.gc(), который просто является подсказкой сборщику мусора, который вы хотите, чтобы он собирал коллекцию. Не существует способа принудительного и непосредственного сбора, поскольку сборщик мусора является недетерминированным.

Ответ 2

Библиотека jlibs имеет хороший служебный класс для сборки мусора. Вы можете форсировать сборку мусора, используя хитрый трюк с объектами 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();
     }
   }

Ответ 3

Лучший (если не единственный) способ заставить GC - написать пользовательскую JVM. Я считаю, что сборщики мусора являются подключаемыми, так что вы можете просто выбрать одну из доступных реализаций и настроить ее.

Примечание: это не простой ответ.

Ответ 5

ДА почти невозможно заставить вас звонить методам в том же порядке и в то же время это:

System.gc ();
System.runFinalization ();

даже если это всего лишь один объект для очистки использования этих двух методов, в то же время заставляет сборщик мусора использовать метод finalise() недоступного объекта, освобождающего выделенную память и выполняющую то, что заявляет метод finalize().

ОДНАКО, это ужасная практика использования сборщика мусора, поскольку его использование может привести к перегрузке программного обеспечения, которое может быть даже хуже, чем в памяти, сборщик мусора имеет свои собственные поток, который невозможно контролировать плюс в зависимости от алгоритма, используемого gc, может занять больше времени и считается очень неэффективным, вы должны проверить свое программное обеспечение, если это худшее с помощью gc, потому что оно определенно сломано, хорошее решение должно не зависит от gc.

ПРИМЕЧАНИЕ:, чтобы иметь в виду, что это будет работать только в том случае, если метод finalize не переназначает объект, если это произойдет, объект будет продолжать жить, он будет иметь воскрешение, которое технически возможно.

Ответ 6

В документации для OutOfMemoryError объявляется, что она не будет выбрана, если VM не восстановит память после полной сборки мусора, Поэтому, если вы продолжаете распределять память до тех пор, пока не получите ошибку, вы уже заставите полную сборку мусора.

Предположительно, вопрос, который вы действительно хотели задать, - "как я могу вернуть память, которую, я думаю, должен вернуть на сборку мусора?"

Ответ 7

Чтобы вручную запросить GC (не из System.gc()):

  • Перейти к: папка bin в JDK например.-C:\Program Files\Java\jdk1.6.0_31\bin
  • Откройте jconsole.exe
  • Подключитесь к желаемому локальному процессу.
  • Перейдите на вкладку "Память" и нажмите "Выполнять GC".

Ответ 8

.gc является кандидатом на устранение в будущих выпусках - Sun Engineer однажды прокомментировал, что, возможно, менее двадцати человек в мире действительно знают, как использовать .gc() - Я проделал некоторую работу прошлой ночью в течение нескольких часов на центральную/критическую структуру данных с использованием данных SecureRandom, где-то около 40 000 объектов, vm замедлялся, как если бы у них закончились указатели. Очевидно, что он задыхался от 16-битных таблиц указателей и демонстрировал классическое поведение "сбоев в работе".

Я попробовал -Xms и т.д., держал бит, скручивающийся до тех пор, пока он не достигнет примерно 57, ххх. Затем он будет запускать gc, скажем, от 57 127 до 57 128 после gc() - примерно в темпе кодового раздувания в лагере Easy Money.

Ваш дизайн нуждается в фундаментальной переработке, возможно, в скользящем оконном подходе.

Ответ 10

Спецификация JVM не говорит ничего конкретного о сборке мусора. Благодаря этому поставщики могут свободно внедрять GC на своем пути.

Таким образом, эта неопределенность вызывает неопределенность в поведении мусора. Вы должны проверить данные JVM, чтобы узнать о подходах/алгоритмах сбора мусора. Также есть варианты настройки поведения.

Ответ 11

Если вам нужно принудительно собрать сбор мусора, возможно, вам стоит подумать над тем, как вы управляете ресурсами. Вы создаете большие объекты, которые сохраняются в памяти? Вы создаете большие объекты (например, графические классы), которые имеют интерфейс Disposable и не вызывают dispose(), когда это делается? Вы объявляете что-то на уровне класса, которое вам нужно только в рамках одного метода?

Ответ 12

Было бы лучше, если бы вы описали причину, почему вам нужна сборка мусора. Если вы используете SWT, вы можете распоряжаться ресурсами, такими как Image и Font, чтобы освободить память. Например:

Image img = new Image(Display.getDefault(), 16, 16);
img.dispose();

Существуют также инструменты для определения нераспределенных ресурсов.

Ответ 13

На самом деле, я не понимаю тебя. Но чтобы быть ясным в "Создании бесконечных объектов", я имел в виду, что в моей большой системе есть какой-то фрагмент кода, создающий объекты, которые обрабатывают и живые в памяти, на самом деле я не мог получить этот фрагмент кода, просто жест!

Это правильно, только жест. У вас есть почти стандартные ответы, которые уже даны несколькими авторами. Давайте возьмем это по одному:

  1. Я не мог получить этот кусок кода на самом деле

Правильно, фактического jvm нет - такова только спецификация, связка компьютерных наук, описывающая желаемое поведение... Недавно я начал копать инициализацию объектов Java из нативного кода. Чтобы получить то, что вы хотите, единственный способ сделать то, что называется агрессивным обнулением. Ошибки, если они сделаны неправильно, настолько плохи, что мы должны ограничиться первоначальным объемом вопроса:

  1. какой-то кусок кода в моей большой системе делает создание объектов

Большинство постеров здесь предполагают, что вы говорите, что работаете с интерфейсом, если это так, мы должны были бы посмотреть, передается ли вам весь объект или один предмет за раз.

Если вам больше не нужен объект, вы можете присвоить объекту нулевое значение, но если вы ошиблись, возникнет исключение нулевого указателя. Бьюсь об заклад, вы можете добиться лучшей работы, если вы используете NIO

Каждый раз, когда вы, я или кто-то еще получаете: "Пожалуйста, мне это ужасно нужно". это почти универсальный предшественник почти полного уничтожения того, над чем вы пытаетесь работать... напишите нам небольшой пример кода, очистите от него любой используемый код и покажите нам свой вопрос.

Не расстраивайся. Часто это решает то, что ваш dba использует купленный где-то пакет, и оригинальный дизайн не настроен для массивных структур данных.

Это очень распространено.

Ответ 14

Если у вас заканчивается память и вы получаете OutOfMemoryException, вы можете попытаться увеличить количество кучи, доступное для java, запустив программу с помощью java -Xms128m -Xmx512m вместо просто java. Это даст вам начальный размер кучи 128 МБ и максимум 512 Мб, что намного больше, чем стандартный 32 МБ /128 МБ.

Ответ 15

(Извините, я не могу добавить это как комментарий, так как у меня недостаточно очков репутации.)

Я когда-то брал интервью у компании по обработке изображений для Java-работы (хотя у меня не было никакого опыта java.)

Их рассказ о горе, который был мне интересен, заключался в том, что их программа выделила бы БОЛЬШОЙ буфер для изображения. Однажды, они были сделаны с изображением и памятью, они будут уважать его. Зная, что им действительно нужно восстановить память раньше, чем позже, они попытались использовать явный вызов Java gc() в течение тихого времени программы. К сожалению, gc() является всего лишь предложением для среды выполнения Java и не имеет никакого эффекта.

Как я помню, им пришлось перерабатывать память.

Ответ 16

Вы можете попробовать использовать Runtime.getRuntime().gc() или использовать служебный метод System.gc() Примечание. Эти методы не гарантируют GC. И их область действия должна быть ограничена JVM, а не программно обрабатывать его в вашем приложении.

Ответ 17

Другой вариант - не создавать новые объекты.

Объединение объектов не требуется, чтобы уменьшить необходимость GC в Java.

Пул объектов обычно не будет быстрее создания объектов (особенно для легких объектов), но он быстрее, чем сборщик мусора. Если вы создали 10000 объектов, и каждый объект был 16 байтов. Эти 160 000 байтов GC должен восстановить. С другой стороны, если вам не нужны все 10000 одновременно, вы можете создать пул для переработки/повторного использования объектов, что устраняет необходимость в создании новых объектов и устраняет необходимость в GC старых объектов.

Как то так (не проверено). И если вы хотите, чтобы он был потокобезопасным, вы можете поменять LinkedList на ConcurrentLinkedQueue.

public abstract class Pool<T> {
    private int mApproximateSize;
    private LinkedList<T> mPool = new LinkedList<>();

    public Pool(int approximateSize) {
        mApproximateSize = approximateSize;
    }

    public T attain() {
        T item = mPool.poll();
        if (item == null) {
            item = newInstance();
        }
        return item;
    }

    public void release(T item) {
        int approxSize = mPool.size(); // not guaranteed accurate
        if (approxSize < mApproximateSize) {
            recycle(item);
            mPool.add(item);
        } else if (approxSize > mApproximateSize) {
            decommission(mPool.poll());
        }
    }

    public abstract T newInstance();

    public abstract void recycle(T item);

    public void decommission(T item) { }

}

Ответ 18

В OracleJDK 10 с G1 GC один вызов System.gc() заставит GC очистить старую коллекцию. Я не уверен, что GC запускается немедленно. Однако GC не будет очищать коллекцию Young, даже если System.gc() вызывается много раз в цикле. Чтобы заставить GC очистить коллекцию Young, вы должны выделить в цикле (например, new byte[1024]) без вызова System.gc(). Вызов System.gc() по какой-то причине не позволяет GC очистить коллекцию Young.

Ответ 19

FYI

Вызов метода System.runFinalizersOnExit(true) гарантирует, что методы финализатора вызывается до того, как Java выключится. Однако этот метод по своей сути является небезопасным и он устарел. Альтернативой является добавление "крюков остановки" с помощью метода Runtime.addShutdownHook.

Масаррат Сиддики

Ответ 20

Существует некоторый косвенный способ форсирования сборщика мусора. Вам просто нужно заполнить кучу временными объектами до момента, когда будет выполнен сборщик мусора. Я создал класс, который таким образом заставляет сборщик мусора:

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 - когда это может быть переносимый Java-способ ГХ.

Ответ 21

Я хотел бы добавить кое-что здесь. Пожалуйста, не то, что Java работает на виртуальной машине, а не на самом деле. Виртуальная машина имеет свой собственный способ связи с машиной. Он может изменяться от системы к системе. Теперь, когда мы вызываем GC, мы просим виртуальную машину Java вызвать сборщик мусора.

Так как сборщик мусора с виртуальной машиной, мы не можем заставить его делать очистку там и тогда. Скорее, мы заказываем наш запрос с Мусороуборочной машиной. Это зависит от виртуальной машины, после определенного времени (это может измениться из системы в систему, как правило, когда пороговая память, выделенная для JVM, заполнена), фактическая машина освободит пространство.: D

Ответ 22

Следующий код берется из метода assertGC (...). Он пытается заставить собирать сборщик недетерминированных мусора.

   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

Ответ 23

Если вы используете JUnit и Spring, попробуйте добавить это в каждый тестовый класс:

@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)

Ответ 24

Лучшим (если не единственным) способом заставить GC было бы написать пользовательский JVM. Я считаю, что Garbage collectors подключается, поэтому вы можете просто выбрать одну из доступных реализаций, чтобы настроить ее.