标签: finalizer

关于C#中的Dispose()和析构函数的两个问题

我有一个关于如何使用Dispose()和析构函数的问题.阅读一些文章和MSDN 文档,这似乎是实现Dispose()和析构函数的推荐方法.

但是我对这个实现有两个问题,你可以在下面看到:

class Testing : IDisposable
{
    bool _disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed) // only dispose once!
        {
            if (disposing)
            {
                // Not in destructor, OK to reference other objects
            }
            // perform cleanup for this object
        }
        _disposed = true;
    }

    public void Dispose()
    {
        Dispose(true);

        // tell the GC not to finalize
        GC.SuppressFinalize(this);
    }

    ~Testing()
    {
        Dispose(false);
    }
}
Run Code Online (Sandbox Code Playgroud)

Dispose()上的GC.SupressFinalize(this)

当程序员使用using或调用Dispose()显式时,我们的类正在调用GC.SupressFinalize(this).我的问题是:

  • 这究竟意味着什么?是否会收集对象但不调用析构函数?我想anwswer是肯定的,因为 …

.net c# dispose destructor finalizer

16
推荐指数
1
解决办法
3395
查看次数

我们可以关闭终结器吗?

由于几乎没有保证什么时候,甚至终结器运行和终结器几乎被认为是现在的气味 - 有没有办法说服JVM完全跳过所有的终结过程?

我问,因为我们有一个庞大的应用程序,当移动到一个较新的JVM(不确定在这个阶段)是什么看起来非常像终结者的已知问题(抛出异常,因此非常慢的GC) .

添加

有关Java内存泄漏故障排除的讨论:终结?建议在终结器中抛出异常时出现主要问题,因为这会大大减慢终结过程.

当内存变低并且堆转储分析显示大量Finalizer对象(超过10,000,000)时,我的问题显示为急剧减速- 向我建议减速可能是他们的错,因为他们正在推迟GC.显然我可能是错的.

我没有权力要求重构.

java garbage-collection finalizer

16
推荐指数
1
解决办法
609
查看次数

终结器线程的范围是什么 - 每个应用程序域或每个进程?

基于我的所有阅读,应该有一个GC线程来调用所有终结器.现在,问题是这个"一个"线程的范围是什么 - 每个进程或每个应用程序域,因为域的整个意图是在一个进程空间中分离并创建"独立"的不同应用程序.

在这里读到:

如果在终结器中发生未处理的异常,则CLR的执行线程将吞下该异常,将终结器视为正常完成,将其从可释放队列中移除并移至下一个条目.

更严重的是,如果你的终结器由于某种原因没有退出会发生什么,例如它会阻塞,等待一个永远不会发生的情况.在这种情况下,终结器线程将被挂起,因此不再有可终结的对象将被垃圾收集.您应该非常了解这种情况,并坚持编写最简单的代码来释放终结器中的非托管资源.

另一个考虑因素是应用程序关闭期间发生 当程序关闭时,垃圾收集器将尽力调用所有可终结对象的终结器,但有一些限制:

  • 在关闭期间,可终结对象不会升级到更高的堆生成.

  • 任何单个终结器最多只能执行2秒; 如果它需要更长时间,它将被杀死.

  • 所有终结器的执行时间最长为40秒; 如果任何终结器仍在执行,或者此时待决,整个过程将被突然终止.

太多帖子(甚至官方文档)滥用术语"应用程序","进程"和"应用程序域" - 他们中的大多数甚至假设它们是相同的,因为通常应用程序在单个进程中在单个应用程序域中运行.这种滥用使得所有这些文档难以阅读,甚至没有用处.

因此,我的问题假设多个应用程序,每个应用程序在单个进程中在单独的应用程序域中运行.

所有这些应用程序是否共享相同的GC和终结器线程?上面的文章中描述的问题(挂起终结器线程)是否会影响该进程中的所有应用程序?如果是 - 是否有解决方法(除了不使用不良应用程序),就像以某种方式发现终结器线程并发送它Thread.Abort?

以上都是因为我遇到了类似的问题.我的应用程序在单独的应用程序域中运行,作为第三方软件(Outlook)的插件.由于各种原因,我需要调用GC.Collect和GC.WaitForPendingFinalizers来完全释放COM引用(对于Office/Outlook,通常的互操作例程是不够的),当一个特定的其他第三方插件运行时,我的GC.WaitForPendingFinalizers将永远挂起,所以我怀疑第三方添加的"坏"终结器.我无法控制替换/删除添加(客户端的要求),因此我必须自己弄清楚如何使它们共存.

.net multithreading process appdomain finalizer

14
推荐指数
1
解决办法
1910
查看次数

VisualStudio调试器退出时执行代码

我假设在终止调试时(例如通过点击"停止"按钮,或按Shift + F5),任何实现终结器或IDisposable的类都将被处理掉.

我有一些实现IDisposable的类.当应用程序从调试器退出时(或从生产中崩溃),我想做(尝试)并执行一些操作.现在,Dispose()似乎没有被调用,也没有终结器IDisposable

有没有办法做到这一点?

.net c# dispose .net-4.0 finalizer

14
推荐指数
1
解决办法
2234
查看次数

14
推荐指数
1
解决办法
4621
查看次数

Java 9 Cleaner应该优先完成吗?

在Java中,覆盖该finalize方法会得到一个糟糕的说唱,虽然我不明白为什么.类似于FileInputStream使用它来确保close在Java 8和Java 10中调用.然而,Java 9引入java.lang.ref.Cleaner了使用PhantomReference机制而不是GC终结.起初,我认为这只是向第三方类添加finalization的一种方式.但是,其javadoc中给出的示例显示了一个可以使用终结器轻松重写的用例.

我应该finalize用Cleaner 重写我的所有方法吗?(当然,我没有很多.只是一些使用OS资源的类,特别是对于CUDA互操作.)

据我所知,Cleaner(通过PhantomReference)避免了一些危险finalizer.特别是,您无法访问已清理的对象,因此您无法复活它或其任何字段.

然而,这是我能看到的唯一优势.清洁工也是非平凡的.事实上,它和终结都使用了ReferenceQueue!(难道你不喜欢阅读JDK是多么容易吗?)它比完成更快吗?它是否避免等待两个GC?如果许多对象排队等待清理,它会避免堆耗尽吗?(所有这些的答案在我看来都不是.)

最后,实际上没有任何保证阻止您在清理操作中引用目标对象.小心阅读长API注意!如果你最终引用了这个对象,那么整个机制将会默默地中断,而不像终结总是试图跛行.最后,虽然终结线程由JVM管理,但创建和保存Cleaner线程是您自己的责任.

java finalize finalization finalizer java-9

14
推荐指数
2
解决办法
825
查看次数

是否应该在没有终结器的对象上调用GC.SuppressFinalize?

出于某种原因,FXCop似乎认为我应该在Dispose中调用GC.SuppressFinalize,无论我是否有终结器.

我错过了什么吗?是否有理由在没有定义终结器的对象上调用GC.SuppressFinalize?

c# fxcop finalizer

13
推荐指数
2
解决办法
3456
查看次数

F#等价的析构函数

我正在翻译一个将非托管库包装到F#的C#类.我遇到了重写后面的析构函数这个看似简单的问题.

class Wrapper {

    // P/Invoke ellided

    private SomeType x;

    public Wrapper() {
        x = new SomeType();
        Begin();
    }

    public ~Wrapper() {
        End();
    }
Run Code Online (Sandbox Code Playgroud)

我现在简化的F#代码如下:

type Wrapper() =
  [<Literal>]
  static let wrappedDll = "Library.dll"

  [<DllImport(wrappedDll , EntryPoint = "Begin")>]
  static extern void Begin()

  [<DllImport(wrappedDll , EntryPoint = "End")>]
  static extern void End()

  let x = new SomeType()

  do
    Begin()
Run Code Online (Sandbox Code Playgroud)

如何修改此F#代码以具有相同的行为?我对F#析构函数的搜索没有出现在我的书籍或网络上.

谢谢.

f# finalizer c#-to-f#

13
推荐指数
2
解决办法
2175
查看次数

"终结者监护人"如何在java中工作?

"终结者监护人"[Effective Java,第30页]如何运作?

你用过它们了吗?它解决了任何具体问题吗?

java garbage-collection finalizer

13
推荐指数
1
解决办法
2305
查看次数

解决java内存泄漏问题:终结?

我有一个看似泄漏的行为不当的应用程序.在简要的剖析器调查之后,大多数内存(80%)由java.lang.ref.Finalizer实例保存.我怀疑终结器无法运行.

这种情况的常见原因似乎是终结者抛出的异常.但是,类的finalize方法的javadoc Object(例如,参见这里)似乎与自己相矛盾:它说明了

如果finalize方法抛出未捕获的异常,则忽略该异常并终止该对象的终止.

但后来,它也说明了这一点

finalize方法抛出的任何异常都会导致暂停此对象的终结,但会被忽略.

我应该相信什么(即终止或不结束?),您是否有任何关于如何调查此类明显泄漏的提示?

谢谢

java memory-leaks finalizer

13
推荐指数
2
解决办法
1万
查看次数