今天,我们的主题是有关Java内部内存泄漏的信息。 等待!? Java中的内存泄漏? 那不可能吧? 这不是Java的承诺之一,即拥有托管内存吗? 当我开始学习代码时,我像人一样开始使用C ++。 让我告诉您一些事情,如果您在C ++中不能很好地管理内存,则可能会感到震惊。 但是无论如何,我们都在谈论Java中的内存泄漏。 我认为最好的方式是举一个例子,我认为本书中的例子就是一个很好的例子:
public class Stack {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_SIZE = 16;
public Stack() {
elements = new Object[DEFAULT_INITIAL_SIZE];
}
public void push(Object element) {
ensureCapacity();
elements[size++] = element;
}
public Object pop() {
if (size == 0) {
throw new EmptyStackException();
}
return elements[--size];
}
private void ensureCapacity() {
if(elements.length = size) {
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
}
看起来可以正常工作吗? 我让你秘密。 该代码确实可以正常工作,但确实存在“内存泄漏”。 你能发现吗? 我肯定没有马上做到这一点。 问题在于我们这条线流行音乐功能。:
return elements[--size];
那么这条线怎么了? 代码在概念上所做的是返回一个对象并将其从堆栈中删除。 实际发生的是元素 array still has a reference to the object and won't be able to be garbage collected until that element is overwritten. So if, for example, a bunch of objects were added to the stack and then popped off we would expect the 元素 to be garbage collected but they will not.
但这实际上是内存泄漏吗? 不是这个词的正常含义。 更正确地说,它们可以被称为“过时的对象引用”。 话虽这么说,其可能引起的症状和问题是相同的。 那么我们如何解决这个问题。 好吧,很简单,我们在返回之前将对象归零:
public Object pop() {
if (size == 0) {
throw new EmptyStackException();
}
Object poppedObject = elements[--size];
elements[size] = null;
return poppedObject;
}
所以我是说您应该在处理完所有对象后将其清空? 请不。 必须清空对象几乎总是例外,而不是规则。 Java确实是一种具有托管内存的语言,当对象超出范围并丢失对它们的所有引用时,它将处理对象的清除。 那么,在什么情况下我们需要解决上述问题,而在什么时候不解决? 归结为是否要管理自己的内存/对象。 如果您要管理内存,则需要完全使用它并进行管理,而不仅仅是半途而废。 上面,我们自己管理内存,因为我们拥有要作为存储管理的元素数组。
我们还看到其他哪些地方。 缓存是另一个例子。 当我们使用高速缓存时,我们需要注意高速缓存中数据的生命周期,因为即使系统中没有其他对象会从高速缓存中请求对象,高速缓存也可以防止对象被垃圾回收。 解决此问题的一种方法是使用Java弱参考 class. We do need to be aware that when using this class it is simply a pointer to the object and is counting on an external system having a reference to the object to keep it from being garbage collected while it is still usable. Using 弱参考s and related classes are a more advanced topic and how to intelligently use it is beyond the scope of this blog article. A final location that developers can leave around obsolete objects is when using listeners and other callbacks. I remember this being of particular concern when working with Android in a previous life of mine. This can be accounted for in the same manner as above with the use of 弱参考s
毫无疑问,今天的讨论主题更加利基。 您可能不会每天都遇到这种情况,但这是我们开发软件时要记住的一件事。 内存泄漏很难调试,因此我们应该尽一切努力避免泄漏。