Будет ли сборщик мусора работать, если никакая программа java не запущена? [Дубликат]

Это затронет только небольшую часть пользователей, но я бы хотел, чтобы это было документировано для этой небольшой части. Из-за этой проблемы этот член этой маленькой горстки потратил 6 часов на устранение неполадок с работающим PHP-почтовым скриптом.

Если вы собираетесь в университет, в котором работает XAMPP с сайта www.AceITLab.com, вы должны знать, что наш профессор не сказал нам: брандмауэр AceITLab (а не брандмауэр Windows) блокирует MercuryMail в XAMPP , Вам придется использовать альтернативный почтовый клиент, груша работает на нас. Вам нужно будет отправить учетную запись Gmail с низкими настройками безопасности.

Да, я знаю, это абсолютно бесполезно для электронной почты реального мира. Однако, из того, что я видел, академические настройки и реальный мир часто имеют очень мало общего.

281
задан Vipin Jain 25 March 2016 в 06:46
поделиться

17 ответов

В общем, лучше не полагаться на finalize(), чтобы делать очистку и т. д.

Согласно Javadoc (что было бы полезно прочитать), это :

Вызывается сборщиком мусора на объекте, когда сбор мусора определяет, что больше нет ссылок на объект.

Как указал Йоахим, это может никогда не произойти в жизни программы, если объект всегда доступен.

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

229
ответ дан Paul Bellora 21 August 2018 в 06:27
поделиться
  • 1
    Другими словами (просто для уточнения для будущих читателей) его никогда не привлекают к основному классу, так как, когда основной класс закрывается, мусор не нужно собирать. ОС очищает все, что приложение использовало в любом случае. – Mark Jeronimus 7 May 2012 в 08:05
  • 2
    «не лучший метод для использования ... если не существует чего-то определенного, что вам нужно для« & quot; - Это предложение относится к 100% всего, так что это не полезно. Ответ Йоахима Зауэра намного лучше – B T 7 March 2013 в 23:37
  • 3
    @ Zom-B ваш пример полезен для пояснения, но для того, чтобы быть педантичным, предположительно, его можно было бы вызвать в основном классе, если основной класс создает поток не-демона, а затем возвращается? – Tom G 15 February 2014 в 23:24
  • 4
    Итак, каковы ситуации, когда finalize будет полезен? – nbro 21 May 2015 в 17:28
  • 5
    @MarkJeronimus - Собственно, это не имеет значения. Метод finalize() для основного класса вызывается, когда экземпляр & gt; & gt; & gt; & lt; класса - сбор мусора, а не когда основной метод завершается. И кроме того, основной класс мог собирать мусор до того, как приложение закончится; например в многопоточном приложении, где "основной" thread создает другие потоки, а затем возвращает. (На практике потребуется нестандартный загрузчик классов ....) – Stephen C 10 September 2016 в 07:51

Иногда, когда он уничтожается, объект должен совершить действие. Например, если объект имеет не-java-ресурс, такой как дескриптор файла или шрифт, вы можете проверить, освобождены ли эти ресурсы до уничтожения объекта. Для управления такими ситуациями java предлагает механизм, называемый «финализация». Завершая его, вы можете определить конкретные действия, которые происходят, когда объект собирается быть удален из сборщика мусора. Чтобы добавить финализатор в класс, просто определите метод finalize (). Время выполнения Java вызывает этот метод всякий раз, когда он собирается удалить объект этого класса. В рамках метода finalize () вы указываете действия, которые необходимо выполнить перед уничтожением объекта. Сборщик мусора периодически ищет объекты, которые больше не ссылаются ни на какое рабочее состояние, ни косвенно на любой другой объект со ссылкой. Перед выпуском актива среда выполнения Java вызывает метод finalize () объекта. Метод finalize () имеет следующий общий вид:

protected void finalize(){
    // This is where the finalization code is entered
}

С ключевым словом protected доступ к finalize () кодом вне его класса. Важно понимать, что finalize () вызывается непосредственно перед сборкой мусора. Он не вызывается, когда объект выходит из области, например. Это означает, что вы не можете знать, когда, или, если будет выполнен finalize () . В результате программа должна предоставлять другие средства для освобождения системных ресурсов или других ресурсов, используемых объектом. Вы не должны полагаться на finalize () для нормальной работы программы.

1
ответ дан Amarildo 21 August 2018 в 06:27
поделиться

метод finalize не гарантируется. Этот метод вызывается, когда объект становится подходящим для GC. Существует много ситуаций, когда объекты не могут быть собраны в мусор.

3
ответ дан Craig S. Anderson 21 August 2018 в 06:27
поделиться
  • 1
    Неправильно. Вы говорите, что объект завершается, когда он становится недоступным. Он фактически вызывается, когда метод фактически собран. – Stephen C 22 January 2017 в 01:12

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

В частности, finalize () вызывается, когда объект больше не используется. Но когда мы пытаемся назвать это, создавая новые объекты, нет уверенности в его вызове. Поэтому для уверенности мы создаем объект null c, который, очевидно, не имеет будущего использования, поэтому мы видим окончательный вызов объекта c.

Пример

class Car {

    int maxspeed;

    Car() {
        maxspeed = 70;
    }

    protected void finalize() {

    // Originally finalize method does nothing, but here we override finalize() saying it to print some stmt
    // Calling of finalize is uncertain. Difficult to observe so we force JVM to call it by System.gc(); GarbageCollection

        System.out.println("Called finalize method in class Car...");
    }
}

class Bike {

    int maxspeed;

    Bike() {
        maxspeed = 50;
    }

    protected void finalize() {
        System.out.println("Called finalize method in class Bike...");
    }
}

class Example {

    public static void main(String args[]) {
        Car c = new Car();
        c = null;    // if c weren`t null JVM wouldn't be certain it's cleared or not, null means has no future use or no longer in use hence clears it
        Bike b = new Bike();
        System.gc();    // should clear c, but not b
        for (b.maxspeed = 1; b.maxspeed <= 70; b.maxspeed++) {
            System.out.print("\t" + b.maxspeed);
            if (b.maxspeed > 50) {
                System.out.println("Over Speed. Pls slow down.");
            }
        }
    }
}

Выход

    Called finalize method in class Car...
            1       2       3       4       5       6       7       8       9
    10      11      12      13      14      15      16      17      18      19
    20      21      22      23      24      25      26      27      28      29
    30      31      32      33      34      35      36      37      38      39
    40      41      42      43      44      45      46      47      48      49
    50      51Over Speed. Pls slow down.
            52Over Speed. Pls slow down.
            53Over Speed. Pls slow down.
            54Over Speed. Pls slow down.
            55Over Speed. Pls slow down.
            56Over Speed. Pls slow down.
            57Over Speed. Pls slow down.
            58Over Speed. Pls slow down. 
            59Over Speed. Pls slow down.
            60Over Speed. Pls slow down.
            61Over Speed. Pls slow down.
            62Over Speed. Pls slow down.
            63Over Speed. Pls slow down.
            64Over Speed. Pls slow down.
            65Over Speed. Pls slow down.
            66Over Speed. Pls slow down.
            67Over Speed. Pls slow down.
            68Over Speed. Pls slow down.
            69Over Speed. Pls slow down.
            70Over Speed. Pls slow down.

Примечание. Даже после печати до 70 и после того, какой объект b не используется в программе, существует неопределенность в том, что b очищается или нет JVM, поскольку «Вызывается метод завершения в классе Bike ... "не печатается.

9
ответ дан cst1992 21 August 2018 в 06:27
поделиться
  • 1
    Вызов System.gc(); не является гарантией того, что сбор мусора будет фактически запущен. – Simon Forsberg 21 September 2015 в 08:31
  • 2
    Также не гарантируется, что будет выполняться kind коллекции. Соответственно, поскольку большинство Java-GC являются «поколением», коллекторы. – Stephen C 22 January 2017 в 01:29

Объект становится пригодным для сбора мусора или GC, если его невозможно достичь из любых живых потоков или любых статических рефренсов, другими словами, вы можете сказать, что объект становится пригодным для сбора мусора, если все его ссылки равны нулю. Циклические зависимости не считаются ссылкой, поэтому, если объект А имеет ссылку на объект B, а объект B имеет ссылку на объект A, и у них нет другой живой ссылки, то оба объекта A и B будут иметь право на сбор мусора. Как правило, объект становится пригодным для сбора мусора в Java в следующих случаях:

  1. Все ссылки этого объекта явно установлены на нуль, например. object = null
  2. Объект создается внутри блока, а ссылка выходит из области действия после того, как элемент управления выйдет из этого блока.
  3. Родительский объект установлен в значение null, если объект имеет ссылку на другой объект и когда вы устанавливаете ссылочный нулевой объект контейнерного объекта, дочерний или содержащий объект автоматически становится подходящим для сбора мусора.
  4. Если у объекта есть только живые ссылки через WeakHashMap, он будет иметь право на сбор мусора.
2
ответ дан Darin Kolev 21 August 2018 в 06:27
поделиться
  • 1
    Если поле final объекта используется неоднократно во время медленного вычисления, и объект никогда не будет использоваться после этого, будет ли объект сохранен в живых до тех пор, пока последний код не запросит это поле, или может JIT-копия поле во временную переменную, а затем отказаться от объекта перед вычислением? – supercat 27 April 2017 в 16:23
  • 2
    @supercat: оптимизатор может переписать код в форму, в которой объект не создается в первую очередь; в этом случае он может быть завершен сразу после завершения его конструктора, если синхронизация не заставит порядок между использованием объекта и финализатором. – Holger 4 May 2017 в 13:45
  • 3
    @Holger: В тех случаях, когда JIT может видеть все, что когда-либо произойдет с объектом между его созданием и отказом, я не вижу причин, по которым JIT должен запускать финализатор раньше. Реальный вопрос будет заключаться в том, что код должен делать, чтобы гарантировать, что финализатор не может запустить в рамках определенного метода. В .NET есть функция GC.KeepAlive(), которая ничего не делает, заставляя GC предполагать, что она может использовать объект, но я не знаю такой функции в Java. Для этой цели можно использовать переменную volatile, но использование переменной исключительно для такой цели представляется расточительным. – supercat 4 May 2017 в 16:28
  • 4
    @supercat: JIT не запускает финализацию, он просто упорядочивает код, чтобы не поддерживать ссылку, однако, возможно, было бы выгодно напрямую поставить в очередь FinalizerReference, чтобы он не нуждался в цикле GC, чтобы узнать, что ссылок нет. Синхронизация достаточно для обеспечения отношения происходит до ; поскольку финализация может (фактически) работать в другом потоке, она часто формально необходима в любом случае. Java 9 добавит Reference.reachabilityFence ... – Holger 4 May 2017 в 17:29
  • 5
    @Holger: Если JIT оптимизирует создание объекта, единственный Finalize будет вызван вообще, если бы JIT создал код, который сделал это напрямую. Предполагается ли, что код синхронизации будет ожидаться для объектов, которые ожидаются только в одном потоке? Если объект выполняет какие-либо действия, которые необходимо отменить, прежде чем он будет оставлен (например, открытие соединения сокета и получение эксклюзивного использования ресурса на другом конце), финализатор закрывает соединение, в то время как код по-прежнему использует сокет, будет катастрофой , Было бы нормально, если бы код использовал синхронизацию ... – supercat 4 May 2017 в 18:42

finalize() вызывается непосредственно перед сборкой мусора. Он не вызывается, когда объект выходит за рамки. Это означает, что вы не можете знать, когда или даже если будет выполняться finalize().

Пример:

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

0
ответ дан Fourat 21 August 2018 в 06:27
поделиться

Попробуйте запустить эту программу для лучшего понимания

public class FinalizeTest 
{       
    static {
        System.out.println(Runtime.getRuntime().freeMemory());
    }

    public void run() {
        System.out.println("run");
        System.out.println(Runtime.getRuntime().freeMemory());
    }

     protected void finalize() throws Throwable { 
         System.out.println("finalize");
         while(true)
             break;          
     }

     public static void main(String[] args) {
            for (int i = 0 ; i < 500000 ; i++ ) {
                    new FinalizeTest().run();
            }
     }
}
-3
ответ дан Fruchtzwerg 21 August 2018 в 06:27
поделиться

Java позволяет объектам реализовать метод finalize (), который может быть вызван.

метод finalize () вызывается, если сборщик мусора пытается собрать объект.

Если сборщик мусора не запускается, метод не вызывается.

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

На практике вы вряд ли сможете использовать его в реальных проектах.

Просто имейте в виду, что он не может быть вызван и что он определенно не будет дважды. Метод finalize () может начинаться с нуля или один раз.

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

Источник

0
ответ дан JavaDev 21 August 2018 в 06:27
поделиться

Метод finalize вызывается, когда объект собирается собирать мусор. Это может быть в любое время после того, как оно стало пригодным для сбора мусора.

Обратите внимание, что вполне возможно, что объект никогда не получает сбор мусора (и, таким образом, finalize никогда не вызывается). Это может произойти, когда объект никогда не станет подходящим для gc (поскольку он доступен на протяжении всего жизненного цикла JVM) или когда сбор мусора фактически не выполняется между временем, когда объект становится приемлемым, и временем, когда JVM перестает работать (это часто происходит с простым тестовые программы).

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

Если вы полагаетесь на finalize для правильной работы вашего приложения, то вы делаете что-то неправильно. finalize следует использовать только для очистки (обычно не Java) ресурсов. И это точно , потому что JVM не гарантирует, что finalize когда-либо вызывается на любом объекте.

340
ответ дан Joachim Sauer 21 August 2018 в 06:27
поделиться
  • 1
    Который из? У вас есть куча =) (Кроме того, я согласен. Не используйте финализаторы ... если вы полагаетесь на них, тогда ваш фундаментальный дизайн испорчен. Wether это слабость дизайна или сила, Java не имеет C ++ деструкторов). – mikek 24 March 2010 в 11:56
  • 2
    @Rajesh. Нет. Это не «продолжительность жизни». вопрос. Вы можете поместить свою программу в бесконечный цикл (в течение многих лет), и если сборщик мусора не нужен, он никогда не будет работать. – ChrisCantrell 25 September 2013 в 23:28
  • 3
    @VikasVerma: идеальная замена - ничто: вам не нужны. Единственный случай, когда это имеет смысл, - если ваш класс управляет каким-то внешним ресурсом (например, соединение TCP / IP, файл ... все, что не может обработать Java GC). В этих случаях интерфейс Closable (и идея за ним), вероятно, вы хотите: make .close() закрыть / отменить ресурс и потребовать от пользователя вашего класса позвонить ему в нужное время. Вы могли бы хотеть добавить метод finalize "только для сохранения", но это будет скорее инструмент отладки, чем фактическое исправление (потому что оно недостаточно надежное). – Joachim Sauer 13 June 2014 в 12:27
  • 4
    @Dragonborn: на самом деле это совсем другой вопрос, и его следует задавать отдельно. Есть крючки остановки, но они не гарантируются, если JVM неожиданно отключается (авария a.k.a.). Но их гарантии значительно сильнее, чем у финализаторов (и они более безопасны). – Joachim Sauer 13 February 2015 в 16:11
  • 5
    В последнем абзаце сказано использовать его только для очистки ресурсов, даже если нет гарантии, что он когда-либо будет вызван. Этот оптимизм говорит? Я бы предположил, что что-то ненадежное, так как это не подходит для очистки ресурсов. – Jeroen Vannevel 18 April 2015 в 12:20

В последнее время борясь с методами финализатора (чтобы избавиться от пулов соединений во время тестирования), я должен сказать, что финализатору не хватает многих вещей. Используя VisualVM для наблюдения, а также используя слабые ссылки для отслеживания фактического взаимодействия, я обнаружил, что в среде Java 8 выполняются следующие вещи (Oracle JDK, Ubuntu 15):

  • Finalize не вызывается немедленно Finalizer (GC part) индивидуально владеет эталоном неуловимо
  • По умолчанию сборщики пулов Garbage собирают недостижимые объекты
  • Finalize вызывается в массе, указывая на деталь реализации, что есть определенная фаза мусора сборщик освобождает ресурсы.
  • Calling System.gc () часто не приводит к тому, что объекты будут финализироваться чаще, это просто приводит к тому, что Finalizer быстрее узнает о недоступном объекте
  • Создание дампа потока почти всегда приводит к запуску финализатора из-за высокой накладной кучи во время выполнения дампа кучи или какого-либо другого внутреннего механизма
  • Швы финализации должны быть связаны требованиями памяти (освободить больше памяти) или список объектов, помеченных для финализации рост определенного внутреннего предела. Поэтому, если у вас есть много объектов, которые будут завершены, фаза завершения будет срабатывать чаще и раньше по сравнению с несколькими
  • . Были обстоятельства, при которых System.gc () запускает финализацию напрямую, но только если ссылка была местной и короткой жизнью. Это может быть связано с генерацией.

Final Thought

Метод Finalize ненадежен, но может использоваться только для одной вещи. Вы можете убедиться, что объект был закрыт или удален до сбора мусора, что позволяет реализовать отказоустойчивость, если обрабатываются объекты с более сложным жизненным циклом, включающие действие с истекшим сроком действия. Именно по этой причине я могу думать, что это стоит того, чтобы переопределить его.

4
ответ дан Martin Kersten 21 August 2018 в 06:27
поделиться

Класс, где мы переопределяем метод finalize

public class TestClass {    
    public TestClass() {
        System.out.println("constructor");
    }

    public void display() {
        System.out.println("display");
    }
    @Override
    public void finalize() {
        System.out.println("destructor");
    }
}

Шансы на метод finalize, который вызывается

public class TestGarbageCollection {
    public static void main(String[] args) {
        while (true) {
            TestClass s = new TestClass();
            s.display();
            System.gc();
        }
    }
}

, когда память перегружена объектами дампа, gc вызовет метод завершения

запустите и посмотрите консоль, где вы не часто вызываете метод finalize, когда память перегружается, тогда вызывается метод finalize.

1
ответ дан Meet Doshi 21 August 2018 в 06:27
поделиться

finalize будет распечатывать счетчик для создания класса.

protected void finalize() throws Throwable {
    System.out.println("Run F" );
    if ( checkedOut)
        System.out.println("Error: Checked out");
        System.out.println("Class Create Count: " + classCreate);
}

main

while ( true) {
    Book novel=new Book(true);
    //System.out.println(novel.checkedOut);
    //Runtime.getRuntime().runFinalization();
    novel.checkIn();
    new Book(true);
    //System.runFinalization();
    System.gc();

Как вы можете видеть. Следующий вывод показывает, что gc был выполнен в первый раз, когда число классов равно 36.

C:\javaCode\firstClass>java TerminationCondition
Run F
Error: Checked out
Class Create Count: 36
Run F
Error: Checked out
Class Create Count: 48
Run F
5
ответ дан OnaBai 21 August 2018 в 06:27
поделиться

Выйти Эффективная Java, страница 2-го издания 27. Пункт 7: Избегайте финализаторов

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

Чтобы завершить работу ресурса, вместо этого используйте try-finally:

// try-finally block guarantees execution of termination method
Foo foo = new Foo(...);
try {
    // Do what must be done with foo
    ...
} finally {
    foo.terminate(); // Explicit termination method
}
19
ответ дан rmtheis 21 August 2018 в 06:27
поделиться

Метод Java finalize() не является деструктором и не должен использоваться для обработки логики, от которой зависит ваше приложение. Спецификация Java заявляет, что нет гарантии, что метод finalize вызывается вообще во время жизни приложения.

То, что вы, вероятно, хотите, это комбинация finally и метода очистки, как в :

MyClass myObj;

try {
    myObj = new MyClass();

    // ...
} finally {

    if (null != myObj) {
        myObj.cleanup();
    }
}
21
ответ дан rsp 21 August 2018 в 06:27
поделиться

Когда метод finalize() вызывается в Java?

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

  • Если объект никогда не становится недоступным, finalize() никогда не будет вызываться на нем.
  • Если GC не запускается, finalize() никогда не может быть вызвана. (Обычно GC работает только тогда, когда JVM решает, что, вероятно, будет достаточно мусора, чтобы сделать его стоящим.)
  • Может потребоваться более одного цикла GC до того, как GC определит, что конкретный объект недоступен. (Java-GC, как правило, являются «генераторными» коллекторами ...)
  • Как только GC обнаруживает, что объект недоступен и финализирован, он помещается в очередь финализации.

(Фактическая спецификация JVM позволяет JVM в never запускать финализаторы ... при условии, что что он не восстанавливает пространство, используемое объектами. JVM, который был реализован таким образом, будет искалечен / бесполезен, но это поведение «разрешено».)

В результате получается, что это неразумно полагаться на завершение, чтобы делать то, что нужно делать в определенные сроки. Это «лучшая практика», чтобы не использовать их вообще. Должен быть лучший (то есть более надежный) способ делать то, что вы пытаетесь сделать в методе finalize().

Единственное законное использование для финализации - очистка ресурсов, связанных с объектами, которые были потеряны кодом приложения. Даже тогда вы должны попытаться написать код приложения, чтобы он не потерял объекты в первую очередь. (Например, используйте Java 7+ try-with-resources , чтобы гарантировать, что close() всегда вызывается ...)


Я создал тест класс, который записывает в файл, когда метод finalize () вызывается путем его переопределения. Он не выполнен. Может ли кто-нибудь сказать мне причину, по которой он не выполняется?

Трудно сказать, но есть несколько возможностей:

  • Объект не
  • Объект не собирает мусор, потому что GC не запускается до завершения вашего теста.
  • Объект найден GC и помещен в завершение очереди GC, но до завершения теста завершение не завершено.
15
ответ дан Stephen C 21 August 2018 в 06:27
поделиться
protected void finalize() throws Throwable {}
  • каждый класс наследует метод finalize() из java.lang.Object
  • , метод вызывается сборщиком мусора, когда он не определяет больше ссылок на объект exist
  • Метод finalize объекта не выполняет никаких действий, но может быть переопределен любым классом
  • , как правило, он должен быть переопределен для очистки ресурсов, отличных от Java, т.е. закрытие файла
  • , если переопределить finalize(), хорошая практика программирования - использовать инструкцию try-catch-finally и всегда вызывать super.finalize(). Это мера безопасности, обеспечивающая непреднамеренное пропущение закрытия ресурса, используемого объектами, вызывающими класс
    protected void finalize() throws Throwable {
         try {
             close();        // close open files
         } finally {
             super.finalize();
         }
     }
    
  • . Любое исключение, созданное finalize() во время сбора мусора, останавливает завершение, но в противном случае игнорируется
  • finalize() никогда не запускается более одного раза на любом объекте

, указанном по адресу: http://www.janeg.ca/scjp/ gc / finalize.html

Вы также можете проверить эту статью:

66
ответ дан XpiritO 21 August 2018 в 06:27
поделиться
  • 1
    Статья JavaWorld, ссылка на которую вы ссылаетесь, находится с 1998 года, и имеет некоторые интересные советы, в частности предложение о том, что один вызов System.runFinalizersOnExit () обеспечивает выполнение финализаторов до выхода JVM. Этот метод в настоящее время не рекомендуется, с комментарием «Этот метод по своей сути является небезопасным. Это может привести к тому, что финализаторы будут вызываться для живых объектов, в то время как другие потоки одновременно манипулируют этими объектами, что приводит к неустойчивому поведению или взаимоблокировке ». Поэтому я не буду этого делать. – Greg Chabala 14 June 2011 в 18:12
  • 2
    Поскольку runFinalizerOnExit () не является потокобезопасным, то что можно сделать, это Runtime.getRuntime (). AddShutdownHook (new Thread () {public void run () {destroyMyEnclosingClass ();}}); в конструкторе Класса. – Ustaman Sangat 24 July 2012 в 22:49
  • 3
    @Ustaman Sangat Это способ сделать это, но помните, что он устанавливает ссылку на ваш экземпляр из shutdownHook, что в значительной степени гарантирует, что ваш класс никогда не будет собирать мусор. Другими словами, это утечка памяти. – pieroxy 18 June 2013 в 17:32
  • 4
    @pieroxy, в то время как я соглашаюсь с тем, что все остальные здесь не используют finalize () для чего-либо, я не понимаю, почему должна быть ссылка от крюка остановки. Можно было бы получить мягкую ссылку. – Ustaman Sangat 19 June 2013 в 22:42
0
ответ дан Praveen Kishor 1 November 2018 в 01:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: