出于某种原因,FXCop似乎认为我应该在Dispose中调用GC.SuppressFinalize,无论我是否有终结器.
我错过了什么吗?是否有理由在没有定义终结器的对象上调用GC.SuppressFinalize?
我正在翻译一个将非托管库包装到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#析构函数的搜索没有出现在我的书籍或网络上.
谢谢.
我有一个看似泄漏的行为不当的应用程序.在简要的剖析器调查之后,大多数内存(80%)由java.lang.ref.Finalizer实例保存.我怀疑终结器无法运行.
这种情况的常见原因似乎是终结者抛出的异常.但是,类的finalize方法的javadoc Object(例如,参见这里)似乎与自己相矛盾:它说明了
如果finalize方法抛出未捕获的异常,则忽略该异常并终止该对象的终止.
但后来,它也说明了这一点
finalize方法抛出的任何异常都会导致暂停此对象的终结,但会被忽略.
我应该相信什么(即终止或不结束?),您是否有任何关于如何调查此类明显泄漏的提示?
谢谢
在回答关于SO的另一个问题*以及随后的评论讨论时,我遇到了一个我不清楚的问题.
在我误入歧途的任何地方纠正我......
当垃圾收集器收集一个对象时,它会在一个单独的线程上调用该对象的终结器(除非终结器已经被抑制,例如通过一个Dispose()方法).在收集时,GC会挂起除触发集合的线程(除了背景集合)之外的所有线程.
不清楚的是:
*链接到原始问题:
.NET GC从终结器访问同步对象
一如既往,一个冗长的问题描述.
我们目前正在对我们的产品进行压力测试 - 现在我们面临一个奇怪的问题.一到两个小时后,堆空间开始增长,应用程序稍后会死.
对应用程序进行概要分析会显示大量的Finalizer对象,从而填充堆.好吧,我们认为"可能是一个奇怪的终结器线程减慢"问题,并审查了减少需要最终确定的对象的数量(在这种情况下为JNA本机句柄).反正好主意,减少了成千上万的新物......
接下来的测试显示了相同的模式,仅一个小时后,并没有那么陡峭.这次Finalizers起源于在测试平台中大量使用的FileInput-和FileOutput流.所有资源都已关闭,但终结器不再清理.
我不知道为什么在1或2小时后(没有例外),FinalizerThread似乎突然停止工作.如果我们在一些线程中手动强制执行System.runFinalization(),则分析器会显示清除终结器.立即恢复测试会导致终结器的新堆分配.
FinalizerThread仍在那里,询问jConsole他正在等待.
编辑
首先,使用HeapAnalyzer检查堆没有发现任何新的/奇怪的.HeapAnalyzer有一些不错的功能,但我起初遇到了困难.我使用jProfiler,它附带了很好的堆检测工具,并将继续使用它.
也许我错过了HeapAnalyzer中的一些杀手级功能?
其次,今天我们使用调试连接而不是分析器来设置测试 - 系统现在稳定了近5个小时.这似乎是一个非常奇怪的组合,包括太多的终结器(在第一次审查中已经减少),分析器和VM GC策略.由于目前一切运行良好,没有真正的见解......
感谢您到目前为止的输入 - 也许您保持关注和感兴趣(现在您可能有更多理由相信我们不会谈论简单的编程错误).
我只是不明白为什么必须使用Runtime.addShutdownHook.如果你想在jvm退出时进行一些清理,为什么不重载守护进程类的finalize方法.使用shutdown hook而不是finalize方法有什么好处.
还有一个不推荐使用的函数runFinalizersOnExit.如果我将其设置为false,我相信终结器将无法运行.这与java保证终结器总是在垃圾收集之前运行相矛盾.
来自Python 文档:
不能保证
__del__()在解释器退出时仍然存在的对象调用方法。
据我了解,也无法保证对象在解释器退出之前停止存在,因为由垃圾收集器决定是否以及何时删除对象。
那么使用这种方法有什么意义呢?您可以在其中编写清理代码,但不能保证它会被执行。
我知道您可以使用try-finally或with子句来解决这个问题,但我仍然想知道该__del__()方法的有意义的用例是什么。
情况
我们正在运行一个大型WPF应用程序,它不会释放内存很长一段时间.它不是真正的内存泄漏,因为内存最终会被释放.我知道通常情况下,这不会被认为是一个问题.不幸的是,它与WPF指挥基础设施相结合成为一个性能问题.有关更详细的说明,请参见下文.
发现
我们有自动化测试,可以执行典型的用例.有些案例工作正常,并及时释放记忆.其他人正在占用内存,直到客户端最小化,打开一个新窗口或触发Gen2集合的其他一些条件.
•使用ANTS我们看到,对象没有GC Root,但是很多引用需要完成的其他对象.
•WinDbg未显示任何准备完成的对象.
•运行几个GC.Collect(),GC.WaitForPendingFinalizers()完全释放内存.
•我们知道哪种UI操作会导致高内存条件,但我们无法识别任何可疑代码.
题
我们希望有关于调试此类问题的任何建议.
WPF CommandManager背景
WPF CommandManager保存WeakReferences(_requerySuggestedHandlers)的私有集合以引发CanExecuteChanged事件.处理CanExecuteChanged成本非常高(尤其是找到EventRoute CanExecute,显然是一个RoutedEvent).只要CommandManager感觉像是在执行命令就可以执行,它会遍历此集合并CanExecuteChanged在相应的命令源上调用事件.
只要存在引用对象的GC句柄,就不会从该集合中删除WeakReferences.虽然尚未收集该对象,但CommandHelper会继续处理CanExecute这些元素的事件(ButtonBase或MenuItems).如果存在大量垃圾(如我们的情况),这可能导致CanExecute事件处理程序的调用数量极大,这会导致应用程序非常滞后.
假设我有一些asm.js代码,可能是由emscripten创建的.假设它有一些相当大的堆分配结构,它由asm.js函数返回,作为一个指针,由一些JavaScript库拾取,包装在一个漂亮的JavaScript对象中.好到目前为止.
但是,如果该对象超出范围并被垃圾收集,会发生什么.现在,asm.js代码无法知道这一点,因此结构的内存将保持分配状态,从而导致内存泄漏.
有没有办法从JavaScript中向JavaScript对象添加终结器?
这样的终结器可用于释放asm.js中的内存,从而避免内存泄漏.到目前为止,我找不到一个记录在案的便携式方法来实现这一点,但也许我一直在寻找错误的地方.
从?reg.finalizerR中的文档:
除其他外,它提供了一种方法来编写代码,以便在R会话结束时运行而无需进行操作
.Last.为了在包中使用,通常最好在命名空间中的对象上设置终结器:然后在会话结束时调用终结器,或者在会话期间完成命名空间后不久调用它.
似乎我可以reg.finalizer()在R会话结束时使用运行某些代码,但它对我不起作用.我在https://github.com/yihui/finalizer-test准备了一个最小的包,它基本上包含以下代码:
e = new.env()
reg.finalizer(e, function(e) {
message('Bye!')
}, onexit = TRUE)
Run Code Online (Sandbox Code Playgroud)
如果我只是在交互式R会话中运行上面的代码并退出会话,我可以看到该消息Bye!,但是如果我安装上面的包(你可以使用devtools::install_github('yihui/finalizer-test')),在R会话中加载它,并退出R会话,我看不到消息.我想知道为什么在这种情况下不执行终结器.
FWIW,当我安装软件包时,我可以看到以下消息Bye!:
$ R CMD INSTALL .
* installing to library ‘/Users/yihui/R’
* installing *source* package ‘finalizer’ ...
** R
** preparing package for lazy loading
No man pages found in package ‘finalizer’
** help
*** installing help indices
Bye!
** building package indices
** testing if installed package can be …Run Code Online (Sandbox Code Playgroud) finalizer ×10
c# ×3
java ×3
asm.js ×1
c#-to-f# ×1
destructor ×1
f# ×1
fxcop ×1
javascript ×1
memory-leaks ×1
python ×1
r ×1
r-package ×1
wpf ×1