对象最终化的前期成本是多少?

2024-01-04

Java 中可终结对象的讨论通常讨论当可终结对象(及其相关资源)无法快速进行垃圾收集时发生的常见间接成本。

目前,我更感兴趣的是可终结的实际直接成本是多少,无论是在内存方面还是在对象分配时间方面。我在很多地方都看到过间接提及这种成本的存在,例如,Oracle 关于终结内存保留问题的文章 http://www.oracle.com/technetwork/java/javamail/finalization-137655.html notes:

When obj分配后,JVM 内部记录obj是可最终确定的。这通常会减慢现代 JVM 所具有的快速分配路径。

JVM 如何记录对象实例是可终结的,这样做的内存和性能成本是多少?

对于那些对我的具体应用感兴趣的人:

我们生产并保留了数以百万计的轻质物体;向这些对象添加单个指针的成本非常高,因此我们做了相当多的工作来从它们中删除指针,而不是使用较小的数字 id 打包到字段位的子集中。解压该数字允许从使用 Map 存储它们的池中检索具有该 id 的共享不可变属性。

剩下的问题是如何处理不再使用的属性值的垃圾收集。

已考虑的一种策略是使用引用计数;当创建对象并检索某个值的池化 id 时,该值的引用计数就会增加;当不再使用时,必须递减。

确保发生这种递减的一种选择是添加以下 Finalize 方法:

public void finalize() {
    Pool.release(getPropertyId());
}

然而,如果可最终化的行为本身意味着必须保留指向该对象的附加指针,则可最终化的前期成本对于该应用程序来说将被认为是很高的。如果这意味着必须分配额外的对象,那么几乎肯定会太高......因此,我的问题是:可终结的直接前期成本是多少?


终结器是awful不仅是因为保留问题,而且从性能角度来看也是如此。

在 Oracle JDK / OpenJDK 中,对象具有finalize方法由以下实例支持终结器 http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/a006fa0a9e8f/src/share/classes/java/lang/ref/Finalizer.java,子类java.lang.ref.Reference.

所有终结器都通过两个步骤在对象构造函数的末尾注册:调用从Java到VM http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/ade5be2b1758/src/share/vm/opto/parse1.cpp#l1938随后调用终结器.register() http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/a006fa0a9e8f/src/share/classes/java/lang/ref/Finalizer.java#l85。这种双重转换 Java->VM->Java 无法由 JIT 编译器内联。但最糟糕的是 Finalizer 的构造函数在全局锁 http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/a006fa0a9e8f/src/share/classes/java/lang/ref/Finalizer.java#l50! (捂脸)

终结器在内存占用方面也很糟糕:除了它们拥有的所有引用字段之外两个额外字段 http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/a006fa0a9e8f/src/share/classes/java/lang/ref/Finalizer.java#l42: next and prev.

幻像引用比终结器要好得多:

  • 它们的构造不需要转换到 VM 并返回,并且可以内联;
  • 除了继承自之外,他们没有额外的字段java.lang.ref.Reference;
  • 没有进行全局同步。

这个基准 http://pastebin.com/X3C2MMCx比较可终结对象和 PhantomReference 支持的对象的分配速度:

Benchmark               Mode  Cnt       Score      Error   Units
Finalizer.finalizable  thrpt    5    2171,312 ± 1469,705  ops/ms
Finalizer.phantom      thrpt    5   61280,612 ±  692,922  ops/ms
Finalizer.plain        thrpt    5  225752,307 ± 7618,304  ops/ms
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对象最终化的前期成本是多少? 的相关文章

  • 在 Eclipse 中隐藏重复的工具栏项

    我不知道如何 但我的 STS 有重复的工具栏项目 我不知道如何删除它们 这是我复制的工具栏的样子 我想摆脱这些 我试图隐藏工具栏 但这没有帮助 有人知道如何删除重复的吗 自从升级到 Oxygen 以来 我一直遇到同样的问题 我无法可靠地重现
  • Android 中的 java.util.Observable 是线程安全的吗?

    Android 中的 java util Observable 是线程安全的吗 这文档 http developer android com reference java util Observable html说只有deleteObser
  • Spring @Validated 在服务层

    Hej 我想使用 Validated group Foo class 在执行方法之前验证参数的注释 如下所示 public void doFoo Foo Validated groups Foo class foo 当我将此方法放入 Spr
  • 探索java图像处理的好资源[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我是图像处理领域的新手 请推荐一些好的资源 书籍和网络链接 来学习 Java 中的图像处理 最适合隐写术分析 适合初学者和高级水平 我看过
  • 我应该使用 JDBC getNString() 而不是 getString() 吗?

    我们正在构建一个由 Oracle 数据库支持的 Java 应用程序 我们使用 JDBC 驱动程序 访问该数据库ojdbc6 jar and orai18n jar 数据库模式主要使用以下方式存储文本列NVARCHAR2数据类型 The JD
  • 限制 JPQL 中的结果数量

    如何限制从数据库检索结果的数量 select e from Entity e I need only 10 results for instance 您可以尝试像这样给出 10 个要显式获取的结果 entityManager createQ
  • 为什么我的 @OneToMany 属性出现主键违规?

    我有一个实体 Entity public class Student GeneratedValue strategy GenerationType AUTO Id private long id OneToMany private Set
  • 外部实体更改后索引不更新

    我目前正在开发一个项目 使用 JPA 2 1 保存数据并使用 hibernate search 4 5 0 final 搜索实体 映射类和索引后 搜索工作正常 但是 当我更改值时描述B 类从 someStr 到 anotherStr 数据库
  • 默认情况下,JSF 生成不可用的 ID,这些 ID 与 Web 标准的 CSS 部分不兼容

    活跃的 JSF 或 Primefaces 用户能否解释一下为什么默认情况下会发生这种情况 为什么没有人对此采取任何措施
  • EJB 中 @Stateless 相对于 @Singleton 的真正用例是什么

    如果我正确理解EJB Singleton实际上与普通Java中的Singleton相同 也是spring中的单例 gt 一个实例 每个调用同时通过同一个实例 Stateless 声明一个 bean 它可以 但不得 具有多个实例 但限制是一个
  • 如何从 Trie 中检索给定长度的随机单词

    我有一个简单的 Trie 用来存储大约 80k 长度为 2 15 的单词 它非常适合检查字符串是否是单词 但是 现在我需要一种获取给定长度的随机单词的方法 换句话说 我需要 getRandomWord 5 来返回 5 个字母的单词 所有 5
  • Java 常量枚举[重复]

    这个问题在这里已经有答案了 可能的重复 理解 Java 中的枚举 https stackoverflow com questions 1419835 understanding enums in java 为什么我们应该使用枚举而不是 Ja
  • 应用程序中空指针异常[重复]

    这个问题在这里已经有答案了 我正在尝试在我的应用程序中实施应用程序内计费 我写了这段代码 public class Settings extends PreferenceFragment ServiceConnection mService
  • 从特定 JAR 文件读取资源(文件的重复路径)

    假设您有 jar1 和artifactId 动物园 jar2 和artifactId 动物 两个 jar 都有一个具有相同路径的资源文件 例如 animals animal txt 有什么方法可以从特定的 jar 中读取该文件吗 使用 ge
  • Java给定长度的随机数

    我需要在 Java 中生成一个恰好 6 位数字的随机数 我知道我可以在随机发生器上循环 6 次 但是在标准 Java SE 中还有其他方法可以做到这一点吗 要生成 6 位数字 Use Random http download oracle
  • 线程上下文类加载器和普通类加载器的区别

    线程的上下文类加载器和普通类加载器有什么区别 也就是说 如果Thread currentThread getContextClassLoader and getClass getClassLoader 返回不同的类加载器对象 将使用哪一个
  • 使用 Commons 或 Guava 将文本文件转换为 Java Set

    我想将文件中的每一行加载到 HashSet 集合中 有没有一种简单的方法可以做到这一点 怎么样 Sets newHashSet Files readLines file charSet 使用番石榴 参考 文件 readLines http
  • 设置 Firefox 配置文件以使用 Selenium 和 Java 自动下载文件

    我想使用 Selenium WebDriver 和 Java 验证文件下载 要下载的文件为 PDF 格式 当 WebDriver 单击 AUT 中的 下载 链接时 Firefox 将打开以下下载确认窗口 我希望 Firefox 自动下载文件
  • AES 密钥是随机的吗?

    AES 密钥可以通过此代码生成 KeyGenerator kgen KeyGenerator getInstance AES kgen init 128 but 如果我有一个 非常可靠 的生成随机数的方法 我可以这样使用它吗 SecureR
  • 膨胀类 android.support.design.widget.CoordinatorLayoute 时出错

    我正在尝试运行我的应用程序 但不断收到标题中列出的错误 我读过周围的内容 人们说尝试将主题更改为 AppCombat 主题 但这似乎不起作用 以下是我遇到的错误 Process com example jmeyer27 crazytiles

随机推荐