垃圾收集是否保证程序不会耗尽内存?

时间:2010-01-19 22:00:24

标签: java

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

12 个答案:

答案 0 :(得分:22)

不,你总是可以尝试分配比现有更多的内存。

自动垃圾收集仅意味着自动收集垃圾(即未引用的存储器)(即,回收用于进一步使用)。如果你保留对它的引用,它不是垃圾,也不是收集的。

答案 1 :(得分:11)

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

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

示例

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);
  }
}

答案 2 :(得分:4)

不,还有很多方法可能会耗尽内存。垃圾收集器只能回收不再引用的对象的内存 - 由您来确保不引用不需要的对象,或者对您想要的对象使用软引用,但不要如果记忆力变紧,那就不会消失。

答案 3 :(得分:3)

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

  • 考虑你不想要的对象 再使用就像垃圾一样。
  • 对这些对象的引用将是 喜欢你的垃圾 房子。
  • 垃圾收集就像你的 镇的垃圾车收集 垃圾。
  • 如果你不释放那些 参考,就像没有采取 垃圾出来很快你的房子会 被垃圾填满了 垃圾车的家伙不会拿出来 你房子里的垃圾。

垃圾收集器会自动垃圾收集未引用的对象。在java中,一旦你退出方法,大多数对象的引用都会自动释放。

对象引用其他对象,而这些对象又引用创建整个对象图形的其他对象。因此,这样的对象可以被多个对象引用。

  • 如果对象没有引用, 它有资格获得垃圾 集合。
  • 对象在堆上分配。
  • 垃圾收集器从不间断运行 删除未引用对象的时间 来自堆。
  • 如果您继续创建更多对象 堆没有释放你会 最终获得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();
 }
}

答案 4 :(得分:2)

没有。如果构造了很多对象(数百万)并保留对它们的引用,使它们不会超出范围(例如通过将它们添加到ArrayList中),则可能会耗尽可寻址的内存。

答案 5 :(得分:1)

绝对不是。即使在像Java这样的垃圾收集语言中,您也很容易丢失引用,这意味着对象永远不会被垃圾收集。

即使这样,您也可以简单地实例化(并保持引用)太多的对象供系统处理。

答案 6 :(得分:1)

任何事情如何确保程序不会耗尽内存而不是从内存中任意删除项目以为新分配腾出空间?

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

答案 7 :(得分:0)

没有。垃圾收集只能防止一种内存泄漏。特别是,当您的应用程序不再需要时,如果您没有明确释放内存,则会发生这种情况。如果您的应用程序持有对不需要的对象的引用(例如,不断增长的列表),则垃圾收集器无法清除它们,并且您的应用程序仍然可能内存不足。

答案 8 :(得分:0)

不,完全没有。

在没有垃圾收集的语言中,程序员(或他使用的库)负责发出内存请求并返回分配的内存以进行“回收”。无法保证在请求时内存可用。但是,如果您从未明确地“回收”,则可能会出现由于没有可用内存而拒绝请求的情况,但如果内存被回收,则可能已为此请求返回该块。

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

例如,如果您的系统有1000个可用块并且您需要同时使用1500个,那么世界上没有任何GC可以帮助您,因为没有什么可用于回收。

答案 9 :(得分:0)

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

答案 10 :(得分: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();
 }

该列表将无限增长,直至内存不足

答案 11 :(得分:0)

但是,保证在JVM声明OutofMemoryException之前,它会垃圾收集所有可收集的引用并考虑使用现在的空闲内存。