java - Java/Android 中现有对象的短期引用的开销

标签 java android performance memory-management

最近我看到一篇关于Android内存优化的文章,但我认为我的问题更多的是一般的Java类型。我找不到任何这方面的信息,所以如果您能为我指出一个好的资源来阅读,我将不胜感激。

我说的这篇文章可以找到here .

我的问题涉及以下两个 fragment :

非最佳版本:

List<Chunk> mTempChunks = new ArrayList<Chunk>();
for (int i = 0; i<10000; i++){
    mTempChunks.add(new Chunk(i));
}

for (int i = 0; i<mTempChunks.size(); i++){
    Chunk c = mTempChunks.get(i);
    Log.d(TAG,"Chunk data: " + c.getValue());
}

优化版本:

Chunk c;
int length = mTempChunks.size();
for (int i = 0; i<length; i++){
    c = mTempChunks.get(i);
    Log.d(TAG,"Chunk data: " + c.getValue());
}

本文还包含以下几行(与第一个 fragment 相关):

In the second loop of the code snippet above, we are creating a new chunk object for each iteration of the loop. So it will essentially create 10,000 objects of type ‘Chunk’ and occupy a lot of memory.

我努力理解的是为什么提到新对象的创建,因为我只能看到对堆上已经存在的对象的引用的创建。我知道引用本身会花费 4-8 个字节,具体取决于系统,但在这种情况下它们很快就会超出范围,除此之外我没有看到任何额外的开销。

也许创建对现有对象的引用在数量众多时被认为是昂贵的?

请告诉我我在这里错过了什么,以及两个 fragment 在内存消耗方面的真正区别是什么。

谢谢。

最佳答案

有两个区别:

非最佳:

  • i < mTempChunks.size()
  • Chunk c = mTempChunks.get(i);

最佳:

  • i < length
  • c = mTempChunks.get(i);

在非最优代码中,size()循环的每次迭代都会调用方法,并创建对 Chunk 的新引用对象被创建。最优代码中,重复调用的开销size()避免了,并且相同引用被回收。

但是,该文章的作者建议在第二非最佳循环中创建 10000 个临时对象似乎是错误的。当然,创建了 10000 个临时对象,但在第一个循环中,而不是在第二个循环中,并且没有办法避免这种情况。在第二个非最佳循环中,创建了 10000 个引用。因此,在某种程度上,它并不是最佳的,尽管作者误认为树木是森林。

进一步引用:

1. Avoid Creating Unnecessary Objects .

2. Use Enhanced For Loop Syntax .

编辑:

我被指控为江湖骗子。对于那些说打电话size()的人没有开销,我只能引用官方文档:

3. Avoid Internal Getters/Setters .

编辑2:

在我的回答中,我最初犯了一个错误:引用的内存是在编译时在堆栈上分配的。我现在意识到这种说法是错误的;这实际上是 C++ 中的工作方式,而不是 Java 中的工作方式。 Java 的世界与 C++ 是颠倒的:虽然引用的内存确实是在堆栈上分配的,但在 Java 中,甚至在运行时也会发生这种情况。心潮澎湃!

引用文献:

1. Runtime vs compile time memory allocation in java .

2. Where is allocated variable reference, in stack or in the heap? .

3. The Structure of the Java Virtual Machine - Frames .

关于java - Java/Android 中现有对象的短期引用的开销,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29421287/

相关文章:

java - 使用 JMeter 测试加载文档功能

java - 在 list 文件中设置主类的路径

android - 将 DatePickerDialog 按钮更改为文本

scala - 元组从列表中消除重复

performance - Cassandra - 单节点单表批量插入性能较差

Java 相当于 C# 泛型数组声明?

java - 密码加密并存入数据库

java - 在多个内部循环中使用大量内存

android - RxJava 2 模拟 Observable 不起作用

WPF 渲染性能缓慢