Java 具有大量引用字段(数组除外)的对象是否会破坏热点JVM';s GC(s)堆遍历性能?
假设我定义(而不是使用引用数组,如Java 具有大量引用字段(数组除外)的对象是否会破坏热点JVM';s GC(s)堆遍历性能?,java,performance,garbage-collection,jvm,jvm-hotspot,Java,Performance,Garbage Collection,Jvm,Jvm Hotspot,假设我定义(而不是使用引用数组,如Object[]),并在应用程序中大量实例化此类 在Hotspot JVM中,当垃圾收集器遍历堆以计算可访问对象时,它会影响垃圾收集器的性能吗?或者,对于某些JVM的内部数据结构或类元数据,这可能会导致大量额外的内存消耗?或者,它是否会以其他方式影响应用程序的效率 这些方面是否特定于Hotspot中的每个垃圾收集器算法,或者Hotspot机制的那些部分是由所有垃圾收集器共享和使用的?让我重新表述一下这个问题。“下面是A级还是B级比较好?” 尽管存在常见的可维护性
Object[]
),并在应用程序中大量实例化此类
在Hotspot JVM中,当垃圾收集器遍历堆以计算可访问对象时,它会影响垃圾收集器的性能吗?或者,对于某些JVM的内部数据结构或类元数据,这可能会导致大量额外的内存消耗?或者,它是否会以其他方式影响应用程序的效率
这些方面是否特定于Hotspot中的每个垃圾收集器算法,或者Hotspot机制的那些部分是由所有垃圾收集器共享和使用的?让我重新表述一下这个问题。“下面是A级还是B级比较好?” 尽管存在常见的可维护性问题。。。从VM的角度来看,给定对类B的已解析引用,它需要一次解引用才能到达目标字段。在类A中,它需要两个解引用,因为我们还需要读取整个数组 在两种情况下对对象引用的处理有细微的不同:在类A中,VM知道有一个连续的引用数组,因此它不需要知道任何其他内容。在类B中,VM必须知道哪些字段是引用(例如,可能存在非引用字段),这需要在类元数据中维护oop映射:
// InstanceKlass embedded field layout (after declared fields):
...
// [EMBEDDED nonstatic oop-map blocks] size in words = nonstatic_oop_map_size
// The embedded nonstatic oop-map blocks are short pairs (offset, length)
// indicating where oops are located in instances of this
请注意,虽然存在占用空间开销,但这不太重要,除非您有很多这种奇怪形状的类,但即使这样,成本也将是每个类,而不是每个实例
Oop映射是在类解析期间通过共享运行时代码构建的。浏览特定对象的“oop”-s的访问者会查看这些oop映射以找到引用的偏移量,该代码也是共享运行时的一部分。因此,此开销独立于GC实现
性能注意事项:
因此,询问单独字段和数组在GC/运行时处理方面的差异可能没有什么意义。考虑引用的局部性很可能会带来更大的收益。这会导致扩展到B类,并带来相关的可维护性开销——正如许多性能技巧所做的那样。要么您的类在其字段中有引用,要么您对其插槽中有引用的
对象[]
。无论哪种方式,您都有一个对象(您的对象或数组),其中包含一组对其他对象的引用。为什么你会期望有不同?@T.J.Crowder我不知道,这就是为什么我问这个问题。但我可以很容易地想象,可能会有不同。JVM可以在许多方面特别处理数组。@T.J.Crowder是正确的。我在Hotspot VM的这一领域做了大量工作。热点GCs在引用数组和具有多个引用字段的对象之间没有区别。如果有区别的话,这不就是(手动维护的)“对象布局”吗?避免数组应该有助于避免索引/航位推算时数据相关负载所需的指针解引用。如果您使用C语言思考,那么在Java中,一切都是指针。每当你看到“对象”时,你都在使用指针。对象数组是指针数组。C中没有
操作符,它看起来像
,但工作起来像->
。即使是==
,指针的比较也应该如此。无法控制内存布局。
// InstanceKlass embedded field layout (after declared fields):
...
// [EMBEDDED nonstatic oop-map blocks] size in words = nonstatic_oop_map_size
// The embedded nonstatic oop-map blocks are short pairs (offset, length)
// indicating where oops are located in instances of this