Java中的垃圾收集器是什么?
我是Java新手,对Java中的垃圾收集器感到困惑。 它究竟做了什么以及什么时候开始实施。 请描述Java中垃圾收集器的一些属性。
垃圾收集器是一个在Java虚拟机上运行的程序,它可以去除Java应用程序不再使用的对象。 这是一种自动内存pipe理的forms。
当一个典型的Java应用程序正在运行时,它正在创build新的对象,比如String
和File
,但是在一段时间之后,这些对象就不再使用了。 例如,看看下面的代码:
for (File f : files) { String s = f.getName(); }
在上面的代码中,在for
循环的每次迭代中都会创buildString s
。 这意味着在每次迭代中,都会分配一点内存来创build一个String
对象。
回到代码中,我们可以看到,一旦执行了一次迭代,在下一次迭代中,在前一次迭代中创build的String
对象就不再被使用 – 该对象现在被认为是“垃圾”了。
最终,我们会开始大量的垃圾,内存将被用于不再使用的对象。 如果这样继续下去,Java虚拟机最终将耗尽空间来创build新的对象。
这是垃圾收集器的地方。
垃圾收集器将查找不再使用的对象,并将其清除,释放内存,以便其他新对象可以使用该内存。
在Java中,内存pipe理由垃圾收集器负责,但在其他语言如C中,需要使用malloc
和free
等函数自行执行内存pipe理。 内存pipe理是容易出错的事情之一,这可能导致所谓的内存泄漏 – 内存不再被使用的地方。
像垃圾收集这样的自动内存pipe理scheme使得程序员不必担心内存pipe理问题,所以他或她可以更专注于开发他们需要开发的应用程序。
它释放分配给程序不再被程序使用的内存 – 因此名称为“垃圾”。 例如:
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()
,创build的原始Object
创build为无法访问 – 这就是垃圾回收。
在Java中,GC自动运行,但也可以使用System.gc()
显式调用它,并尝试强制执行一个主要的垃圾回收。 正如Pascal Thivent所指出的那样,你真的不应该这样做,这可能会造成更多的伤害(见这个问题 )。
有关更多信息,请参阅Garbage collection和Tuning Garbage Collection (来自Oracle)的维基百科条目
如果对象无法从任何活动线程或任何静态引用访问,则对象变为符合垃圾收集或GC的条件。
换句话说,如果一个对象的所有引用都为null,那么你可以说这个对象有资格进行垃圾回收。 循环依赖不被视为引用,所以如果对象A具有对象B的引用,并且对象B具有对对象A的引用,并且它们没有任何其他活动引用,则对象A和B都将有资格进行垃圾收集。
垃圾收集的堆世代 –
Java对象是在Heap
中创build的,为了在Java中进行垃圾收集, Heap
被分成三部分或几代,这些被称为堆的年轻(新)代,终身(旧)代和Perm区 。
新一代又分为伊甸空间,幸存者1和幸存者2三个部分。 首先在堆中创build的对象在Eden空间内的新一代中创build,如果对象存活,则在后续的小型垃圾收集之后,将其移至生存者1,然后在主垃圾收集将该对象移至旧生成或生成生成之前生存者2。
Java堆的Perm空间是JVM存储有关类和方法,string池和类级别细节的元数据的位置。
请参阅这里了解更多: 垃圾收集
尽pipe可以使用System.gc()
或Runtime.gc()
方法发出请求,但不能强制JVM运行垃圾回收。
在java.lang.System中
public static void gc() { Runtime.getRuntime().gc(); }
在java.lang.Runtime中
public native void gc(); // note native method
标记和扫描algorithm –
这是垃圾收集最常用的algorithm之一。 任何垃圾收集algorithm都必须执行2个基本操作。 其一,它应该能够检测到所有不可到达的对象,其次,它必须回收垃圾对象所使用的堆空间,并使该空间再次可用于程序。
上述操作由Mark和Sweepalgorithm分两个阶段进行:
- 标记阶段
- 扫描阶段
在这里阅读更多细节 – 标记和扫描algorithm
垃圾收集器意味着程序不再需要的对象是“垃圾”,可以扔掉。
垃圾收集器是JRE的一部分,确保未被引用的对象将从内存中释放。
它通常运行时,你的应用程序内存不足。 AFAIK它拥有一个图表,表示对象和孤立的对象之间的联系可以被释放。
为了节省性能,当前的对象被分组为几代,每次GC扫描一个对象,并发现它仍然被引用时,其生成计数加1(对于某个最大值,我认为是3或4),并且首先扫描新一代(内存中的对象最短,不再需要它),所以并不是每次GC运行时都要扫描所有的对象。
阅读这个更多的信息。
垃圾回收器允许您的计算机模拟无限内存的计算机。 其余的只是机制。
它通过检测何时不能从代码中访问内存块,然后将这些块返回给空闲存储来完成此操作。
编辑:是的,链接是为C#,但C#和Java在这方面是相同的。
许多人认为垃圾收集和丢弃死物。
实际上,Java垃圾收集正在做相反的事情! 实时对象被跟踪,其他一切都被指定为垃圾。
当一个对象不再使用的时候,垃圾回收器会回收底层的内存,然后重用它来为将来的对象分配。 这意味着没有明确的删除操作并且没有内存返回给操作系统。 为了确定哪些对象不再被使用,JVM间歇地运行一个非常合适的称为标记和扫描algorithm。
检查这个更详细的信息: http : //javabook.compuware.com/content/memory/how-garbage-collection-works.aspx
Java中的垃圾收集器是什么?
在Java中,从内存中销毁对象是由JVM自动完成的。 当没有对象的引用时,则认为该对象不再需要,并释放该对象占用的内存。 这种技术被称为垃圾收集。 这是由JVM完成的。
与C ++不同,没有明确的需要销毁对象。
内存pipe理是任何编程语言最重要的工作之一。 考虑到读取一组数据并将其写入数据库的应用程序,为此,它将使用一些中间存储位置将数据存储到数据库中。 现在,如果这个中间存储空间没有清除以前的数据,那么可能会导致它耗尽,从而导致我们的应用程序失效。 为了防止这种情况发生,可以有两种方式,一种是像C ++或C那样手动清除内存,另一种是使用垃圾回收的后台进程自动完成这项工作。
现在,无论何时运行一个软件程序,它都会消耗一些内存,比如创build对象的堆。 垃圾收集处理它,其主要目的是删除所有未使用或不可触及的对象。 所以,我们通过Java代码所做的一切就是根据需要创build对象,然后在不再使用时将其销毁。 这个垃圾回收器在JVM的控制之下。 虽然JVM可以被命令来运行垃圾收集器,但是似乎不能保证实际上垃圾收集器将被设置为工作。 所以,垃圾收集器通常在JVM内存不足的时候运行。
Java中的垃圾收集(以及其他语言/平台)是Java运行时环境(JRE)从不再需要的Java对象中重用内存的一种方式。 简单地说,当JRE最初启动时,它向操作系统(O / S)询问一定量的内存。 当JRE运行你的应用程序时,它使用这个内存。 当您的应用程序使用该内存完成时,JRE的“垃圾收集器”随之而来,并回收该内存以供现有应用程序的不同部分使用。 JRE的“垃圾收集器”是一个始终运行的后台任务,并试图挑选系统闲置时进行垃圾运行。
一个真实世界的比喻是来到你家的垃圾人,拿起你的可回收垃圾……最终,它由你自己和/或其他人以其他方式重用。
垃圾收集器可以被视为引用计数pipe理器。 如果一个对象被创build并且它的引用存储在一个variables中,那么它的引用计数就会增加一个。 在执行过程中,如果该variables分配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)防止某些types的内存泄漏,其中程序无法释放被不可用的对象占用的内存,这可能导致内存耗尽。
缺点
1)消耗额外的资源,性能影响,可能的程序停顿,以及与手动资源pipe理不兼容。 即使程序员可能已经知道这些信息,垃圾收集也会消耗计算资源来决定释放哪些内存。
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用于生活中的对象,例如类,图书馆。
由于对象是由新运算符dynamic分配的,因此可以询问这些对象如何被销毁以及释放内存的繁忙程度。 在其他语言如C ++中,您需要通过delete操作符dynamic释放手动分配的对象。 Java有不同的方法; 自动处理重新分配。 这项技术被称为垃圾收集 。
它的工作原理是这样的:当没有对象的引用时,假定这个对象不再需要,你可以检索对象占用的内存。 不需要像在C ++中那样显式地销毁对象。 垃圾收集在程序执行期间偶尔发生; 它不是简单的发生,因为有一个或多个不再使用的对象。 另外,一些Java运行时实现有不同的垃圾收集方法,但大多数程序员不必担心编写程序
如果对象无法从任何活动线程或任何静态引用访问,则对象变为符合垃圾收集或GC的条件。
换句话说,如果一个对象的所有引用都为null,那么可以说这个对象有资格进行垃圾回收。 循环依赖不被视为引用,所以如果对象A具有对象B的引用,并且对象B具有对对象A的引用,并且它们没有任何其他活动引用,则对象A和B都将有资格进行垃圾收集。
垃圾收集的堆世代 –
Java对象是在Heap
中创build的,为了在Java中进行垃圾收集, Heap
被分成三部分或几代,这些被称为堆的年轻(新)代,终身(旧)代和Perm区 。
新一代又分为伊甸空间,幸存者1和幸存者2三个部分。 首先在堆中创build的对象在Eden空间内的新一代中创build,如果对象存活,则在后续的小型垃圾收集之后,将其移至生存者1,然后在主垃圾收集将该对象移至旧生成或生成生成之前生存者2。
Java堆的Perm空间是JVM存储有关类和方法,string池和类级别细节的元数据的位置。
自动垃圾收集是JVM摆脱或保留内存中的某些数据点以最终为正在运行的程序释放空间的过程。 内存首先发送到堆内存,这是垃圾回收器(GC)的工作,然后决定终止或保留。 Java假定程序员不能总是被信任,所以它终止它认为不需要的项目。