JVM中的垃圾回收
垃圾回收是JVM中的一个重要概念,它的出现是为了解决JVM内存空间不足的问题。当JVM没有足够的内存空间运行时,垃圾回收器将会运行并删除不必要的对象,以释放内存空间。
不必要的对象是指没有其他引用(地址)指向它们的对象。一个对象可以通过以下4种方式成为垃圾回收的候选对象:
1. 空引用
当一个对象的引用变量被赋予null
值时,垃圾回收器可以删除该对象。
A a = new A(); a = null;
2. 重新赋值
当另一个对象被赋值给一个对象的引用变量时,旧的被引用对象可以被垃圾回收器删除。
A a = new A(100); a =new A(200);
3. 局部作用域
如果一个对象在一个代码块内被创建,那么该对象在该代码块外将成为垃圾回收的候选对象。
if(condition){ A a = new A(); }
4. 孤立对象
一个对象可以包含对另一个对象的引用,但是在栈中必须至少有一个引用变量指向这些对象,否则所有这些对象都将成为垃圾回收的候选对象。
class A{ A r; A(int i){ //something } } A a1 = new A(100); a1.r = new A(101); a1.r.r = new A(102); a1.r.r.r = a1; a1 = null //所有对象都可以被垃圾回收器回收
通过垃圾回收机制,JVM能够自动识别和释放不再使用的内存空间,从而提高内存的利用率和程序的性能。
垃圾回收(Garbage Collection)是Java虚拟机(JVM)中的一个重要特性,它负责自动管理内存。垃圾回收的出现是为了解决手动内存管理所带来的问题。以下是导致垃圾回收出现的原因以及解决方法:
原因:
1. 程序的运行方式取决于程序的即时编译(JIT)。
2. 从外部无法确定垃圾回收何时运行。
3. 垃圾回收遵循特定的算法,这取决于具体的垃圾回收机制。
4. Java虚拟机运行在客户端机器上,具有一定的虚拟内存大小,例如Windows默认为4GB。垃圾回收还依赖于特定时间的可用虚拟内存。
解决方法:
通过上述提到的小程序可以检查垃圾回收的行为。以下是一个示例程序:
public class GCTest { final int NELEMS = 50000; void eatMemory() { int[] intArray = new int[NELEMS]; for (int i=0; i
可能的输出结果(每次运行可能不同):
创建数组前的可用内存:4054912 创建数组后的可用内存:3852496 运行垃圾回收后的可用内存:4064184
以上是垃圾回收在JVM中出现的原因以及解决方法的详细内容。如需更多信息,请查看此链接:[http://www.devdaily.com/java/edu/pj/pj010008/](http://www.devdaily.com/java/edu/pj/pj010008/)。
垃圾收集(Garbage Collection,简称GC)是Java虚拟机(JVM)中的一项重要功能,它的出现是为了解决内存管理的问题。在JVM中,垃圾收集器会在确定需要运行时进行垃圾回收。一种常见的策略是在分配第0代内存失败时运行垃圾收集器。也就是说,每次分配一小块内存时(大块内存通常直接放入“较旧”的代),系统都会检查第0代堆中是否有足够的空闲空间,如果没有,则运行垃圾收集器以释放空间以便分配成功。
然后,旧数据被移动到第1代堆中,当第1代堆空间不足时,收集器会在其中进行垃圾回收,并将最长时间存在的数据升级到第2代堆中,依此类推。因此,垃圾收集器并不仅仅是“运行”。它可能仅在第0代堆中运行(大多数垃圾收集将只在第0代堆中进行),或者如果确实需要释放大量内存,则可能检查每一代。
然而,这远非唯一的策略。并发的垃圾收集器可以在程序运行时进行后台清理。某些垃圾收集器可能会作为每次内存分配的一部分运行。增量式收集器可能会在每次内存分配时扫描一些对象。
垃圾收集器的整个目的是在不需要用户输入的情况下完成其工作。因此,通常情况下,您无法预测垃圾收集器何时运行,也不应该这样做。
Java虚拟机在Java 1.2版本开始使用分代收集器,这是为了解决垃圾回收后堆内存碎片化的问题。JDK 1.3版本以后,Java虚拟机采用了更先进的分代收集器。Java 6还引入了垃圾优先(Garbage-First)垃圾收集器(G1),它在Java 6u14版本中首次提供。G1垃圾收集器不是默认启用的,而是作为并发收集器的替代方案。它旨在提供更可预测的性能,并通过内存区域设计实现快速分配。
至于垃圾收集器是否永远移动到较高的代,而不是真正删除它,这取决于具体的实现。一般来说,当垃圾被识别时,它会被释放。分代收集器只会检查某些对象是否为垃圾。它会频繁检查新创建的对象(第0代)是否可以被释放。如果一个对象存活时间足够长,达到某个阈值,那么它会被放入第1代,这意味着在正常、快速的垃圾收集过程中,垃圾收集器不会检查它。不时地,垃圾收集器会检查第1代对象,看是否有任何垃圾可以释放,而在更少的情况下,它会检查第2代对象(取决于垃圾收集器使用的代数)。
这只是一种启发式的实现策略:“如果一个对象刚刚被创建,那么它很可能很快就会成为垃圾,所以在需要释放内存时,这些对象应该是我们首先检查的对象。但如果它已经存在很长时间,那么它很可能会继续存在很长时间。因此,不断检查它将是低效的。”
分代收集器对于遗留的对象更少地遍历,JVM还会切换策略。由于旧对象变化较少,因此JVM会跟踪旧代对象的变化,所以垃圾收集器也可以跳过自上次主要垃圾回收以来没有更改的旧对象的区域,因此仍然引用与之前相同的对象。
总之,垃圾收集器的目的是管理和释放不再使用的内存,以提高程序的性能和效率。分代收集器通过将存活的对象移动到不同的堆中,实现了高效的内存管理。这种自动化的内存管理方式让开发人员能够专注于业务逻辑而不用过多关注内存管理。