Почему там финализаторы в Java и c#?

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

11
задан RCIX 5 December 2009 в 01:31
поделиться

8 ответов

Что ж, они невероятно полезны в определенных ситуациях.

В .NET CLR, например:

  • не гарантируется запуск

Финализатор всегда, в конце концов, , запустить, если программа не убита. Это просто не детерминировано относительно того, когда он будет запущен.

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

Это верно, однако они все еще работают.

В .NET это очень и очень полезно. В .NET довольно распространено оборачивать собственные ресурсы, не относящиеся к .NET, в класс .NET. Реализуя финализатор, вы можете гарантировать, что собственные ресурсы очищены правильно. Без этого пользователь был бы вынужден вызвать метод для выполнения очистки, что резко снизило бы эффективность сборщика мусора.

It ' Не всегда легко узнать, когда именно освободить ваши (собственные) ресурсы - реализовав финализатор, вы можете гарантировать, что они будут очищены правильно, даже если ваш класс используется не совсем идеально.

  • и (по крайней мере, в java) они вызывают поразительно большой удар по производительности, даже если придерживаться класса

. Опять же, сборщик мусора .NET CLR имеет здесь преимущество. Если вы реализуете правильный интерфейс ( IDisposable ), И если разработчик реализует его правильно, вы можете предотвратить дорогостоящую часть завершения. Это делается так, что определяемый пользователем метод очистки может вызывать GC.SuppressFinalize , который обходит финализатор.

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

16
ответ дан 3 December 2019 в 01:53
поделиться

Хмя, вы получаете картину, нарисованную здесь слишком радужно. Также не гарантируется работа финализаторов в .NET. Типичными ошибками являются финализатор, который генерирует исключение или тайм-аут в потоке финализатора (2 секунды).

Это было проблемой, когда Microsoft решила предоставить поддержку хостинга .NET в SQL Server. Тип приложения, в котором перезапуск приложения для устранения утечек ресурсов не считается жизнеспособным решением. В .NET 2.0 появились критические финализаторы, которые стали производными от класса CriticalFinalizerObject. Финализатор такого класса должен придерживаться правила областей ограниченного выполнения (CER), по сути, области кода, в которой подавляются исключения. Возможности, которые вы можете делать в CER, очень ограничены.

Возвращаясь к исходному вопросу, финализаторы необходимы для освобождения ресурсов операционной системы, кроме памяти. Сборщик мусора очень хорошо управляет памятью, но ничего не делает для освобождения перьев, кистей, файлов, сокетов, окон, каналов и т. Д. Когда объект использует такой ресурс, он должен убедиться, что освободил ресурс после того, как это будет сделано с помощью Это. Финализаторы гарантируют, что это произойдет, даже если программа забыла это сделать. Вы почти никогда не пишете класс с финализатором самостоятельно, операционные ресурсы обертываются классами в структуре.

В .NET framework также есть шаблон программирования, обеспечивающий ранний выпуск такого ресурса, поэтому ресурс не задерживается до тех пор, пока финализатор запускается. Все классы, у которых есть финализаторы, также реализуют метод IDisposable.Dispose (), позволяющий вашему коду явно освобождать ресурс. Об этом часто забывают. NET, но обычно это не вызывает проблем, потому что финализатор гарантирует, что в конечном итоге это будет сделано. Многие программисты .NET потеряли часы сна, беспокоясь о том, позаботятся ли обо всех вызовах Dispose (), и на форумах было запущено огромное количество потоков по этому поводу. Люди, занимающиеся Java, должны быть счастливее.


В продолжение вашего комментария: исключения и тайм-ауты в потоке финализатора - это то, о чем вам не нужно беспокоиться. Во-первых, если вы обнаружите, что пишете финализатор, сделайте глубокий вдох и спросите себя, на правильном ли вы пути. Финализаторы предназначены для классов фреймворка, вы должны использовать такой класс для использования рабочего ресурса, вы получите финализатор, встроенный в этот класс, бесплатно. Вплоть до классов SafeHandle у них есть критический финализатор.

Во-вторых, сбои потоков финализатора - грубые сбои программы. Подобно получению исключения OutOfMemory или спотыканию о шнур питания и отключению устройства от сети. Вы ничего не можете с ними поделать, кроме как исправить ошибку в коде или перенаправить кабель. Для Microsoft было важно разработать критически важные финализаторы, они не могут полагаться на всех программистов, которые пишут код .NET для SQL Server, чтобы получить правильный код. Если вы сами нащупаете финализатор, то такой ответственности не возникнет, заказчик позвонит вам, а не Microsoft.

Для Microsoft было важно разработать критически важные финализаторы, они не могут полагаться на всех программистов, которые пишут код .NET для SQL Server, чтобы получить правильный код. Если вы сами возитесь с финализатором, то такой ответственности не будет, заказчик позвонит вам, а не Microsoft.

Для Microsoft было важно разработать критически важные финализаторы, они не могут полагаться на всех программистов, которые пишут код .NET для SQL Server, чтобы получить правильный код. Если вы сами нащупаете финализатор, то такой ответственности не возникнет, заказчик позвонит вам, а не Microsoft.

10
ответ дан 3 December 2019 в 01:53
поделиться

Если вы читаете JavaDoc для finalize (), он говорит, что он «Вызывается сборщиком мусора на объекте, когда сборщик мусора определяет, что больше нет ссылок на объект. Подкласс отменяет метод finalize для удаления системных ресурсов или выполнения другой очистки. "

http://java.sun.com/javase/6/docs/api/java/lang/Object.html#finalize

Итак, "Почему". Думаю, вы можете поспорить, эффективна ли их реализация.

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

class MyResource {
    private Throwable allocatorStack;

    public MyResource() {
        allocatorStack = new RuntimeException("trace to allocator");
    }

    @Override
    protected void finalize() throws Throwable {
        try {
            System.out.println("Bug!");
            allocatorStack.printStackTrace();
        } finally {
            super.finalize();
        }
    }
 }
4
ответ дан 3 December 2019 в 01:53
поделиться

В java существуют финализаторы, позволяющие очистить внешние ресурсы (вещи, которые существуют за пределами JVM и не могут быть собраны мусором, когда есть «родительский» объект java) . Это всегда было редкостью. Например, это может быть, если вы взаимодействуете с каким-то нестандартным оборудованием.

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

Одна вещь, которую вы могли бы сделать с финализатором в «чистой» java, - это использовать его для проверки условий завершения, например, чтобы проверить, что все соединения закрыты, и сообщить об ошибке, если это не так.

4
ответ дан 3 December 2019 в 01:53
поделиться

В зоне .Net t не гарантируется , когда они работают. Но они побегут.

0
ответ дан 3 December 2019 в 01:53
поделиться

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

Конечно, во многих случаях как автор приложения вы знаете, что есть только одна ссылка на соединение с БД (для пример); в этом случае финализаторы не заменяют его правильное закрытие, когда вы знаете, что закончили с ним.

2
ответ дан 3 December 2019 в 01:53
поделиться

Ссылаетесь ли вы на Object.Finalize?

Согласно msdn, «В коде C # Object.Finalize нельзя вызвать или переопределить». Фактически, они рекомендуют использовать метод Dispose, поскольку он более управляем.

0
ответ дан 3 December 2019 в 01:53
поделиться

There's an additional complication with finalizers in .NET. If the class has a finalizer and does not get Dispose()'d, or Dispose() does not suppress the finalizer, the garbage collector will defer collecting until after compacting generation 2 memory (the last generation), so the object is "sort of" but not quite a memory leak. (Yes, it will get cleaned up eventually, but quite possibly not until application termination.)

As others have mentioned, if an object holds non-managed resources, it should implement the IDisposable pattern. Developers should be aware that if an object implements IDisposable, then it's Dispose() method should always be called. C# provides a way to automate this with the using statement:

using (myDataContext myDC = new myDataContext())
{
    // code using the data context here
}

The using block automatically calls Dispose() on block exit, even exits by return or exceptions being thrown. The using statement only works with objects that implement IDisposable.

And beware another confusion point; Dispose() is an opportunity for an object to release resources, but it does not actually release the Dispose()'d object. .NET objects are elligible for garbage collection when there are no active references to them. Technically, they can't be reached by any chain of object references, starting from the AppDomain.

0
ответ дан 3 December 2019 в 01:53
поделиться