终结器对JVM的性能影响 [英] Performance implications of finalizers on JVM

查看:123
本文介绍了终结器对JVM的性能影响的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据这篇文章,在.Net中,


终结者实际上甚至更糟。除了它们运行较晚(这对于许多种资源确实是一个严重的问题),它们也不那么强大,因为它们只能执行析构函数中允许的操作的子集(例如,终结器不能可靠地使用其他对象,而析构函数可以),即使在写入该子集时,终结器也很难正确编写。并且收集可终结的对象是昂贵的:每个可终结的对象,以及可从其获得的对象的潜在巨大图形,被提升到下一代GC生成,这使得通过一些大的倍数收集它更加昂贵。

Finalizers are actually even worse than that. Besides that they run late (which is indeed a serious problem for many kinds of resources), they are also less powerful because they can only perform a subset of the operations allowed in a destructor (e.g., a finalizer cannot reliably use other objects, whereas a destructor can), and even when writing in that subset finalizers are extremely difficult to write correctly. And collecting finalizable objects is expensive: Each finalizable object, and the potentially huge graph of objects reachable from it, is promoted to the next GC generation, which makes it more expensive to collect by some large multiple.

这是否也适用于一般的JVM,特别是HotSpot?

Does this also apply to JVMs in general and to HotSpot in particular?

推荐答案

以下是 Effective Java 2nd Edition中的一些选择引用:第7项:避免终结器


终结器是不可预测的,通常是危险的,通常是不必要的。它们的使用会导致不稳定的行为,性能不佳和可移植性问题。终结者几乎没有有效用途,[...]作为经验法则,你应该避免使用终结者。

Finalizers are unpredictable, often dangerous, and generally unnecessary. Their use can cause erratic behavior, poor performance, and portability problems. Finalizers have few valid uses, [...] as a rule of thumb, you should avoid finalizers.

你应该确保事实上,你需要终结者;大部分时间你都不这样做。

You should really make sure that in fact, you DO need finalizers; most of the time you DON'T.


C ++程序员被警告不要将终结器视为Java的C ++析构函数的类比。在C ++中,析构函数是回收与对象关联的资源的常用方法,对象是构造函数的必要对应物。在Java中,垃圾收集器在它变得无法访问时回收与对象相关联的存储,而不需要程序员的特殊努力。 C ++析构函数也用于回收其他非内存资源。在Java中, try-finally 块通常用于此目的。

调用终结器时的语义也很重要:

The semantics of when finalizers are invoked is also important to consider:


JLS 12.6类实例的最终确定



Java编程语言没有指定多长时间调用 finalizer [...也不会]哪个线程将为任何给定对象调用终结器。 [...]如果在完成期间抛出未捕获的异常,则忽略该异常并终止该对象的终止。 (JLS 12.6.2)终结器调用不是已订购

JLS 12.6 Finalization of Class Instances

The Java programming language does not specify how soon a finalizer will be invoked [...nor] which thread will invoke the finalizer for any given object. [...] If an uncaught exception is thrown during the finalization, the exception is ignored and finalization of that object terminates. (JLS 12.6.2) Finalizer Invocations are Not Ordered

此外,按需运行终结器的唯一机制已被破坏。以下引用来自 Effective Java 第2版:

Moreover, the only mechanism to run finalizer on demand is broken. The following quotes are from Effective Java 2nd Edition:


[...]声称的唯一方法保证最终确定是 System.runFinalizersOnExit 及其邪恶的双胞胎, Runtime.runFinalizersOnExit 。这些方法存在致命缺陷并且已被弃用。

[...] The only methods that claim to guarantee finalization are System.runFinalizersOnExit and its evil twin, Runtime.runFinalizersOnExit. These methods are fatally flawed and have been deprecated.

Bloch进一步评论性能损失(强调他的):

Bloch went further to comment on the performance penalty (emphasis his):


哦,还有一件事:使用终结器会导致严重的性能损失 。在我的机器上,创建和销毁一个简单对象的时间约为5.6ns。添加终结器可将时间增加到2,400ns。换句话说,使用终结器创建和销毁对象的速度要快430倍。

Oh, and there's one more thing: there is a severe performance penalty for using finalizers. On my machine, the time to create and destroy a simple object is about 5.6ns. Adding a finalizer increases the time to 2,400ns. In other words, it is about 430 times slower to create and destroy objects with finalizers.

关于基准测试方法的细节很少,我不认为具体的数字意味着什么,但它确实证实了广泛记载的内容:终结器非常昂贵。

With such little details on the benchmarking methodology, I don't think the specific numbers mean much, but it does confirm what have been widely documented: finalizers are very costly.

本书确实解释了罕见的情况。使用终结器是有效的。从这个答案中省略这些引用是故意的。

The book does explain the rare scenarios under which using finalizers is valid. The omission of those quotes from this answer is intentional.

这篇关于终结器对JVM的性能影响的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆