2014-09-30 156 views
0

我在一次采访中被问到垃圾收集问题。Java:垃圾回收

下面是一段代码。

List<String> a=new ArrayList<String>(); 
    a.add("one"); 
    a.add("two"); 
    a.add("three"); 
    a.add("four"); 

HashSet<String> h=new HashSet<String>(); 
h.add("four"); 
h.add("five"); 
h.add("six"); 

h.addAll(a); 
a=null; 

的问题是:有多少个对象符合垃圾收集>

请解释。

+1

海事组织唯一正确答案是:*不可能告诉*。 :-)我们不知道'String','HashSet'和'ArrayList'在内部创建了多少个对象。 – NPE 2014-09-30 06:23:32

+0

另一个不可能说明的原因是,没有人明确说明要评估问题的确切时间。最后一次分配后,或方法结束后? – 2014-09-30 06:32:34

+0

@NPE其实,我们至少用openjdk来做。唯一的用户可见GC符合条件的对象是ArrayList,它[分配一个](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/ util/ArrayList.java#ArrayList.0DEFAULT_CAPACITY)'Object [10]'。所以答案是两个。 – maaartinus 2014-09-30 06:32:37

回答

3

本地范围内可见对象的一般答案:只有ArrayList。通过范围内的本地变量h可以访问HashSet,通过HashSet可以访问字符串。只有不可访问的对象才有资格进行垃圾回收。

注:

  1. 字符串字面具体可以在字符串池中进行分配,在注释中。在这种情况下,这些对象将无法进行垃圾回收。

  2. 只能通过特殊类型的引用(如弱引用)才能访问的对象可能仍然符合条件。

  3. 把这整件事情用一粒盐,因为这是一个关于实践中复杂的主题的理论面试问题。例如,您不知道在幕后分配了哪些其他对象。或者可能存在积极的GC,即使它们(从语言的角度来看)可访问,如果它可以证明没有其他用途,它们也可以收集对象。

+1

实际上,字符串将被放置在字符串池(文字)中,所以你答案的第二部分是部分有效的。 – TheLostMind 2014-09-30 06:23:06

+1

@TheLostMind取决于JVM字符串的版本将在permgen堆中的字符串池(永远不会垃圾回收)或常规堆中(自java 7以来)。如果不再需要,他们会定期收集。 – SimY4 2014-09-30 06:32:02

+1

@ SimY4 - 我知道。这就是为什么我没有投票或说他错了。我只是指出他是部分有效的。 – TheLostMind 2014-09-30 06:34:08

1
List<String> a=new ArrayList<String>(); 
    a.add("one"); --> "one" is added to the String constants pool and the reference is added to th arraylist 
    a.add("two"); --> same as above 
    a.add("three"); --> same as above 
    a.add("four"); --> same as above 
// 4 String literals in string pool, 4 references to them in the array list. 

HashSet<String> h=new HashSet<String>(); 
h.add("four");--> "four" is added to the String constants pool and the reference is added to the hashSet 
h.add("five"); 
h.add("six"); 
// even if you don't use h.addAll(), only 1 object i.e, a will be ready for GC once you set it to null because String literals in the constant pool cannot get GCed. 
//h.addAll(a); 
a=null; 


PS : System.out.println(a.get(0) == "one"); returns true . same applies to elements of HashSet 
1

既然你已经有了

a = null; 

,如果有持有到列表或引用其包含的对象没有其他对象,这将是符合垃圾回收。另外要知道,JVM何时会在其上运行垃圾收集和释放内存并不能保证。