Java内存管理的一些最佳实践是什么?

Java内存管理的一些最佳实践是什么?,java,memory-management,Java,Memory Management,我从以前的开发人员那里接管了一些应用程序。当我通过Eclipse运行应用程序时,我看到内存使用量和堆大小增加了很多。经过进一步的调查,我发现他们在循环中一遍又一遍地创建一个对象以及其他东西 我开始做一些清理工作。但我经历的越多,我问的问题就越多,比如“这真的有什么用吗?” 例如,不是在上面提到的循环外声明变量,而是在循环中设置其值。。。他们在循环中创建了对象。我的意思是: for(int i=0; i < arrayOfStuff.size(); i++) { String som

我从以前的开发人员那里接管了一些应用程序。当我通过Eclipse运行应用程序时,我看到内存使用量和堆大小增加了很多。经过进一步的调查,我发现他们在循环中一遍又一遍地创建一个对象以及其他东西

我开始做一些清理工作。但我经历的越多,我问的问题就越多,比如“这真的有什么用吗?”

例如,不是在上面提到的循环外声明变量,而是在循环中设置其值。。。他们在循环中创建了对象。我的意思是:

for(int i=0; i < arrayOfStuff.size(); i++) {
    String something = (String) arrayOfStuff.get(i);
    ...
}
for(int i=0;i

String something = null;
for(int i=0; i < arrayOfStuff.size(); i++) {
    something = (String) arrayOfStuff.get(i);
}
String something=null;
对于(int i=0;i

我说底部循环更好是不对的吗?也许我错了

另外,在上面的第二个循环之后,我将“something”设置回null,怎么样?那会清除一些记忆吗

在这两种情况下,我可以遵循哪些良好的内存管理最佳实践来帮助我在应用程序中保持较低的内存使用率

更新:


我感谢大家迄今为止的反馈。然而,我并不是真的在询问上述循环(尽管根据您的建议,我确实回到了第一个循环)。我正在努力寻找一些我可以关注的最佳实践。“当你使用完一个集合后,把它清除掉”这句话中的某些内容。我只需要确保这些应用程序占用的内存不会太多。

不要试图智胜虚拟机。第一个循环是建议的最佳实践,包括性能和可维护性。在循环后将引用设置回null不能保证立即释放内存。当您使用尽可能小的范围时,GC将尽其最大努力

(从用户的角度)详细介绍这些内容的书籍包括和


如果您想了解更多关于性能和虚拟机内部的信息,您需要查看对话或阅读书籍。

这两个循环是等效的,除了
something
的范围之外;有关详细信息,请参阅


一般最佳做法?嗯,让我们看看:除非有充分的理由,否则不要在静态变量中存储大量数据。处理完大型对象后,从集合中删除它们。哦,是的,“测量,不要猜测。”使用探查器查看内存分配的位置。

这两个循环使用的内存量基本相同,任何差异都可以忽略不计。“stringsomething”只创建对一个对象的引用,而不是一个新对象本身,因此使用的任何额外内存都很小。另外,编译器/虚拟机与JVM的结合可能会优化生成的代码

对于内存管理实践,您应该尝试更好地分析内存,以了解瓶颈实际在哪里。尤其要注意指向大块内存的静态引用,因为它们永远不会被收集

您还可以查看弱引用和其他专门的内存管理类

最后,请记住,如果一个应用程序占用内存,可能是有原因的

更新内存管理的关键是数据结构,以及您需要/何时提供多少性能。这种折衷通常是在内存和CPU周期之间进行的

例如,缓存可以占用大量内存,这是为了提高性能,因为您试图避免昂贵的操作


因此,请仔细考虑您的数据结构,并确保您在内存中保存的时间不会超过必须的时间。如果是web应用程序,请避免将大量数据存储到会话变量中,避免对大量内存池进行静态引用等。

第一个循环更好。因为

  • 变量something将更快地清除(理论)
  • 该程序更易于阅读
但从记忆的角度来看,这是不相关的


如果您有内存问题,那么您应该分析它的使用位置。

在两个代码示例中都没有创建对象。只需将对象引用设置为arrayOfStuff中已有的字符串。所以记住,没有区别。

好吧,第一个循环实际上更好,因为某些东西的范围更小。关于内存管理,它没有太大区别


大多数Java内存问题发生在将对象存储在集合中,但忘记删除它们时。否则GC会使他的工作非常出色。

第一个示例很好。这里没有任何内存分配,除了每次通过循环进行堆栈变量分配和释放(非常便宜和快速)

原因是“分配”的只是一个引用,它是一个4字节的堆栈变量(无论如何,在大多数32位系统上)。堆栈变量是通过添加到表示堆栈顶部的内存地址来“分配”的,因此非常快速且便宜

您需要注意的是循环,如:

for (int i = 0; i < some_large_num; i++)
{
   String something = new String();
   //do stuff with something
}
for(int i=0;i

因为这实际上是在进行内存分配。

JVM最擅长释放短期对象。尽量不要分配不需要的对象。但是,在了解工作负载、对象生存期和对象大小之前,无法优化内存使用。探查器可以告诉您这一点

最后,你必须避免做的一件事:永远不要使用终结器。终结器会干扰垃圾收集,因为对象不能被释放,但必须排队等待终结,这可能会发生,也可能不会发生。最好不要使用终结器

至于m