我是一名C ++程序员,目前正在尝试使用Java。使用C ++我习惯于跟踪动态内存分配并采用各种技术(如RAII)来避免内存泄漏。我们所知道的Java提供了一个垃圾收集器(GC)来处理内存泄漏。因此,在使用Java进行编程时,应该放弃堆内存的所有健康问题并将其留给GC来处理内存泄漏,或者是有一种类似于没有GC的编程语言时的方法,尝试照顾你分配的内存,让GC处理你可能错过的内存。该方法应该是什么?两者的缺点是什么?
答案 0 :(得分:5)
我不确定你是什么意思,试图照顾你在GC存在时分配的内存,但我会尝试一些心灵阅读。
基本上,你不应该“担心”你的记忆被收集。如果您不再引用对象,它们将被拾取。如果你创建一个为程序的其余部分引用对象的情况,那么逻辑内存泄漏仍然是可能的(例如:注册侦听器并且从不取消注册它们,例如:实现类似矢量的集合,不将项目设置为{{ 1}}当删除项目时)。
但是,如果你有一个强大的RAII背景,你会感到失望,因为你知道Java中没有直接的等价物。 GC是处理内存的一流工具,但无法确保何时(或者甚至是)调用终结器。这意味着应用于内存的第一类处理是 not 应用于任何其他资源,例如:windows,数据库连接,套接字,文件,同步原语等。
答案 1 :(得分:5)
使用Java和.net(我想,大多数其他GC语言),你根本不需要担心堆内存。您做需要担心的是,文件句柄,套接字,字体等GUI原语等本机资源。那些通常需要“处置”,这释放了本机资源。 (无论如何,他们经常将自己置于最终定稿之上,但是如果再回到这一点上就有点好了。自己处理一些东西。)
答案 2 :(得分:2)
使用GC,您必须:
除此之外,你不能真正“照顾你分配的内存”,尝试这样做会浪费时间。
答案 3 :(得分:2)
从技术上讲,您无需担心在内存分配后进行清理,因为所有对象都已正确引用计数,GC将负责所有操作。在实践中,过度活跃的GC会对性能产生负面影响。因此,虽然Java没有delete
运算符,但您最好尽可能地重用对象。
此外,Java没有析构函数,因为对象将存在,直到GC到达它们为止。因此,Java具有finally
构造,您应该使用该构造来确保在完成它们时关闭所有与内存无关的资源(文件套接字等)。不要依赖finalise
方法为您执行此操作。
答案 4 :(得分:1)
在Java中,GC负责分配内存并释放未使用的内存。这并不意味着你可以完全忽视这个问题。
Java GC释放未从根引用的对象。这意味着如果您不小心从全局HashMaps中的缓存等全局上下文中删除引用,Java仍然可能存在内存泄漏。
如果未从根引用任何引用彼此的对象集群,则Java GC将释放它们。即它不适用于引用计数,因此您不需要null
所有对象引用(尽管某些编码样式确实更喜欢将引用清除为sonn,因为它们不再需要它们。)