2010-01-19 23 views
8

我听说java最优雅的属性是垃圾回收 我想知道它是否能保证程序不会耗尽内存?垃圾收集是否可以保证程序不会耗尽内存?

+4

如果垃圾收集意味着我的多TB应用程序永远不会耗尽内存,那么处理大型数据集就会非常棒。 – 2010-01-19 22:03:59

回答

10

不,它不能保证这一点。程序员完全有可能错误地创建永远不会超出范围的对象,因此消耗越来越多的内存,直到所有堆耗尽。

程序员有责任确保不再使用的对象不再被应用程序引用。这样垃圾收集器就可以完成它的工作并回收这些对象所使用的内存。

public class Main { 
    public static void main(String[] main) { 
    List<String> l = new LinkedList<String>(); 

    // Enter infinite loop which will add a String to 
    // the list: l on each iteration. 
    do { 
     l.add(new String("Hello, World")); 
    } while(true); 
    } 
} 
+0

如果你让字符串变大,你可以使内存出血更快:) – medopal 2010-01-19 22:11:01

+0

的确......尽管我已明确地调用“new”来避免引用相同的字符串字面值。 – Adamski 2010-01-19 22:43:08

2

号如果您构建了很多对象(百万),并且将它们添加到一个ArrayList保持对它们的引用,使他们不出门的范围(例如),则可能会耗尽可寻址内存。

4

不,还有很多方法可能导致内存不足。垃圾收集器只能回收不再被引用的对象的内存 - 这取决于你确保不引用不需要的对象,或者使用软引用来获得你想要的对象,但不要如果记忆变得紧张,不要在意消失。

22

不,总是有可能尝试分配比可用内存更多的内存。

自动垃圾收集仅意味着垃圾(即未被引用的内存)被自动收集(即回收以供进一步使用)。如果你保持对它的引用,它不是垃圾,也不是收集的。

1

绝对不是。即使是像Java这样的垃圾收集语言,您也很容易失去引用,这意味着对象永远不会被垃圾回收。即使到那时,您也可以简单地实例化(并继续引用)太多的对象以供系统处理。

1

怎么可能什么确保一个程序不会耗尽内存不足以从内存中任意删除一个项目,为新的分配腾出空间?

现在,如果你实际上保留一个参考(使用)随机选择被驱逐的东西?你很快会有不正确的行为。

0

编号垃圾收集只防止一种内存泄漏。具体而言,如果您的应用程序不再需要时未明确释放内存,则会发生这种情况。如果您的应用程序持有对不需要的对象的引用(例如,不断增长的列表),则垃圾回收器无法清除它们,并且您的应用程序仍可能耗尽内存。

0

不,完全没有。

在没有垃圾收集的语言中,程序员(或他使用的库)负责提出内存请求并返回分配的内存以“回收”。没有保证内存在请求时可用。但是,如果您从不显式“回收”,则可能会出现由于没有可用内存而拒绝请求的情况,但是如果内存已回收,则可能已针对此请求返回了该块。

自动垃圾回收意味着系统可能为您回收。因此,某些请求将使用“回收”内存填充。但是,与非GC语言一样,某些请求无法填充。

举例来说,如果你的系统有可用的1000块,你需要1500的同时,世界上没有一个GC是要帮助你,因为没有什么是真正可供回收利用。

0

不,垃圾回收不能保证你的应用程序不会耗尽内存。它甚至不保证当内存可用时你的应用程序不会耗尽内存。如果您接近耗尽内存或正在分配多个对象,它可能会导致GC出现异常,从而导致内存不足异常。当程序使用所有物理内存(实际和虚拟)或程序超过JVM允许的最大内存时(参见-Xmx),该程序也可能会耗尽内存。

0

不可以。垃圾回收器可以帮助您自动释放未使用的内存。

它的工作原理是,如果一个对象引用不能达到,该对象的存储器可被垃圾收集的方法。

例如:

public void test() { 
    Object o = new Object(); 
    // the memory used by o may be garbage collected after this line 
} 

但是,如果你从来没有释放对象的引用,垃圾回收器绝不会收集任何与OutOfMemoryError异常将被抛出。

List list = .... 
public void test() { 
    o = new Object(); 
    list.add(o); 
    // the memory used by o WON'T be garbage collected after this line 
    // because its reference is used in the list. 
} 

如果使用这几次:

while(true) { 
    test(); 
} 

名单将继续增长下去,直到你耗尽内存

3

要回答你的问题,NO。垃圾收集不能保证程序不会耗尽内存。

  • 考虑你不想要的对象 使用更多就像垃圾一样。
  • 引用这些对象将是 就像在你的 房子的垃圾。
  • 垃圾收集是喜欢收集垃圾 您 镇上的垃圾车。
  • 如果你不释放那些 引用,这就像没有采取 垃圾出来,很快你的房子将 超过堆满了垃圾作为 垃圾车的家伙会不会拿出从你的房子 垃圾。

未引用的对象都将被垃圾通过垃圾收集器自动收集。在java中,一旦你脱离方法,大多数对象的引用都会自动释放。

对象有参照其它的目的,这反过来又referr创建整个对象图的其他对象。所以这样的对象可以被多个对象引用。

  • 如果对象是具有零个引用, 它是符合垃圾收集 。
  • 对象分配在堆上。
  • 垃圾收集器从时间运行到 从堆中删除未引用对象 的时间。
  • 如果你一直不释放创造上 堆更多的对象,你会 最终得到OutOfMemoryError

实例与垃圾收集工作

public class TestGarbageNoError { 

public static void main(String[] args) { 
    String hugeString; 
    for (int i = 0; i < Integer.MAX_VALUE; i++) { 
    System.out.println("i = " + i); 
    hugeString = getHugeString(); 
    // At each iteration reference variable hugeString 
    // points to new String object. Hence there will be 
    // zero reference to previous string object and will 
    // eventually be garbage collected 
    } 
} 

public static String getHugeString() { 
    StringBuilder sb = new StringBuilder(); 
    for (int x = 0; x < 5000000; x++) { 
    sb.append(x); 
    } 
    return sb.toString(); 
} 
} 

内存泄漏示例工作

public class TestGarbageError { 

public static void main(String[] args) { 
    Collection<String> memoryLeak = new ArrayList<String>(); 
    for (int i = 0; i < Integer.MAX_VALUE; i++) { 
    System.out.println("i = " + i); 
    String hugeString = getHugeString(); 
    memoryLeak.add(hugeString); 
    // At each iteration reference variable hugeString 
    // points to new String object. But all objects are added 
    // to memoryLeak Collection and will always have atleast one 
    // reference, i.e. from memoryLeak object. Hence this string 
    // objects will never be garbage collected and program will 
    // eventually run out of memory 
    } 
} 

public static String getHugeString() { 
    StringBuilder sb = new StringBuilder(); 
    for (int x = 0; x < 5000000; x++) { 
    sb.append(x); 
    } 
    return sb.toString(); 
} 
} 
+0

不理解它,在第二个例子中,String是在for循环中定义的,所以每个迭代指针在堆栈中丢失,可能会被新的指针覆盖(我的方式看看事情是怎么回事)。请解释这个String对象在每次迭代时会发生什么...... – 2010-01-20 08:15:02

+0

您错过了“memoryLeak.add(hugeString);”这一行。这是由于哪个内存泄漏而引用每个字符串的地方。尝试运行这两个程序,你会看到结果的差异。 – 2010-01-20 15:39:30

+0

啊......是的,现在我看到了多余的线。 Offcourse,如果某处存在代码memoryLeak.get(..),则objetc必须持有对String的引用。我认为有什么东西与定位的地方StringStringString放置... – 2010-01-21 13:22:52

0

但是,保证了JVM声明OutOfMemoryException异常之前,将垃圾收集所有收藏引用,并考虑使用现在的可用内存。