动态内存处理 Java 与 C++
我是一名 C++ 程序员,目前正在尝试从事 Java 工作。在 C++ 工作中,我习惯跟踪动态内存分配并采用 RAII 等各种技术来避免内存泄漏。我们知道,Java 提供了垃圾收集器(GC)来处理内存泄漏。因此,在使用 Java 编程时,我们应该放弃对堆内存的所有有益的担忧,而将其留给 GC 来处理内存泄漏,或者应该有一种与没有 GC 的编程语言类似的方法,尝试处理您分配的内存,并让 GC 处理您可能会错过的内存。应该采取什么方法?两者都有什么缺点?
I am a C++ programmer currently trying to work on Java. Working on C++ I have an habit of keeping track of dynamic memory allocations and employing various techniques like RAII to avoid memory leak. Java as we know provides a Garbage Collector(GC) to take care of memory leaks.So while programing in Java should one just let go all the wholesome worries of heap memory and leave it for GC to take care of the memory leaks or should one have a approach similar to that while programming languages without GC, try to take care of the memory you allocate and just let GC take care of ones that you might miss out. What should be the approach? What are the downsides of either?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我不确定你所说的尝试处理在 GC 存在时分配的内存是什么意思,但我会尝试一些读心术。
基本上,您不应该“担心”您的记忆被收集。如果您不再引用对象,它们将被拾取。如果您创建了一种为程序的其余部分引用对象的情况,则仍然可能发生逻辑内存泄漏(例如:注册侦听器并且从不取消注册它们,例如:实现不将项目设置为
null
当从末尾删除项目时)。然而,如果您有很强的 RAII 背景,您会失望地发现 Java 中没有直接的等价物。 GC 是处理内存的一流工具,但不能保证何时(或是否)调用终结器。这意味着应用于内存的一流处理不应用于任何其他资源,例如:窗口、数据库连接、套接字、文件、同步原语等。
I'm not sure what you mean by trying to take care of the memory you allocate in presence of a GC, but I'll try some mind reading.
Basically, you shouldn't "worry" about your memory being collected. If you don't reference objects anymore, they will be picked up. Logical memory leaks are still possible if you create a situation where objects are referenced for the rest of your program (example: register listeners and never un-register them, example: implementing a vector-like collection that doesn't set items to
null
when removing items off the end).However, if you have a strong RAII background, you'll be disapointed to learn that there is no direct equivalent in Java. The GC is a first-class tool for dealing with memory, but there is no guaranteed on when (or even if) finalizers are called. This means that the first-class treatment applied to memory is not applied to any other resource, such as: windows, database connections, sockets, files, synchronization primitives, etc.
对于 Java 和 .net(我想,大多数其他 GC 化的语言),您根本不需要太担心堆内存。您需要担心的是本地资源,例如文件句柄、套接字、GUI 基元(例如字体等)。这些通常需要“处置”,从而释放本机资源。 (无论如何,他们经常将自己安排在最终确定上,但依靠这一点有点不确定。自己处理东西。)
With Java and .net (and i imagine, most other GC'ed languages), you don't need to worry much about heap memory at all. What you do need to worry about, is native resources like file handles, sockets, GUI primitives like fonts and such. Those generally need to be "disposed", which releases the native resources. (They often dispose themselves on finalization anyway, but it's kinda iffy to fall back on that. Dispose stuff yourself.)
使用 GC,您必须:
除此之外,您无法真正“管理您分配的内存”,并且尝试这样做会浪费时间。
With a GC, you have to:
Apart from that, you can't really "take care of the memory you allocate", and trying to do so would be a waste of time.
从技术上讲,您无需担心内存分配后的清理工作,因为所有对象都经过正确的引用计数,并且 GC 会处理所有事情。实际上,过度活跃的 GC 会对性能产生负面影响。因此,虽然 Java 没有删除运算符,但您最好尽可能地重用对象。
另外,Java 没有析构函数,因为对象将一直存在,直到 GC 到达它们为止。因此,Java 具有
finally
构造,您应该使用它来确保所有非内存相关资源(文件套接字等)在使用完毕后都被关闭。不要依赖finalise
方法来为您执行此操作。Technically you don't need to worry about cleaning up after memory allocations since all objects are properly reference counted and the GC will take care of everything. In practice, an overactive GC will negatively impact performance. So while Java does not have a
delete
operator, you will do well to reuse objects as much as possible.Also Java does not have destructors since objects will exists until the GC gets to them,. Java therefore has the
finally
construct which you should use to ensure that all non-memory related resources (files sockets etc) are closed when you are finished with them. Do not rely on thefinalise
method to do this for you.在 Java 中,GC 负责分配内存和释放未使用的内存。这并不意味着您可以完全忽视这个问题。
Java GC 会释放未从根引用的对象。这意味着,如果您不小心从全局上下文中删除引用(例如全局 HashMap 中的缓存等),Java 仍然可能会出现内存泄漏
。如果任何相互引用的对象簇没有从根引用,Java GC 将释放它们。即它不适用于引用计数,因此您不需要
null
所有对象引用(尽管某些编码风格确实更喜欢像 sonn 那样清除引用,因为它们不再需要了。)In Java the GC takes care of allocating memory and freeing unused memory. This does not mean you can disregard the issue alltogether.
The Java GC frees objects that have are not referenced from the root. This means that Java can still have memory leaks if you are not carefull to remove references from global contexts like caches in global HashMaps, etc.
If any cluster of objects that reference eachother are not referenced from the root, the Java GC will free them. I.e. it does not work with reference counts, so you do not need to
null
all object references (although some coding styles do prefer clearing references as sonn as they are not needed anymore.)