问题标签 [finalize]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
6 回答
1912 浏览

ada - 在 Ada(2005 或 2012)中实现相当于 java finalize 块的最佳实践

Java 有 finalize 块,它允许在块离开后执行一些语句(即使引发异常也执行)。例子:

Ada 具有允许实现Finalize操作的受控对象,但没有与 java 中等效的 finalize 块。这对于记录、关闭文件、事务等很有用(无需为每个可能的块创建特定的标记类型)。

  1. 您将如何在 Ada 2005 中实现这样的 finalize 块(同时保持代码可读性)?
  2. Ada 2012 中是否有计划允许轻松执行任何终结代码?
0 投票
1 回答
568 浏览

java - Java - 程序结束时对象不是“垃圾收集”?

使用上面的代码 finalize() 永远不会执行。没有任何内容打印到控制台。当从 gc() 中删除注释时,finalize() 会执行,并且“cleaned”会打印到控制台。为什么我必须显式调用垃圾收集器?

0 投票
4 回答
314 浏览

java - 我很确定 finalize 在以后的 JVM 上仍然是个坏消息——还有其他选择吗?

我想实现一个 ORM 风格的系统,当调用者不再可以访问 POJO 时,它可以保存对 POJO 的更新。

我认为引用类可以做到这一点,但它们似乎只在对象被清除后才将引用加入队列(我希望是在它们能够被收集的时候),所以一旦加入队列, .get() 方法将始终返回无效的。

我可以使用终结器,但上次我检查这些是有问题的(不能保证立即运行或根本运行)--我相信终结器和 runShutdownHook() 的组合会起作用,但这进入了相当混乱的领域。

除了强制性的“当他完成后让调用者调用 .save() ”之外,还有其他我没有想到的路径吗?

0 投票
1 回答
804 浏览

c# - 完成队列释放速度不够快

我有针对位于服务器上的 Oracle DB 运行的 ac# 3.5 框架 Windows 应用程序。

其中一种应用程序的顶部有八个选项卡。每个选项卡的选项卡内容区域内都有一个组合框。组合框在每个表单上显示相同的信息。当用户使用下拉箭头或键盘箭头更改组合框值时,八个选项卡区域将填充从 Oracle 提取的数据。

根据现有程序的结构,每次更改组合框时,都会打开大约 20 个单独的 DB 连接。首先,调用大约 8 个来将不同选项卡中的数据保存到正确的表中。每个选项卡的内容都传递给一个 DB 类以保存该选项卡的数据。其次,基于组合框,大约进行了 8 次 DB 调用以从表中加载选项卡。

澄清一下,这就像在更改汽车型号的任何选项卡上选择一个组合框。然后每个选项卡都会是“内部选项”“引擎选项”等内容。

然后进行几个数据库调用以根据 ID 锁定高级记录,这样其他人就不能同时编辑该特定记录。

总的来说,这个过程非常可靠。保存/加载时间非常快。我可以通过几乎即时的数据保存/加载在两个不同的组合框值之间来回切换。

那么问题来了

如果我来回旋转足够快(有几个用户也这样做了),整个程序就会挂起。没有崩溃,只是挂起。

在调试环境中重复此操作,我发现它总是停在同一行代码上(一个简单的记录集分配(例如 CarModelInterior.Notes = Convert.ToString(myReader[6]);)

然后我发现垃圾收集器(GC)线程在后台运行,但每次也都停在同一个地方。

进入安装 RED-Gate 内存/性能监视器。

我发现切换组合框值的速度越来越快,GC 终结器队列填满的速度也越快。最终,似乎同一个 SQL 调用位于列表的顶部。

输入我的假设和猜测。

我的想法是,要么打开了太多连接并且没有足够快地完成,要么某处有锁。

我能说的是,整个程序中我的所有(每一个)数据库调用都使用“USING”语句,因此所有处理都是自动完成的。此外,所有(是的,我检查了整个应用程序),所有数据库调用都在主线程上。因此,为每个组合框值更改进行的所有 20 次左右的 DB 调用都是按顺序进行的。至少就可能的单线程问题而言,这消除了锁定的可能性。

我还剩下什么?在这一点上,我已经放弃了太多的谷歌搜索并在这里发布。是否有可能完成队列的处理速度不够快?还有其他想法吗?

0 投票
3 回答
1879 浏览

java - 方法完成和异常

当GC从内存中回收对象时忽略异常时,我不太了解。

如果我有一个try/catch进入 finalize 方法,我会看到它总是被执行......那么哪些情况下没有抛出异常?

谢谢。

0 投票
1 回答
106 浏览

vb.net - 应用程序退出时使用对象更新 Web 服务

我正在开发一个 Silverlight 应用程序,用户可以在其中创建、编辑、删除对象。他们所做的更改被放置在一个队列中,该队列每 4 分钟处理一次。处理后,更新通过异步 Web 方法调用发送,一次一个保存在 sql 数据库中。当第一次更新完成时,下一次更新开始。
当用户进行更改然后在 4 分钟计时器到期之前退出浏览器应用程序时,我遇到了问题。目前,更改正在丢失。

我建立在我之前从事此工作的人所做的工作的基础上,并探索了 Dispose 和 Finalize 方法,尝试在工厂关闭时启动更新过程,但由于 Web 服务调用的异步性质,这不起作用. 我收到错误消息,说需要的对象已被处理掉。

当用户尝试关闭或刷新网页时,我正在寻找一种使用 web 方法将数据保存在更新队列中的方法。我不希望队列中挤满了更新。这是一个通常一次运行几个小时的应用程序。

0 投票
3 回答
2270 浏览

java - 定义:未完成的对象与可完成的对象

为了理解 Java 中的弱引用,我不得不查阅 Java 语言规范。来自第 12.6 节的以下部分让我感到困惑:

未终结的对象从未自动调用其终结器;已完成的对象已自动调用其终结器。可终结对象从未自动调用其终结器,但 Java 虚拟机最终可能会自动调用其终结器。

那么 unfinalized 和 finalizable 对象之间的正式区别是什么?从引用看来,如果 unfinalized 和 finalizable 要不同,那么对于一个 unfinalized 对象,JVM 最终可能会调用它的终结器是不正确的。有点混乱,或者我还有一些英语语义要研究;)

链接到 Java 规范中的部分:实现终结

0 投票
2 回答
533 浏览

java - 当部署在 tomcat 上时,何时调用 finalize

我创建了一个简单的 Java 类,如下所示:

我将内容作为字节数组和文件名传递,该类在某处创建一个 TempFile。

}

我想如果我在 finalize 方法中实现清理,那么当 GC 处理对象时,临时文件将被自动删除。

我尝试对此进行调试,但似乎未调用 finalize 方法。

什么原因?这可能是因为我正在部署这个 Tomcat 服务器吗?

干杯

0 投票
1 回答
272 浏览

java - 在这种情况下,何时会在我的类实例上调用 finalize()?

我知道每当垃圾收集器收集类实例时都会调用 finalize() 。但是,当通过队列将类的实例传递给另一个线程时,我有点困惑。

假设这是 Thread1 的骨架:

然后,线程 2 将从队列中删除数据包并执行冗长的操作。这第二个线程是否获得了数据包的“副本”,还是通过某种形式的引用?重要的是,如果是通过复制,在线程 1 中创建的实例上的 finalize() 可以在线程 2 完成数据包之前调用。如果是通过引用,我保证 finalize() 只为数据包中的信息调用一次。

这个基本示例可能没有显示重要性,但我在数据包中存储了一个 C 指针(来自 JNI),以便在我完成对象时破坏一些内存。如果它通过副本传递,则内存可能会在第二个线程完成之前被破坏。如果它是通过引用传递的,那么它应该只在 GC 看到它不再被两个线程使用时才被销毁(我想要的行为)。如果不能保证后一种情况,我不会使用 finalize() 并使用其他东西,但它会更复杂。

0 投票
1 回答
602 浏览

java - 为什么我的 Java 对象被复制或 finalize() 被调用两次?

长长的 Java/Android/JNI 简而言之……我有两个类,一个是我创建的名为 Packet 的对象/类,一个是我编写的低级 C 代码的 JNI 接口。在一类中,我解析传入的数据包并将它们存储在 ArrayList 中。当它们被“解析”时,会调用一个函数 Packet.dissect(),它使用 JNI 调用较低级别的 C 代码。此 C 代码 malloc() 的一些内存,并将内存指针返回到 Java 代码,Java 代码将其存储在 Packet 对象的私有成员中:

现在,我想确保释放此内存,以免发生泄漏。因此,当垃圾收集器确定不再使用 Packet 对象时,我依靠 finalize() 调用 JNI C 代码函数,传递指针,从而释放内存:

太好了,这工作得很好,直到我尝试与第二类共享 ArrayList。为此,我在 Android 中使用广播,方法是将带有 ArrayList 列表的广播从第一类发送到第二类中的 BroadcastReceiver。这是从头等舱广播的地方:

认为这样做的正确之处在于列表中的每个数据包都通过引用对象传递给第二个类。如果这是真的,那么无论这两个类对 List 和其中的对象做什么,我都保证垃圾收集器只会为每个数据包调用 finalize()一次(当两个类都被认为完成了每个数据包时) . 这非常重要,否则 free() 将在同一个指针上被调用两次(导致 SEGFAULT)。

这似乎发生在我身上。一旦第二个类从广播中接收到 ArrayList,它就会对其进行解析,并从列表中保存几个 Packet。这样做时,另一个对象/类有一个 Packet 类型的成员,如果我“喜欢”该数据包,我会通过以下方式保存它:

最终这个接收广播的方法返回,并且一些数据包被“保留”。最后,当我单击一个按钮时(几秒钟后),原始类中的 ArrayList 被清除:

我假设即使在这里调用 clear() 时,如果第一个类“保留”了一些数据包,垃圾收集器也不会对它们调用 finalize()。唯一错误的方法是:(1)当广播被发送时,ArrayList 被复制而不是通过引用传递,或者(2)当数据包被“保留”在第二类,Packet 对象中时被复制而不是通过引用保存。

好吧,其中一个是错误的,因为 free() 偶尔会在同一块内存上调用两次。我看到它已分配(“新解剖:MEMORY_ADDRESS1 - IGNORE_THIS”),然后调用两个 finalize() 试图释放相同的内存地址:

因此,我对传递的对象所做的两个假设之一是错误的。有谁知道它可能是哪个,以及如何通过引用更仔细地传递对象,以便我可以正确清理内存?

如果您通过我的问题做到了这一点并理解它,谢谢;)