在下面的示例中,有两种功能上等效的方法:
public class Question {
public static String method1() {
String s = new String("s1");
// some operations on s1
s = new String("s2");
return s;
}
public static String method2() {
final String s1 = new String("s1");
// some operations on s1
final String s2 = new String("s2");
return s2;
}
}
但是在method1
它们的first()中,字符串“
s1”显然可用于return
语句之前的垃圾回收。在second(method2
)字符串中,“
s1”仍然可以访问(尽管从代码审查的角度来看,它不再使用了)。
我的问题是-jvm规范中是否有任何内容说明一旦在堆栈中未使用变量,便可以将其用于垃圾回收了?
编辑: 有时变量可以像完全渲染的图像一样引用对象,并且对内存有影响。
我问是出于实际考虑。我在一种方法中有大量的内存贪婪代码,并在考虑是否可以通过将这种方法分成几个小的方法来帮助JVM(一点点)。
我真的更喜欢无需重新分配代码的代码,因为它更易于阅读和推理。
更新 :根据
jls-12.6.1:
Java编译器或代码生成器可能会选择设置将不再用于为null的变量或参数,以使此类对象的存储可以尽快收回
因此,看起来GC可能会声明仍然可见的对象。但是,我怀疑这种优化是在脱机编译期间完成的(这会增加调试的难度),并且很可能将由JIT完成。
否,因为您的代码可以想像地检索它并对其进行处理,并且抽象JVM不会考虑即将出现的代码。但是,一个非常非常非常聪明的优化JVM可能会分析前面的代码,并发现s1
无法引用任何方法,并进行垃圾回收。但是,您绝对不能指望这一点。
问题内容: 我有一个Java应用程序正在泄漏内存。我知道在垃圾回收期间哪些对象没有被释放,但是我无法确定引用它们的对象。 JVM内部保存的对象图是否具有某种可见性? 否则就有可能找出哪些对象引用了另一个对象? 问题答案: 在真正的基础上,您可以使用命令jhat和jmap从正在运行的Java进程中读取堆文件,然后对其进行处理- 它在本地端口上启动小型Web服务器。它并不是很容易阅读,但是您不必购买分
我一直在研究我的代码中的一个bug,它似乎是由一些“丑陋的”终结器代码引起的。代码大致如下所示 我认为正在发生的事情是,在的第二行之后被检测为没有引用,并由终结器线程获得GCD和完成--而循环仍在发生,使用,而仍“在作用域内”。 这个可以用吗?允许java在对象超出范围之前对其进行GC吗? 注意:我知道在finalizer中做任何事情都是不好的。这是我继承并打算修复的代码--问题是我是否正确理解了
问题内容: 有没有一种方法可以检查垃圾收集器是否可以提取对象? 在我的代码中的某个地方,我有一个对象的引用: 然后,通过Eclipse Debugger,获得对象的存储位置。之后,我将引用设置为null: 有什么方法可以检查以前引用的对象现在是否适合垃圾回收,或者是否有其他引用? 非常感谢, 斯特凡 问题答案: 您无法在运行时使用任意对象执行此操作,实际上,不可能完全确定地执行此操作。但是,有两种
问题内容: 首先,我想澄清一下我的理解,因为以下问题是相同的。 上面代码的输出是 这意味着,尽管一旦GC运行,实际的对象对象就会被垃圾回收,但是内存中仍然有一个类对象,该对象此时不指向任何对象。 现在考虑到上述理解为真,我对工作原理感到困惑。在下面的代码中 输出: 现在的 问题 是,据说输入是弱引用,这意味着在上面的代码中, 成为实际对象时可以进行垃圾回收,因为不再有对该对象的强引用,但是 和作为
问题内容: 在Java中分配未使用的对象引用是否可以以任何可衡量的方式改善垃圾回收过程? 我在Java(和C#)方面的经验告诉我,尝试使虚拟机或JIT编译器胜过智能通常是反直观的,但是我看到同事使用此方法,我很好奇这是否是一个好的选择或其中一种巫术编程迷信? 问题答案: 通常没有。 但是像所有事物一样:这取决于。如今,Java中的GC非常好,应在无法访问所有内容后不久对其进行清理。这只是在为局部变
嗨,根据这里的留档https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/concurrent.html#mostly_concurrent热点JVM有两个并发收集器——CMS和G1。所以在垃圾回收机制中,这两个是并行使用的,还是只选择了一个?