Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/git/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中的游荡对象垃圾收集_Java_Garbage Collection - Fatal编程技术网

Java中的游荡对象垃圾收集

Java中的游荡对象垃圾收集,java,garbage-collection,Java,Garbage Collection,我在读Java中的垃圾收集,偶然发现了游荡的对象 这些对象被分配了内存,但没有被使用,也没有被垃圾收集。这些会不断增加JVM堆的大小,并表示内存泄漏,这可能会导致内存不足错误或垃圾收集器的开销过大 任何人都可以提供这些游荡对象的代码示例。任何可以从GC根目录访问的对象都没有资格进行垃圾收集。GC根可能包括静态字段、线程本地存储和任何线程的堆栈 private static Object fieldThatIsNeverAccessed = new VeryLargeObject(); 即使在初

我在读Java中的垃圾收集,偶然发现了游荡的对象

这些对象被分配了内存,但没有被使用,也没有被垃圾收集。这些会不断增加JVM堆的大小,并表示内存泄漏,这可能会导致内存不足错误或垃圾收集器的开销过大


任何人都可以提供这些游荡对象的代码示例。

任何可以从GC根目录访问的对象都没有资格进行垃圾收集。GC根可能包括静态字段、线程本地存储和任何线程的堆栈

private static Object fieldThatIsNeverAccessed = new VeryLargeObject();
即使在初始化后从未访问上述字段,其值以及该值直接或间接引用的任何对象仍将驻留在堆中。

公共类缓存{
public class Cache {
    private static Map<String, Integer> cache = new HashMap<>();

    public static Integer compute(String s) {
        if (cache.containsKey(s) {
            return cache.get(s);
        }
        else {
            Integer result = performComputation(s);
            cache.put(s, result);
            return result;
        }
    }

    private static Integer performComputation(String s) {
        ...
    }
}
私有静态映射缓存=新HashMap(); 公共静态整数计算(字符串s){ if(cache.containsKey){ 返回cache.get; } 否则{ 整数结果=性能计算; cache.put(s,result); 返回结果; } } 专用静态整数性能计算(字符串s){ ... } }

上述方法试图通过使用计算值缓存来加快重复值的计算速度,这是一种明智的做法。但由于旧条目从未被删除,缓存会不断增长,直到没有可用的内存。

旧问题,但我想我可能会将其清除。我发明了术语“游荡对象”这些对象仍被应用程序引用,但在语义上不再有用。游荡对象和泄漏对象之间的区别在于游荡对象最终会消失。游荡的一个主要示例是附加到HTTP会话的对象。会话将超时,连接的对象将消失但与此同时,他们将为过度内存消耗带来的所有问题负责

在“正常”内存泄漏的情况下,泄漏对象永远不会消失。这是应用程序逻辑中的一个缺陷,在这个缺陷中,您最有可能在技术上调整您的方法,以摆脱游荡的情况,解决正常内存泄漏的唯一方法是以后编写代码


虽然游荡和泄漏的结果可能相同,但区分两者有助于早期诊断问题。通常情况下,用户会在对话中抱怨内存不足错误。如果JVM能够从内存不足错误状态中恢复,那么您可以非常有信心您有一个游荡对象。在这种情况下,您可以查找断开保留在不需要的数据上的引用的用例。在大多数情况下,这将是一个计时器。JVM永远不会从正常内存泄漏中恢复。

以下代码演示了使用数组实现堆栈,并提供了一个非常简单的游荡示例:

public class FixedCapacityStackOfStrings {

private String[] array;
private int N = 0;

public FixedCapacityStackOfStrings(int capacity) {
    array = new String[capacity];
}

public boolean isEmpty() {
    return N == 0;
}

public void push(String item){
    array[N++] = item;
}

public String pop(){
    return array[--N];
}}
请注意,在代码中递减N的值时:数组[--N], 实际上,它将指针移到N-1处的索引,并将N处的索引移到null。 这里一个指针仍然指向null,尽管我们知道我们没有使用它,但JVM不知道。因此导致游荡,因为这个指针不会被JVM垃圾收集,即使它是null

我们可以通过如下更改代码来改进这一点:

public String pop(){
    String s = array[--N];
    array[N] = null;
    return s;
}
这个版本避免了游荡,如果没有未完成的引用,垃圾收集器可以回收内存


<>希望有帮助!

你能给我们提供一个对象的例子吗?从技术上讲,java在C++开发者的理解中不会有内存泄漏。游荡对象是描述所谓“内存泄漏”的另一种方式。在Java中,+1中包含了一个实际展示问题中提到的增长问题的示例。