Java 在此示例中,有多少对象符合垃圾收集器的条件
当Java 在此示例中,有多少对象符合垃圾收集器的条件,java,garbage-collection,Java,Garbage Collection,当m()退出时,我统计了5个符合垃圾收集器条件的元素。练习说6是正确答案。您能帮助我吗?对getCurrency()的两个调用将总共创建两个Currency对象。每次通话需要: 一个整数对象作为参数,随后分配给值 货币对象 名称字符串对象(不是静态,即每个货币对象都有一个) 3×2=6 更新: 最大的问题似乎是,是否会为对Currency构造函数的每次调用创建一个新的Integer对象。将原语int自动装箱为Integer将调用Integer.valueOf()。关于Integer.valu
m()
退出时,我统计了5个符合垃圾收集器条件的元素。练习说6是正确答案。您能帮助我吗?对getCurrency()
的两个调用将总共创建两个Currency
对象。每次通话需要:
- 一个
对象作为参数,随后分配给整数
值
对象货币
字符串对象(不是名称
,即每个静态
对象都有一个)货币
Currency
构造函数的每次调用创建一个新的Integer
对象。将原语int
自动装箱为Integer
将调用Integer.valueOf()
。关于Integer.valueOf()
,有这样的说法:
返回表示指定int值的整数实例。如果不需要新的整数实例,通常应优先使用该方法而不是构造函数整数(int),因为通过缓存频繁请求的值,该方法可能会产生显著更好的空间和时间性能此方法将始终缓存-128到127(含)范围内的值,并可能缓存此范围以外的其他值。
因此-128到127范围内的值会被缓存。但问题是,在代码中,您使用的是两个不同的值50和100,因此缓存不会避免创建新的
整数对象AFAIK。我不同意公认的答案。我相信你关于五个对象符合垃圾收集条件的回答实际上是正确的,而你所做的练习是错误的(尽管如果有人能解释我的错误,我将不胜感激)
以下是程序引用的对象:
Integer
#0-由static Integer value=new Integer()创建的Integer
*
Currency
#1-由Currency.getCurrency(50)
创建的Currency
Integer
#1-自动装箱50
返回的Integer
String
#1-由Currency
#1中的String name=new String()
创建的字符串
Currency
#2-由Currency.getCurrency(100)
创建的Currency
Integer
#2-自动装箱100
返回的Integer
String
#2-由Currency
#2的创建中的String name=new String()
创建的字符串
*这实际上并没有编译,但我假设它被有效的代码替换,否则不会影响程序
因此,代码运行需要七个对象。当value
被50
覆盖时,value
最初引用的对象将有资格进行垃圾收集。第一个和第二个Currency
s在m
结束时符合条件,因为它们的唯一引用超出了范围。当第一个和第二个字符串s的唯一引用对象Currency
s1和2超出范围时,它们在m
的末尾符合条件。来自100
的自动装箱的Integer
在最后仍然被静态引用值
引用,因此不符合垃圾收集的条件。有5个对象符合条件,1个不符合条件,还有一个尚未讨论
最后一个对象是50
的自动装箱返回的整数。您的代码显然不再引用它,因为value
被设置为reference100
。这似乎表明它有资格进行垃圾收集,但我不同意。整数
类以符合。因此,当m
退出时,缓存仍将包含对50
中已装箱的整数的引用,从而使其不符合垃圾收集的条件
我尝试使用此程序测试此行为:
public class Currency {
String name = new String();
static Integer value = new Integer();
static void getCurrency(Integer v) {
Currency c = new Currency();
c.value = v;
}
public static void m() {
Currency.getCurrency(50);
Currency.getCurrency(100);
}
public static void main(String[] argv) {
Currency.m();
}
}
表明,至少在本例中,未缓存的整数
已被垃圾收集,而缓存的整数未被垃圾收集。这表明,即使没有明确引用50
,它仍然没有资格进行垃圾收集,因为缓存中存储了引用
我承认这并不能证明什么,因为首先,System.gc()
不能保证它将收集所有(或任何)可用内存。然而,我认为这应该表明问题并不像人们想象的那么简单,而且在最常见的JDK/JVM上,第六个值不符合垃圾收集的条件是合理的
TL;DR-我不认为通过装箱50
返回的Integer
可以进行垃圾收集,因为它仍然被Integer
类维护的缓存引用。对getCurrency()
的每次调用都将创建一个Currency对象。因此,对m()
的调用将创建两个货币对象。但本例中传入的Integer
值不应该是Integer
缓存的一部分,因此不符合垃圾收集的条件吗?@Andreas抱歉,我在手机上回答了这个问题。@Vwin Yes。我不明白这会对我所说的有什么影响。我们都错了。没有对象符合GC条件,因为没有创建对象,因为new Integer()
导致构造函数Integer()未定义
编译错误,因此阻止代码运行。您能告诉我们您认为哪5个变量符合垃圾条件吗
public class Test{
public static final WeakReference<Integer> inCache = new WeakReference<>(50);
public static final WeakReference<Integer> outOfCache = new WeakReference<>(10000);
public static void main(String[] args){
System.gc();
System.out.println(inCache.get());
System.out.println(outOfCache.get());
}
}
50
null