Go是否会像Java一样受到微妙的内存泄漏?


89

这是事实:

  • Go语言具有垃圾回收器。

  • Java有垃圾回收

  • 许多Java程序都有(微妙的或没有的)内存泄漏

作为具有内存泄漏的Java程序的示例(并非出于胆怯,这个问题可能会动摇您的信念),请参见此处有关一个名为Tomcat的小型Java程序,该程序甚至具有“查找泄漏”按钮:有没有办法以避免在Tomcat中取消部署内存泄漏?

所以我想知道:用Go编写的程序是否会表现出与某些用Java编写的程序一样的(细微或不细微的)内存泄漏?


29
“很多Java程序都有(微妙的或没有的)内存泄漏”,您是否有证据表明这种“事实”,或者仅仅是一个话题。
彼得·劳里

17
@Webinator:我认为您需要举一个例子,说明“很多” Java程序具有的这些“细微的内存泄漏”。除非您声称垃圾收集器中有错误,否则泄漏纯Java中内存的唯一方法是坚持使用不再使用的引用,例如将对象放入集合中,并且永远不要从该集合中删除它们。如果您指的是这种泄漏,那么世界上没有任何语言会阻止它们,包括Go。
JeremyP 2010年

14
:这里有内存泄漏我谈论(+200 upvotes,与+150 upvotes的答案,很多实际的Java内存泄漏的解释)stackoverflow.com/questions/6470651/...
SyntaxT3rr0r

6
当然,JAVA程序确实存在内存泄漏,当您不再需要它们时,只需忘记将某些引用设置为null。在大型的持久性集合(如缓存)中经常发生,带有观察者设计模式或线程局部变量。这不是理论上的,我自己在生产中纠正了几次内存泄漏。这不是反Java。我是一名全职JAVA开发人员超过5年,一直从事许多不同的项目。不认识到您可能会用JAVA(或所有其他现有语言)造成内存泄漏并不是狂热,更是缺乏对事物真正工作原理的理解。
Nicolas Bousquet

6
这个问题可以不用戏剧和有关“狂热主义”,“动摇某人的信念”等的评论来解决。Esp。因为整个讨论都归结为“我的定义memory leak比您的定义更好”。
LAFK说恢复莫妮卡的时间为

Answers:


44

您在这里混淆了不同类型的内存泄漏。

基于Java(或任何其他基于GC的语言)的基于内存的令人发指的显式内存管理不再存在。这些泄漏是由于完全失去对内存块的访问而没有将其标记为未使用引起的。

在计算机可以读取我们的思想之前,Java以及地球上其他所有语言仍然存在“内存泄漏”,并且这将在可预见的将来出现。这些泄漏是由代码/程序员保留对技术上不再需要的对象的引用引起的。这些从根本上讲是逻辑错误,使用当前技术无法用任何语言阻止。


23
内存泄漏只是当您忘记释放内存时。在Java中,当您忘记将引用设置为null时,就会发生这种情况。在C ++中,如果您忘记调用free,就会发生这种情况。两者都是有效的内存泄漏情况。基本问题是一样的,您的程序会消耗越来越多的内存,直到最终由于OutOfMemory错误而崩溃。
Nicolas Bousquet

1
虽然没有一种语言可以阻止程序员犯此类逻辑错误,但是Java SDK本身也存在某些此类错误(例如,参见java.util.logging.Level包含一个私有静态ArrayList变量,所有此类构造对象都包含在其中),这确实是正确的。放置在结构上,并且永远都不会删除它们),这使得Java编程时比使用不包含此类缺陷的其他语言更难避免使用它们
Jules 2014年

7
我认为OP正在询问确实无法访问的对象的内存泄漏,例如链接问题的已接受答案。由线程加载类引起的内存泄漏。-1
qbt937

1
还可以想象,静态分析可以确定引用是否在其使用寿命内继续存在-无需仔细阅读。
凯尔·斯特兰德

1
@Amrit不,垃圾收集器收集您不再引用的内存。它无法知道是否可以删除您仍然引用的内容。
拉斐尔·施米兹

19

Go程序很可能会出现内存泄漏。Go的当前实现有一个简单的标记清除垃圾收集器。这仅用作临时解决方案,而不用作长期垃圾收集器。请参阅此页面以获取更多信息。看标题下Go Garbage Collector。如果您愿意,该页面甚至包含指向当前版本代码的链接。


1
Java中的标记和清除收集器的问题之一是内存碎片。尽管从技术上讲不是内存,但可能会丢失应用程序可用的内存。
彼得·劳瑞

9

“内存泄漏”是指程序员认为要释放的一块内存没有被释放。无论是否收集垃圾,这种情况都可能以任何语言发生。GC语言中的常见原因是保留了对内存的其他引用。

“语言不会导致内存泄漏,程序员会导致内存泄漏”。


8

无论是否收集垃圾,您都可以编写一种程序,该程序大部分都使用Java,Go或任何其他语言进行内存泄漏。

垃圾回收确实减轻了程序员的负担,但是并不能完全防止泄漏。


4
我知道我知道。我专门讲的是Java中存在的某种微妙的内存泄漏,即使在强硬的Java刚开始销售时,由于GC的存在,这种语言也没有内存泄漏语言
语法T3rr0r 2010年

4
抱歉,不清楚。您说过“许多Java程序都有(微妙的或没有)内存泄漏”。
jzd 2010年

3

您在这里混合了抽象级别:内存泄漏是由于库中的错误引起的(对象之间相互引用,尽管'a的链保持对b'的引用,以及在效率和效率之间实现垃圾收集器的折衷方案)您想花多少时间来发现这样的回路?如果您花费两倍的时间,您将能够检测到两倍长的回路。

因此,内存泄漏问题不是特定于编程语言的,没有理由认为GO本身应该比Java更好或更差。


1
我并不完全同意。内存泄漏是由于Java可以用脚射击自己,而不一定与库错误有关。许多程序员编写的程序会缓慢但肯定会泄漏Java中的内存,这是他们自己的错,而不是库的错。另外,如果Java GC正好在进行时间/可能泄漏的折衷,那么Go是否要进行相同的折衷?
语法T3rr0r,2010年

1
问题实际上不是“我想花多少时间找出这种循环?” 问题是“规范要求Go GC在此类循环上花费多少时间”,恕我直言,这是一个有趣的问题。
语法T3rr0r 2010年

16
循环引用链不会阻止Java中的垃圾回收。
安迪·托马斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.