java如何遍历引用数组对象_关于java:具有大量引用字段(数组除外)的对象是否会破坏Hotspot JVM的GC堆遍历性能?...

想象一下,我定义了一个具有数十个引用字段的类(而不是使用诸如Object[]之类的引用数组),并在应用程序中大量实例化了该类。

当它遍历堆以计算可访问对象时,会影响Hotspot JVM中垃圾收集器的性能吗? 或者,对于某些JVM的内部数据结构或类元数据,这可能会导致大量额外的内存消耗? 还是会以其他方式影响应用程序的效率?

是Hotspot中每种垃圾收集器算法的特定方面,还是所有垃圾收集器都共享和使用Hotspot机制的那些部分?

您的类在其字段中具有引用,或者您对Object[]的引用–在其插槽中具有引用。无论哪种方式,您都有一个对象(您的数组)或对其他对象的引用。您为什么期望会有区别?

@ T.J。Crowder我不知道,这就是为什么我问这个问题。但是我很容易想到可能会有所不同。 JVM可以通过多种方式专门处理数组。

@ T.J。Crowder是正确的。 Ive在Hotspot VM中在此领域进行了广泛的工作。引用数组与具有多个引用字段的对象之间的热点GC并无区别。

如果有的话,这难道不等于(手动维护的)对象布局吗?避免使用数组应该有助于避免在建立索引/死锁重新定位时依赖于数据依赖的加载所需的指针取消引用。

如果您想用C语言编写代码,那么在Java中,一切都是指针。每当您看到"对象"时,就使用指针。对象数组是指针数组。 C没有.运算符,它看起来像.,但是却像->一样工作。甚至==都可以准确地进行指针比较。无法控制内存布局。

我再改一下这个问题。"在下面开设A级或B级会更好吗?"

class A {

Target[] array;

}

class B {

Target a, b, c, ..., z;

}

尽管存在常见的可维护性问题,但是...从VM的角度来看,给定已解析的对B类的引用,它需要一个取消引用才能到达Target字段。在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-map是在类解析期间通过共享的运行时代码构建的。为特定对象走" oop" -s的访问者会查看那些oop-map以查找引用的偏移量,并且该代码也是共享运行时的一部分。因此,此开销与GC实施无关。

性能注意事项:

Oop-map是分块的:相邻参考字段的运行将形成一个连续的oop-map块,就像访问引用数组中的连续oop块一样,访问该块非常相似。

GC(标记)的性能取决于它必须遵循的引用数,而取消引用的内存延迟将是一阶效应。请注意,在A类中,我们必须遍历更多引用。

如果请求的索引不是常量并且关键代码路径上的数组长度未知,则在A类情况下,空检查和数组边界检查可能很重要。相比之下,字段是静态绑定的,并且它们的偏移量始终是已知的。

因此,询问独立字段与数组的GC /运行时处理的区别可能毫无意义。考虑参考的局部性很可能会带来更大的收益。这将级别扩展到B级,并带有相关的可维护性开销-就像许多性能技巧一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值