Java中Object数组赋值:1.4倍容量为何比1.3倍耗时大幅减少?
问题分析:Java数组容量差异导致赋值耗时巨大差距
测试代码
public class Test { public static void main(String[] args) { testObject(1.3); testObject(1.4); } private static void testObject(double num) { System.out.println("test:" + num); long sta = System.currentTimeMillis(); int size = 10000000; Object[] o = new Object[(int) (size * num)]; for (int i = 0; i < size; i++) { o[i] = "" + i; } System.out.println("object[]: " + (System.currentTimeMillis() - sta) + " ms"); } }
执行结果
test:1.3 object[]: 7694 ms test:1.4 object[]: 3826 ms
核心原因:内存分配与GC触发差异
这个差异的本质不是数组赋值机制本身,而是数组大小差异导致JVM内存分配策略变化,进而触发了不同次数的垃圾回收(GC):
- 内存占用计算:64位JVM中每个Object引用占8字节,1.3倍size的数组(1300万元素)约占104MB,1.4倍数组(1400万元素)约占112MB。循环中创建的1000万个字符串对象,每个包含char数组和对象头,总内存也达几十MB级别。
- 新生代GC触发差异:默认JVM新生代(Eden区)初始大小通常在128MB左右。创建1.3倍数组时,数组本身占用104MB,加上循环生成的字符串,会快速填满Eden区,触发多次Minor GC——GC会暂停应用线程,大幅增加总耗时。而1.4倍的数组属于大对象,JVM会直接将其分配到老年代,避免占用新生代空间。此时新生代有足够容量容纳字符串对象,全程无Minor GC触发,耗时自然大幅降低。
- 验证方式:若启动JVM时添加
-XX:+PrintGCDetails参数,可清晰看到1.3倍场景下的GC日志,1.4倍场景则几乎无Minor GC记录,直接验证上述结论。
内容的提问来源于stack exchange,提问作者jarome
相关产品推荐
相关产品推荐

