主要问题在于主题,但是让我展示我对Java中最终化过程的看法,以便我可以向您提出更多要求.
那么gc通过标记所有活动对象来启动垃圾收集.当所有可到达的对象都标记为"实时"时.所有其他对象都无法访问.下一步是检查每个无法到达的对象,并确定它是否可以立即进行清理,或者应该首先完成.如果对象的finalize方法有一个主体,那么gc会想到下一个方法,那么这个对象是可以最终确定的并且应该最终确定; 如果对象的finalize方法有一个空体(protected void finalize(){})那么它不能最终化并且现在可以被gc清理.(我是对的吗?)
所有可终结的对象将放在同一个队列中,以便稍后逐一完成.据我所知,可终结的对象可以花费大量时间放在队列中,同时等待轮到他们完成.这可能发生,因为通常只有一个名为Finalizer的线程从队列中获取对象并调用它们的finalize方法,当我们在某个对象的finalize方法中有一些耗时的操作时,队列中的其他对象将等待很长时间才能完成.好的,当一个对象完成后,它被标记为FINALIZED并从队列中删除.在下一个垃圾收集过程中,收集器将看到此对象无法访问(再次)并且具有非空的finalize方法(再次),因此该对象应该被放入队列中(再次) - 但它不会因为收集器以某种方式看到这个对象被标记为FINALIZED.(这是我的主要问题:这个对象被标记为FINALIZED的方式,收集器如何知道该对象不应该再次终结?)
我需要在内存使用方面优化我的应用程序。所以我使用了 .net 性能分析器...但是我的应用程序中的一些引用仍然存在并且即使我强制它收集也永远不会被 GC 收集。
活着的引用是“终结句柄”类型。我不知道该怎么做才能删除这种引用......请帮忙。
我有一些我怀疑是泄漏记忆的代码.因为代码使用ccall并维护指针内部保存的重要信息,这些信息应该由s ccall期间编写的代码释放finalizer.
在我的调试中,我正在打电话gc().我想知道这是否会立即触发finalizer附加到已超出范围的对象的所有s
答案应该只关注julie 0.5+.
我们发现我们的一个 WCF 应用程序出现内存泄漏,我想知道是否有人可以为我澄清一些事情。我使用 windbg 运行了 !finalizequeue,它将每个堆集中的数千个对象显示为“准备好完成”。
Heap 0
generation 0 has 464 finalizable objects (0000000033877190->0000000033878010)
generation 1 has 52 finalizable objects (0000000033876ff0->0000000033877190)
generation 2 has 19958 finalizable objects (0000000033850040->0000000033876ff0)
Ready for finalization 228791 objects (0000000033878010->0000000033a36dc8)
------------------------------
Heap 1
generation 0 has 1508 finalizable objects (000000002ee2e168->000000002ee31088)
generation 1 has 91 finalizable objects (000000002ee2de90->000000002ee2e168)
generation 2 has 23498 finalizable objects (000000002ee00040->000000002ee2de90)
Ready for finalization 249421 objects (000000002ee31088->000000002f0182f0)
------------------------------
Heap 2
generation 0 has 66 finalizable objects (00000000292660d0->00000000292662e0)
generation 1 has 63 finalizable …Run Code Online (Sandbox Code Playgroud) 简介: C#/ .NET应该是垃圾回收.C#有一个析构函数,用于清理资源.当一个对象A被垃圾收集在同一行我试图克隆其变量成员之一时会发生什么?显然,在多处理器上,有时,垃圾收集器赢了......
问题
今天,在关于C#的培训课程中,老师向我们展示了一些仅在多处理器上运行时才包含错误的代码.
我将总结一下,有时候,编译器或JIT通过在从被调用方法返回之前调用C#类对象的终结器来搞砸.
在Visual C++ 2005文档中给出的完整代码将作为"答案"发布,以避免提出非常大的问题,但基本要点如下:
以下类具有"Hash"属性,该属性将返回内部数组的克隆副本.在构造中,数组的第一项值为2.在析构函数中,其值设置为零.
关键是:如果你试图得到"示例"的"哈希"属性,你将获得一个干净的数组副本,其第一个项目仍然是2,因为正在使用该对象(因此,不是垃圾收集/定稿):
public class Example
{
private int nValue;
public int N { get { return nValue; } }
// The Hash property is slower because it clones an array. When
// KeepAlive is not used, the finalizer sometimes runs before
// the Hash property value is read.
private byte[] hashValue;
public byte[] Hash { get { return (byte[])hashValue.Clone(); } }
public Example()
{
nValue = 2;
hashValue = new byte[20]; …Run Code Online (Sandbox Code Playgroud) 我有两个单位unitA和unitB.类TFoo在unitB中声明.
在单元A的最终确定中调用B.Free是否总是安全的?
它如何依赖于unitA和unitB在dpr中的顺序?
执行unitA终结时,我能确定unitB是否存在?
unit unitB;
interface
type
TFoo = class
// code...
end;
// code....
end;
unit unitA;
// code..
implementation
uses
unitB;
var
A: TStringList;
B: UnitB.TFoo;
initialization
A:= TStringList.Create;
B:= UnitB.TFoo.Create;
finalization
A.Free;
B.Free; // Is it safe to call?
end.
Run Code Online (Sandbox Code Playgroud) 我有一个应用程序,它使用静态链接的运行时包以及使用它们的设计时包.由于某种原因,任何单元定型部分中的代码都没有在运行时运行(我无法分辨何时开始发生).
finalization
ShowMessage('Goodbye');
end.
Run Code Online (Sandbox Code Playgroud)
关闭Delphi会显示消息,但不会在我的应用程序关闭时显示.如果我在ShowMessage上设置一个断点,它会在那里中断,但不执行该行,这更令人讨厌.如果最终化中有多行,则调试器在第一行停止,不执行它然后跳转到结尾.
procedure ProcOne;
begin
SomeObject.Free; // Debugger does not enter or stop here
SomeObject := nil;
end;
finalization
ProcOne; // Debugger stops here, doesn't execute, jumps to "end."
ProcTwo; // Every line has a blue dot
ShowMessage('Bye');
end.
Run Code Online (Sandbox Code Playgroud)
ProcOne断点上的调用堆栈显示@ Halt0 => FinalizeUnits => MyPackage.MyUnit.Finalization.
如果我将该单元包含在不使用包的应用程序中,则一切都正常执行.
有谁知道可能导致这种情况的原因是什么?
编辑:
感谢Allen Bauer的评论指向了正确的方向,我已经设法解决了这个问题.如果使用运行时包构建应用程序,然后动态加载另一个也引用该包和单元的包,则似乎会出现问题.
我创建了一个演示问题的测试项目:TestFinalization
有谁知道这个和/或解决方法的原因?在您注意到外部资源未被清除之前,您通常可能不会注意到您的终结未运行.
我有一个多线程的应用程序有很多表单,但我必须实例化一些类,并在创建表单之前调用一些初始化的东西.当然,我必须执行相应的终结代码.
这是.dpr文件的简化示例:
begin // .dpr project file
LoadDlls;
try
Config := TConfig.Create;
try
Application.Initialize;
Application.Title := 'Foo';
Application.CreateForm(TMainForm, MainForm);
Application.CreateForm(TOtherForm, OtherForm);
//...other forms...
Application.Run;
finally
Config.Free;
end;
finally
UnloadDlls;
end;
end;
Run Code Online (Sandbox Code Playgroud)
这里的问题是finally块内部的代码在我的表单的OnDestroy/ destructors 之前执行.这清楚地看着单位finalization部分Form:
finalization
if Application <> nil then DoneApplication;
Run Code Online (Sandbox Code Playgroud)
并且DoneApplication呼叫Application.DestroyComponents有效地释放所有Application拥有的形式.
因此,创建的表单Application.CreateForm将在主begin..end块内的任何代码之后被销毁.
我想要的是,在Application.Run所有表单被销毁之后,它们的OnDestroy事件处理程序可以看到Config我的dll中定义的对象和外部函数.同上,如果引发异常.但是我也想要标准的应用程序的异常处理if Config.Free或UnlodDllsraise(应用程序必须仍然存在).
注意:
finalization块(可能在.dpr中?)来保持代码更清晰和可调试;我认为,最简单的办法是显式调用Application.DestroyComponents …
我是delphi的初学者,我遇到了终结错误e2155.我正在使用RAD 10并尝试在移动设备上运行我的程序.它在我的Windows机器上工作正常,但是当我改为Android或IOS时,它给了我终结错误.
代码:
type
TRaumparameter = record
ID : string;
Länge: string;
Breite: string;
Höhe: string;
Fläche: string;
Raumvolumen: string;
Wände: string;
Decke: string;
Boden: string;
Baujahr: string;
Heizlast: string;
end;
var Aufstellraum: Traumparameter;
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
{$R *.iPad.fmx IOS}
procedure TForm1.speichernClick(Sender: TObject);
var F: File of Traumparameter;
begin
Aufstellraum.Länge:=form2.Länge.Text;
Aufstellraum.Breite:=form2.Breite.Text;
Aufstellraum.Höhe:=form2.Höhe.Text;
Aufstellraum.Fläche:=form2.Fläche.Text;
Aufstellraum.Raumvolumen:=form2.ErgebnisRaumVol.Text;
Aufstellraum.Wände:=form2.Wände.Text;
Aufstellraum.Decke:=form2.Decke.Text;
Aufstellraum.Baujahr:=form2.Baujahr.Selected.Text;
Aufstellraum.Heizlast:=form2.Heizlast.Text;
try
AssignFile(F,'D:\test\1.txt');
ReWrite(F);
Write(F,Aufstellraum);
finally
CloseFile(F);
end;
end;
Run Code Online (Sandbox Code Playgroud)
我已经尝试用[]来限制字符串的长度,但它告诉我:';' 预期,但'''发现.希望我能得到一些答案,因为我安静了一段时间没有任何成功.提前致谢!!
Java允许编写:
new PhantomReference(new Object(), null)
Run Code Online (Sandbox Code Playgroud)
在这种情况下new Object()将被收集?
据我了解,幻影引用是finalize() 方法使用的替代方法。
在队列中出现引用后,我需要执行一些其他操作,然后运行 clear()
Java Doc保留:
可以使用空队列创建幻影引用,但是这种引用完全没有用:其get方法将始终返回null,并且由于它没有队列,因此永远不会入队。
如果它永远不会被排队,那意味着什么?
据我了解,这意味着在完成方法调用后,引用不会再添加到referenceQueue中。因此可能导致:
1.对象存储器将立即被清除
2.对象存储器将不会被清除
哪种情况正确?