以前看过很多次关于垃圾回收相关的文章,都只是看过就忘记了,没有好好的整理一下,发现写文章可以强化自己的记忆。
java与C,c++有很大的不同就是java语言开发者不需要关注内存信息,不会显式的直接操作内存,而是通过jvm虚拟机来实现。
java虚拟机运行的时候内存分配图如下图:
jvm虚拟机栈:一个是线程独有的,每次启动一个线程,就创建一个jvm虚拟机栈,线程退出的时候就销毁。这里面主要保存线程本地变量名和局部变量值。
本地方法栈: 调用本地jni方法的时候而创建的。这里分配的jvm之外的内存空间。方法调用结束之后销毁。
pc寄存器 : 这个保存线程当前执行的字节码指令
堆:主要保存创建的对象。
方法区:保存class相关的信息。主要是class的一个内存结构信息
常量池:方法区的一部分,主要保存class内存结构中常量值 例如String值,public static final 类型的值
我们这里说的垃圾回收,主要是java虚拟机对堆内存区域的回收。
1 首先的问题是:jvm如何知道那些对象需要回收 ?
目前有两种算法
每个对象上都有一个引用计数,对象每被引用一次,引用计数器就+1,对象引用被释放,引用计数器-1,直到对象的引用计数为0,对象就标识可以回收
这个可以用数据算法中的图形表示,对象A-对象B-对象C 都有引用,所以不会被回收,对象B由于没有被引用,没有路径可以达到对象B,对象B的引用计数就就是0,对象B就会被回收。
但是这个算法有明显的缺陷,对于循环引用的情况下,循环引用的对象就不会被回收。例如下图:对象A,对象B 循环引用,没有其他的对象引用A和B,则A和B 都不会被回收。
这种算法目前定义了几个root,也就是这几个对象是jvm虚拟机不会被回收的对象,所以这些对象引用的对象都是在使用中的对象,这些对象未使用的对象就是即将要被回收的对象。简单就是说:如果对象能够达到root,就不会被回收,如果对象不能够达到root,就会被回收。
如下图:对象D访问不到根对象,所以就会被回收
以下对象会被认为是root对象:
- 被启动类(bootstrap加载器)加载的类和创建的对象
- jvm运行时方法区类静态变量(static)引用的对象
- jvm运行时方法去常量池引用的对象
- jvm当前运行线程中的虚拟机栈变量表引用的对象
- 本地方法栈中(jni)引用的对象
由于这种算法即使存在互相引用的对象,但如果这两个对象无法访问到根对象,还是会被回收。如下图:对象C和对象D互相引用,但是由于无法访问根,所以会被回收。
jvm在确定是否回收的对象的时候采用的是root搜索算法来实现。
在root搜索算法的里面,我们说的引用这里都指定的是强引用关系。所谓强引用关系,就是通过用new 方式创建的对象,并且显示关联的对象
Object obj = new Object();
以上就是代表的是强引用关系,变量obj 强引用了 Object的一个对象。
java里面有四种应用关系,从强到弱分别为:
Strong Reference(强引用) –>Weak Reference (弱引用) -> Soft Reference(软引用) – > Phantom Reference(引用)
Strong Reference : 只有在引用对象root不可达的情况下才会标识为可回收,垃圾回收才可能进行回收
Weak Reference :即使在root算法中 其引用的对象root可达到,但是如果jvm堆内存 不够的时候,还是会被回收。
Soft Reference : 无论其引用的对象是否root可达,在响应内存需要时,由垃圾回收判断是否需要回收。
Phantom Reference :在回收器确定其指示对象可另外回收之后,被加入垃圾回收队列.
下面可以看一个测试
public class ReferenceTest {
public static final Map<Integer, Reference> map = new HashMap<Integer, Reference>();
public static void main(String[] args) {
for (int i = 0; i < 1000; i++) {
map.put(i, new WeakReference(new ReferenceObject(i)));
}
int i = 0;
for (Reference r : map.values()) {
if (r.get() == null) {
i++;
}
}
System.out.println("被回收的对象数:" + i);
}
static class ReferenceObject {
private int i;
private byte[] b;
public ReferenceObject(int i) {
this.i = i;
b = new byte[1024 *10];
}
}
}
这里创建大约1000个 10K的 Weak Reference 对象,最后打印的结果是:被回收的对象数:767,这里ReferenceObject如果设置为1K的话,最后的打印结果是0
这个例子并不严谨,但是却说明了被Weak Reference的对象在一定的时候会被jvm回收,但是强引用就不会出现这种状态。
分享到:
相关推荐
Java垃圾回收机制总结 Java垃圾回收机制是Java虚拟机(JVM)中的一种机制,用于防止内存泄露和有效地使用空闲的内存。垃圾回收机制的主要目的是为了回收无用的对象占用的内存空间,使该空间可被程序再次使用。 ...
Java垃圾回收机制是Java编程中一个非常重要的概念,尤其在面试和实际开发中常常被讨论。垃圾回收(Garbage Collection, GC)是Java虚拟机自动管理内存的一种方式,旨在自动识别并释放不再使用的对象,从而避免内存...
### Java垃圾回收原理详解 #### 一、引言 在现代软件开发中,Java作为一种广泛使用的编程语言,其垃圾回收机制是确保程序高效运行的关键技术之一。本文将深入探讨Java中的垃圾回收机制,包括其基本原理、不同类型...
### Java垃圾回收及内存泄漏知识点详解 #### 一、Java内存管理 1. **运行时数据区**:Java虚拟机管理的内存主要分为以下几个部分: - **方法区(Method Area)**:存储类的信息(如类名、字段、方法等)、常量、...
Java垃圾回收机制的详细介绍,调理比较清晰,个人进行的总结。
### Java高级之垃圾回收机制详解 #### 一、引言 在现代软件开发中,Java因其平台无关性、丰富的库支持以及自动内存管理等特性,成为企业级应用开发的首选语言之一。其中,垃圾回收机制(Garbage Collection, GC)是...
### JAVA垃圾回收个人总结 #### 一、垃圾回收(GC)概述 垃圾回收(Garbage Collection,简称GC)是Java虚拟机(JVM)提供的一种自动内存管理机制,它负责自动回收不再使用的对象所占用的内存空间,从而避免了手动管理...
垃圾收集器是Java语言区别于其他程序设计语言的一大特色。它把程序员从手工回收内存空间的繁重工作中解脱了...鉴于此,笔者总结了这个垃圾收集器的专题,希望对广大Java技术的爱好者和准备认证考试的考生们有所帮助。
总结,理解并掌握Java垃圾回收机制是提升Java应用程序性能的关键。通过选择合适的垃圾回收器、合理调整参数以及遵循良好的编程实践,我们可以有效管理内存,减少系统停顿,提高应用的稳定性和响应速度。
### Java垃圾回收技术详解 #### 一、引言 在现代软件开发中,Java作为一种广泛使用的编程语言,其垃圾回收机制(Garbage Collection, GC)是面试和技术交流中经常提及的话题之一。尤其对于那些深入研究Java内存...
Java垃圾回收机制是Java编程中一个重要的概念,它主要用于自动管理程序运行时的内存,确保内存的有效利用并防止内存泄漏。垃圾回收主要关注Java堆和方法区,特别是堆区域,因为这是对象的主要存储区域。 垃圾收集器...
### Java与C#的垃圾回收机制 #### 一、引言 在现代编程语言中,内存管理是一项重要的功能,能够显著提升程序的稳定性和效率。本文将深入对比Java与C#这两种广泛使用的编程语言中的垃圾回收机制,帮助开发者更好地...
本文将对Java垃圾回收进行小结,探讨其基本原理、类型以及常见算法。 1. 基本原理: Java中的内存分为堆(Heap)和栈(Stack)两部分,垃圾回收主要关注堆内存。当一个对象不再被任何引用指向时,它被视为可回收的...
### Java垃圾回收机制详解 #### 一、引言 在软件开发领域,特别是对于像Java这样的面向对象语言,内存管理一直是开发者关注的核心问题之一。Java的出现极大地简化了这一过程,其中最为突出的特点之一就是其内置的...
Java技术体系中所提倡的自动内存管理最终可以归结为自动化地解决了两个问题:给对象分配内存以及回收分配给对象...本文主要对java垃圾回收机制以及jvm参数等方面做个综述,也算是自己做开发这几年对这方面的一个总结。
总结,Java垃圾回收机制是Java平台的一个核心特性,它使得开发者无需关心内存管理细节,但理解其工作原理和优化策略对于提高应用性能至关重要。通过选择合适的GC类型,调整参数,以及良好的编程习惯,我们可以有效地...