2

q(除此之外 - 我不确定对于创建但未存储在变量中的对象的术语是什么)。

我真的不知道如何很好地表达我的问题,所以我将说明它。

示例一,声明了两个对象:

Random random = new Random();
for (int i = 0; i < 10000000; i += 1){
    Integer integer = new Integer(random.nextInt());
    String string = integer.toString();
}

仅声明一个对象的示例二:

Random random = new Random();
for (int i = 0; i < 10000000; i += 1){
    String string = (new Integer(random.nextInt())).toString();
}

在第二个示例中,仍创建了 Integer 对象,但未保存其在内存中的位置(我认为)。我知道将对象创建减少一个似乎微不足道,但是在具有许多迭代的大循环中,将对象引用减半肯定是有益的。这种技术是否可以节省内存(即最小化垃圾收集)?

编辑:更改示例以更好地说明问题。

4

4 回答 4

1

无论是两种方法中的一种,在这两种方法中都有在单次迭代范围内创建的两个对象。一旦迭代完成,两者都有资格获得gc.

现在,IMO GC minor cycle(在这种短期对象的特定情况下)不会每次迭代,并且会在相关空间充满 GC 对象时发生(检查jstat -gcutil),您选择哪种方法都没有关系,因为两者都会给你类似的内存统计。

于 2013-07-21T05:03:31.663 回答
1

这种技术是否可以节省内存(即最小化垃圾收集)?

事实上,你问的是两个不同的问题。答案是“否(在实践中)”和“否”。

(这适用于问题的原始版本和更新版本。)


第一个答案需要一点解释。

在第一个示例中,如果这是在循环中,则stringandinteger变量将多次超出范围,或者将被多次覆盖。(在您的示例中,它们超出了范围。)

如果其中任何一种发生,变量的当前值将被“遗忘”,相应的对象将变得无法访问。

在第二个示例中,您没有将Integer对象放入变量中,因此相应的对象可能会在几纳秒前变得无法访问。但由于这段代码在循环中,所以差异可以忽略不计。事实上,它可能是无法衡量的。


第二个答案更容易解释。如果两个分配之一(即创建 的语句或创建的语句)需要比立即可用的内存更多的内存,您的代码只会触发垃圾收集。由于这两个代码位执行相同的分配,因此GC 运行的次数没有差异。newIntegerInteger.toString()String


另一点是,在 Java 中以这种详细程度考虑这些事情只是浪费时间。一般来说,垃圾收集器只负责处理事情。在这个特定示例中,“优化”的最大理论优势是单个Integer对象可能会在垃圾回收周期更早地被释放。该对象占用大约 16 个字节。这根本不值得考虑。

您正在做的事情在业内被称为“过早优化”。不要在上面浪费时间。如果你需要优化,等到你有一个工作程序,然后分析它。然后将精力花在分析器认为有问题的部分上。

于 2013-07-21T05:02:21.703 回答
0

这是一个过早的优化,您可能永远不需要这样做。

但是,是的。只要integer永远不会超出范围,就永远不会被垃圾收集。

于 2013-07-21T04:27:55.503 回答
0

无法访问的对象将有资格进行垃圾收集(在您的情况下new Integer(5)

请参阅调整垃圾收集,但我怀疑您是否需要这样做

于 2013-07-21T04:31:13.210 回答