我是Java新手,对Java中的垃圾收集器感到困惑。它实际上是做什么的,什么时候生效。请描述Java中垃圾收集器的一些属性。
我是Java新手,对Java中的垃圾收集器感到困惑。它实际上是做什么的,什么时候生效。请描述Java中垃圾收集器的一些属性。
Answers:
该垃圾收集器是运行在一个程序的Java虚拟机,其摆脱其未使用的Java应用程序了对象。它是自动内存管理的一种形式。
当典型的Java应用程序运行时,它正在创建新的对象,例如String
s和File
s,但是在一段时间之后,这些对象将不再使用。例如,看下面的代码:
for (File f : files) {
String s = f.getName();
}
在上面的代码中,String s
在for
循环的每次迭代中创建。这意味着在每次迭代中,都会分配一点内存来创建一个String
对象。
回到代码,我们可以看到,一旦执行了一次迭代,在下一次迭代中,String
就不再使用在上一次迭代中创建的对象,该对象现在被视为“垃圾”。
最终,我们将开始产生大量垃圾,内存将用于不再使用的对象。如果这种情况持续下去,最终Java虚拟机将耗尽空间以创建新对象。
那就是垃圾收集器介入的地方。
垃圾收集器将查找不再使用的对象,并摆脱它们,释放内存,以便其他新对象可以使用该内存。
在Java中,垃圾收集器负责内存管理,但是在其他语言(例如C)中,则需要使用诸如malloc
和的free
功能自行执行内存管理。内存管理是容易出错的事情之一,可能会导致所谓的内存泄漏 -在不再使用内存时无法回收内存的地方。
像垃圾回收这样的自动内存管理方案使程序员不必担心内存管理问题,因此他或她可以将更多精力放在开发他们需要开发的应用程序上。
它释放分配给程序不再使用的对象的内存,因此命名为“垃圾”。例如:
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自动运行,但是您也可以使用显式调用GC,System.gc()
并尝试强制进行大型垃圾回收。正如帕斯卡尔Thivent所指出的,你真的不应该有这样做,它可能会做弊大于利(见这个问题)。
System.gc()
不会强制GC运行。
myObj
在调用otherMethod
发生之前销毁是完全有效的,因为myObj
这时不再可用。
System.gc()
,拥有GC的全部意义就是不必这样做。
如果无法通过任何活动线程或任何静态引用访问对象,则该对象将具有垃圾回收或GC的资格。
换句话说,如果对象的所有引用均为null,则可以说该对象可以进行垃圾回收。循环依赖项不算作引用,因此,如果对象A对对象B的引用,对象B对对象A的引用,并且它们没有任何其他实时引用,则对象A和B都可以进行垃圾回收。
用于垃圾收集的堆世代-
为了在Java中进行垃圾回收,在其中创建Java对象Heap
并将Heap
其分为三个部分或三代,它们分别称为堆的Young(新)代,Tenured(旧)代和Perm Area。
新一代又分为三个部分,分别称为伊甸园空间,幸存者1和幸存者2空间。当一个对象首先在堆中创建时,它的生成在伊甸园空间内的新一代中进行了,随后在如果一个对象幸存的情况下进行了次要的垃圾收集,它的对象被转移到幸存者1,然后转移到幸存者2,直到主要垃圾收集将该对象转移到旧的或终身代。
Java Heap的Perm空间是JVM存储有关类和方法,字符串池和类级别详细信息的元数据的地方。
在这里参考更多:垃圾收集
尽管可以使用System.gc()
或Runtime.gc()
方法发出请求,但不能强制JVM运行垃圾回收。
public static void gc() {
Runtime.getRuntime().gc();
}
public native void gc(); // note native method
标记和扫描算法-
这是垃圾收集使用的最受欢迎的算法之一。任何垃圾收集算法都必须执行2个基本操作。首先,它应该能够检测所有无法访问的对象,其次,它必须回收垃圾对象使用的堆空间,并使该空间可再次用于程序。
以上操作由标记和扫描算法分两个阶段执行:
在这里阅读更多详细信息- 标记和扫描算法
垃圾收集器是JRE的一部分,可确保未引用的对象从内存中释放出来。
它通常在应用程序内存不足时运行。AFAIK它包含一个图形,该图形表示对象之间的链接,可以释放孤立的对象。
为了节省当前对象的性能,每当GC扫描一个对象并发现仍引用该对象时,其生成计数就增加1(我认为是3或4个最大值),并且首先扫描新生成的对象。 (内存中的对象越短,就越有可能不再需要它),因此并不是每次GC运行时都会扫描所有对象。
阅读此以获得更多信息。
垃圾收集器使您的计算机可以模拟具有无限内存的计算机。其余只是机制。
它通过检测何时不再可以从您的代码访问内存块并将这些块返回到自由存储区来实现此目的。
编辑:是的,链接用于C#,但是C#和Java在这方面是相同的。
许多人认为垃圾收集会收集和丢弃死掉的物体。
实际上,Java垃圾回收是相反的!跟踪活动对象,并将所有其他内容指定为垃圾。
当不再使用对象时,垃圾回收器将回收底层内存,并将其重新用于将来的对象分配。这意味着没有显式删除,也没有内存返回给操作系统。为了确定不再使用哪些对象,JVM会间歇性地运行非常恰当的标记-清除算法。
检查此以获得更多详细信息:http : //javabook.compuware.com/content/memory/how-garbage-collection-works.aspx
用即使是非程序员也能理解的最简单的术语来说,当程序处理数据时,它会为该数据创建中间数据和存储空间(变量,数组,某些对象元数据等)。
当跨功能或以一定大小访问这些对象时,将从中央堆分配它们。然后,当不再需要它们时,需要对其进行清理。
在线上有一些非常好的文章介绍了它是如何工作的,因此我只介绍最基本的定义。
GC基本上是执行此清理的功能。为此,清除所有活动对象未引用的表条目,有效地删除对象,然后复制并压缩内存。比这复杂一点,但是您知道了。
最大的问题是此过程中的某些部分通常需要整个Java VM临时停止才能发生,并且整个过程非常占用处理器和内存带宽。GC的各种选项和每个选项的调整选项旨在在整个GC过程中平衡这些各种问题。
垃圾收集器可以视为参考计数管理器。如果创建了对象并将其引用存储在变量中,则其引用计数将增加一。在执行过程中,如果该变量分配了NULL。该对象的引用计数递减。因此,该对象的当前引用计数为0。现在,当执行垃圾回收器时,它将检查引用计数为0的对象,并释放分配给它的资源。
垃圾收集器调用受垃圾收集策略控制。
您可以在此处获取一些数据。 http://www.oracle.com/technetwork/java/gc-tuning-5-138395.html
垃圾收集器是jvm的组件。
当cpu免费时,它用于收集垃圾。
这里的垃圾意味着它在主程序的后台运行的未使用的对象
监视主程序的状态。
自动垃圾回收是查看堆内存,识别正在使用的对象和未使用的对象以及删除未使用的对象的过程。使用中的对象或引用的对象意味着程序的某些部分仍维护着指向该对象的指针。程序的任何部分都不再引用未使用的对象或未引用的对象。因此,可以回收未引用对象使用的内存。
在像C这样的编程语言中,分配和取消分配内存是手动过程。在Java中,垃圾回收器会自动处理释放内存的过程。请检查链接以获得更好的理解。 http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html
垃圾收集是指通过删除程序中不再可访问的对象来自动释放堆上的内存的过程。堆是称为免费存储的内存,代表分配给Java应用程序的大量未使用内存。
垃圾回收的基本原理是在程序中查找将来无法访问的数据对象,并回收那些对象使用的资源。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用于应用程序生命周期中的对象,例如类,库。
自动垃圾收集是一个过程,在该过程中,JVM摆脱了某些数据点或将某些数据点保留在内存中,从而最终释放了正在运行的程序的空间。内存首先发送到堆内存,这是垃圾收集器(GC)进行工作的位置,然后决定终止或保留该内存。Java假定程序员不能总是被信任,因此它终止了它认为不需要的项目。