我是Java新手,对Java中的垃圾收集器感到困惑。它实际上做了什么以及什么时候开始行动。请用Java描述垃圾收集器的一些属性。
答案 0 :(得分:115)
garbage collector是一个在Java Virtual Machine上运行的程序,它删除了Java应用程序不再使用的对象。它是自动内存管理的一种形式。
当典型的Java应用程序正在运行时,它正在创建新对象,例如String
和File
,但在一定时间之后,这些对象将不再使用。例如,请查看以下代码:
for (File f : files) {
String s = f.getName();
}
在上面的代码中,String s
循环的每次迭代都会创建for
。这意味着在每次迭代中,都会分配一小部分内存来生成String
对象。
回到代码,我们可以看到,一旦执行了一次迭代,在下一次迭代中,在上一次迭代中创建的String
对象不再被使用 - 该对象现在被认为是“垃圾”。
最终,我们将开始获得大量垃圾,并且内存将用于不再使用的对象。如果这种情况继续下去,最终Java虚拟机将耗尽空间来创建新对象。
这就是垃圾收集器的用武之地。
垃圾收集器将查找不再使用的对象,并清除它们,释放内存,以便其他新对象可以使用该内存。
在Java中,内存管理由垃圾收集器处理,但在其他语言(如C)中,需要使用malloc
and free
等功能自行执行内存管理。 Memory management是容易犯错误的事情之一,这可能导致所谓的memory leaks - 不再使用时不回收内存的地方。
像垃圾收集这样的自动内存管理方案使得程序员不必过多担心内存管理问题,因此他或她可以更专注于开发他们需要开发的应用程序。
答案 1 :(得分:18)
它释放了分配给程序未被程序使用的对象的内存 - 因此名称为“垃圾”。例如:
public static Object otherMethod(Object obj) {
return new Object();
}
public static void main(String[] args) {
Object myObj = new Object();
myObj = otherMethod(myObj);
// ... more code ...
}
我知道这是非常人为的,但是在你致电otherMethod()
之后,创建的原始Object
无法访问 - 这就是垃圾收集的“垃圾”。
在Java中,GC会自动运行,但您也可以使用System.gc()
显式调用它,并且尝试强制执行主要的垃圾回收。正如Pascal Thivent指出的那样,你真的不应该必须这样做,它可能弊大于利(见this question)。
有关更多信息,请参阅Garbage collection和Tuning Garbage Collection上的维基百科条目(来自Oracle)
答案 2 :(得分:13)
如果对象无法从任何活动线程或任何静态引用访问,则该对象符合垃圾收集或GC的条件。
换句话说,如果对象的所有引用都为null,则可以说对象符合垃圾回收的条件。循环依赖项不计入引用,因此如果对象A具有对对象B的引用,而对象B具有对对象A的引用,并且它们没有任何其他实时引用,则对象A和B都将符合Garbage的条件集合。
垃圾收集的堆生成 -
Java对象在Heap
中创建,Heap
分为三部分或几代,以便在Java中进行垃圾收集,这些被称为 Young(新)代堆的,Tenured(Old)Generation和Perm Area 。
http://life.xxx.info/ 新一代进一步分为三个部分,即Eden space,Survivor 1和Survivor 2 space。当一个对象最初在堆中创建时,它会在Eden空间内的新一代中创建,并且在后续的小垃圾收集之后,如果一个对象存活,它将被移动到幸存者1,然后幸存者2在主要垃圾收集之前将该对象移动到 old或tenured代强>
Java堆的Perm空间是JVM存储有关类和方法,字符串池和类级别详细信息的元数据的地方。
虽然您可以使用System.gc()
或Runtime.gc()
方法发出请求,但您无法强制JVM运行垃圾收集。
<强> Garbage Collection 强>
public static void gc() {
Runtime.getRuntime().gc();
}
<强> In java.lang.System 强>
public native void gc(); // note native method
标记和扫描算法 -
这是垃圾收集使用的最流行的算法之一。任何垃圾收集算法都必须执行2个基本操作。一,它应该能够检测所有无法到达的对象;其次,它必须回收垃圾对象使用的堆空间,并使该空间再次可用于该程序。
上述操作由Mark和Sweep Algorithm分两个阶段执行:
请在此处阅读详情 - In java.lang.Runtime
答案 3 :(得分:6)
垃圾收集器意味着程序不再需要的对象是“垃圾”并且可以被丢弃。
答案 4 :(得分:6)
垃圾收集器是JRE的一部分,它确保未引用的对象将从内存中释放 它通常在应用程序内存不足时运行。 AFAIK它拥有一个图形,表示对象和孤立对象之间的链接可以被释放 为了保存性能,当前对象分组为几代,每次GC扫描一个对象并发现它仍然被引用它的生成计数递增1(到某个最大值最大值,我认为是3或4),并且首先扫描新一代(内存中的对象最短,不再需要它),因此每次GC运行时都不会扫描所有对象 阅读this了解更多信息。
答案 5 :(得分:3)
The garbage collector allows your computer to simulate a computer with infinite memory.其余的只是机制。
它通过检测代码中何时无法访问内存块并将这些块返回到免费商店来实现此目的。
编辑:是的,该链接适用于C#,但C#和Java在这方面是相同的。答案 6 :(得分:3)
许多人认为垃圾收集会收集并丢弃死物 实际上,Java垃圾收集正在做相反的事情!跟踪活动对象,并将其他所有内容指定为垃圾。
当不再使用某个对象时,垃圾收集器会回收底层内存并重新使用它以供将来的对象分配。这意味着没有明确删除,并且没有内存返回给操作系统。 为了确定哪些对象不再使用,JVM间歇性地运行非常恰当的标记和扫描算法。
检查以获取更多详细信息: http://javabook.compuware.com/content/memory/how-garbage-collection-works.aspx
答案 7 :(得分:1)
用即使是非程序员也可以理解的最简单的术语来说,当程序处理数据时,它会为该数据创建中间数据和存储空间(变量,数组,某些对象元数据等)。
当通过函数或一定大小访问这些对象时,将从中央堆分配它们。然后,当不再需要它们时,需要对其进行清理。
在线上有一些很好的文章介绍了它的工作原理,所以我只介绍最基本的定义。
基本上,GC是执行此清理的功能。为此,清除所有活动对象未引用的表条目,有效地删除对象,然后复制并压缩内存。比这复杂一点,但是您知道了。
最大的问题是,该过程的某些部分通常需要整个Java VM临时停止,并且整个过程非常占用处理器和内存带宽。 GC的各种选项和每个选项的调整选项旨在平衡这些问题与整个GC流程。
答案 8 :(得分:0)
Java中的垃圾收集(以及其他语言/平台)是java运行时环境(JRE)从不再需要的Java对象重用内存的一种方式。简单地说,当JRE最初启动时,它会向操作系统(O / S)询问一定量的内存。当JRE运行您的应用程序时,它会使用该内存。当您的应用程序使用该内存完成时,JRE的“垃圾收集器”会出现并回收该内存以供现有应用程序的不同部分使用。 JRE的“垃圾收集器”是一个后台任务,它始终在运行,并尝试在系统空闲时进行垃圾运行。
真实世界的比喻就是垃圾人来到你家并拿起你的可回收垃圾......最终,它会被你自己和/或其他人以其他方式重复使用。
答案 9 :(得分:0)
可以将垃圾收集器视为引用计数管理器。 如果创建了一个对象并且其引用存储在一个变量中,则其引用计数会增加一。在执行过程中,如果该变量被赋值为NULL。该对象的引用计数递减。因此,对象的当前引用计数为0.现在,当执行垃圾收集器时,它会检查引用计数为0的对象,并释放分配给它的资源。
垃圾收集器调用由垃圾收集策略控制。
您可以在此处获取一些数据。 http://www.oracle.com/technetwork/java/gc-tuning-5-138395.html
答案 10 :(得分:0)
垃圾收集器是jvm的一个组件。
当cpu被释放时,它用于收集垃圾。
这里垃圾意味着它在主程序背景中运行的未使用对象
监控主程序的状态。
答案 11 :(得分:0)
自动垃圾收集是查看堆内存,识别正在使用哪些对象以及哪些对象未被删除以及删除未使用对象的过程。使用中的对象或引用的对象意味着程序的某些部分仍然维护指向该对象的指针。程序的任何部分都不再引用未使用的对象或未引用的对象。因此,可以回收未引用对象使用的内存。
在像C这样的编程语言中,分配和释放内存是一个手动过程。在Java中,解除分配内存的过程由垃圾收集器自动处理。请查看链接以获得更好的理解。 http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html
答案 12 :(得分:0)
垃圾收集是指通过删除程序中不再可访问的对象来自动释放堆上内存的过程。 堆是一个称为空闲存储的内存,表示分配给Java应用程序的大量未使用内存。
答案 13 :(得分:0)
垃圾收集的基本原则是在程序中查找将来无法访问的数据对象,并回收这些对象使用的资源。 https://en.wikipedia.org/wiki/Garbage_collection_%28computer_science%29
<强>优点强>
1)保存错误,这些错误发生在释放一块内存但仍有指向它的指针时,其中一个指针被解除引用。 https://en.wikipedia.org/wiki/Dangling_pointer
2)双重免费错误,当程序试图释放已经释放的内存区域并且可能已经再次分配时发生。
3)防止某些类型的内存泄漏,程序无法释放已无法访问的对象占用的内存,这可能导致内存耗尽。
<强>缺点强>
1)消耗额外的资源,性能影响,程序执行中可能的停顿以及与手动资源管理的不兼容。 垃圾收集在决定释放哪个内存时消耗计算资源,即使程序员可能已经知道了这些信息。
2)实际收集垃圾的时刻可能是不可预测的,导致在整个会话期间分散的停顿(暂停移位/空闲内存)。在实时环境,事务处理或交互式程序中,不可预测的停顿是不可接受的。
Oracle教程 http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html
垃圾收集是识别哪些对象正在使用哪些对象的过程,以及删除未使用的对象。
在C,C ++等编程语言中,分配和释放内存是一个手动过程。
int * array = new int[size];
processArray(array); //do some work.
delete array; //Free memory
该过程的第一步称为标记。这是垃圾收集器识别正在使用哪些内存而哪些内存不在使用的地方。
步骤2a。正常删除会删除未引用的对象,留下引用的对象和指向可用空间的指针。
为了提高性能,我们希望删除未引用的对象,并压缩剩余的引用对象。我们希望将引用的对象保持在一起,因此分配新内存会更快。
如前所述,必须标记和压缩JVM中的所有对象效率低下。随着越来越多的对象被分配,对象列表会增长和增长,从而导致垃圾收集时间越来越长。
继续阅读本教程,您将了解GC如何应对这一挑战。
简而言之,堆有三个区域,短生命对象 YoungGeneration ,长期对象 OldGeneration , PermanentGeneration 在应用程序生命周期中存在的对象,例如,类,库。
答案 14 :(得分:0)
当对象由 new 运算符动态分配时,您可以询问这些对象是如何被销毁的以及释放内存的繁忙程度。在其他语言(如C ++)中,您需要通过delete运算符动态释放手动分配的对象。 Java有不同的方法;它会自动处理释放。该技术称为垃圾收集。
它的工作原理如下:当没有对象的引用时,假定不再需要该对象,并且可以检索该对象占用的内存。没有必要像在C ++中那样显式地销毁对象。在程序执行期间偶尔会发生垃圾收集;它不会简单地发生,因为有一个或多个对象不再使用。此外,一些Java运行时实现具有不同的垃圾收集方法,但大多数程序员在编写程序时不必担心这一点。
答案 15 :(得分:-2)
自动垃圾收集是JVM在内存中清除或保留某些数据点以最终为正在运行的程序释放空间的过程。内存首先被发送到堆内存,这是垃圾收集器(GC)完成其工作的地方,然后决定终止或保留。 Java假定程序员不能总是被信任,因此它终止了它认为不需要的项目。