第九章Java中类生命周期与java垃圾回收机制.ppt

合集下载

图解JAVA垃圾回收机制(转)

图解JAVA垃圾回收机制(转)

图解JAVA垃圾回收机制(转)摘要: Java技术体系中所提倡的⾃动内存管理最终可以归结为⾃动化地解决了两个问题:给对象分配内存以及回收分配给对象的内存,⽽且这两个问题针对的内存区域就是Java内存模型中的堆区。

关于对象分配内存问题,笔者的博⽂已经阐述了如何划分可⽤空间及其涉及到的线程安全问题,本⽂将结合垃圾回收策略进⼀步给出内存分配规则。

垃圾回收机制的引⼊可以有效的防⽌内存泄露、保证内存的有效使⽤,也⼤⼤解放了Java程序员的双⼿,使得他们在编写程序的时候不再需要考虑内存管理。

本⽂着重介绍了判断⼀个对象是否可以被回收的两种经典算法,并详述了四种典型的垃圾回收算法的基本思想及其直接应⽤——垃圾收集器,最后结合内存回收策略介绍了内存分配规则。

友情提⽰: 为了更好地了解Java的垃圾回收机制,笔者建议读者先要对JVM内存模型有⼀个整体的了解和把握。

鉴于笔者在博⽂中已经深⼊介绍了JVM内存模型,此不赘述。

本⽂内容是基于 JDK 1.6 的,不同版本虚拟机之间也许会有些许差异,但不影响我们对JVM垃圾回收机制的整体把握和了解。

⼀、垃圾回收机制的意义 在笔者的上⼀篇博⽂中提到,JVM 内存模型⼀共包括三个部分:堆 ( Java代码可及的 Java堆和 JVM⾃⾝使⽤的⽅法区)、栈 ( 服务Java⽅法的虚拟机栈和服务Native⽅法的本地⽅法栈 ) 和保证程序在多线程环境下能够连续执⾏的程序计数器。

特别地,我们当时就提到Java堆是进⾏垃圾回收的主要区域,故其也被称为GC堆;⽽⽅法区也有⼀个不太严谨的表述,就是永久代。

总的来说,堆 (包括Java堆和⽅法区)是垃圾回收的主要对象,特别是Java堆。

实际上,Java技术体系中所提倡的⾃动内存管理最终可以归结为⾃动化地解决了两个问题:给对象分配内存以及回收分配给对象的内存,⽽且这两个问题针对的内存区域就是Java内存模型中的堆区。

关于对象分配内存问题,笔者的博⽂已经阐述了如何划分可⽤空间及其涉及到的线程安全问题,本⽂将结合垃圾回收策略进⼀步给出内存分配规则。

Java 垃圾回收机制详解

Java 垃圾回收机制详解

Java 垃圾回收机制详解•Java内存模型• 1.内存回收机制:内存回收就是释放掉在内存中已经没用的对象。

2.要判断怎样的对象是没用的对象。

这里有2种方法:– 1.采用标记计数的方法:给内存中的对象给打上标记,对象被引用一次,计数就加1,引用被释放了,计数就减一,当这个计数为0的时候,这个对象就可以被回收了。

当然,这也就引发了一个问题:循环引用的对象是无法被识别出来并且被回收的。

所以就有了第二种方法:– 2.采用根搜索算法:从一个根出发,搜索所有的可达对象,这样剩下的那些对象就是需要被回收的判断完了哪些对象是没用的,这样就可以进行回收了最简单的,就是直接清空那个需要被回收的对象。

但是这又出现了一个问题,就是内存会被分为一块一块的小碎片。

– 3.为了解决这个问题,可以采用第二种方法,就是在之前的基础上将存活的对象给整理一下,使他们变成一个连续的内存,从而释放出连续的较大的内存空间。

还有一中回收方法就是采用复制的办法:将内存分为2块,一块用来存放对象,另一块用来放着,当存放对象的那块满了以后就将上面存活的对象给复制过来,然后在这块内存上工作,并且将之前的内存清空,当自己这块满了以后再复制回去,如此反复。

比较效率的一中做法是将以上的几种方法给结合起来。

首先将内存分块,分为新生代,老年代和永久代。

永久代用来存放代码,等一些基本不改变的数据,新生代用来存放刚产生的一些对象,新生代又可分为3块。

分别为Edon区,Survivor0,survivor1,刚产生的对象是放在Edon区中,当这个区块放满了以后就将其存活的部分复制到survivor0块中,并且将Edon区中的数据清空,等到survivor0满了就将其中的存活的数据放到survivor1中,清空survivor0,垃圾回收到了一定次数还未被回收的对象,就可以放到老年区。

一般来说,刚才产生的对象大多是要在下一次垃圾回收的时候就要被回收掉的,只有一小部分对象会被保留下来,这些被保留下来的对象都是比较稳定的,所以在老年区中的对象回收方法可以采用整理的方法,而在Edon区等新生代中采用复制的方法比较好。

Java垃圾回收机制(GC)

Java垃圾回收机制(GC)

Java垃圾回收机制(GC)
分类:
1. 什么是GC
2. GC的区域在哪⾥
3. GC的对象是什么
4. GC做了哪些事
需要GC的内存区域
jvm 中,程序记数器、虚拟机栈、本都⽅法栈都是随线程⽽⽣,随线程⽽灭,栈随着⽅法的进⼊和退出做⼊栈和出栈操作,实现了⾃动的内存清理,因此,我们的内存⽴即回收主要集中于java 堆和⽅法区中,在程序运⾏期间,这部分内存的分配和使⽤都是动态的。

GC的对象
需要进⾏回收的对象就是已经没有存活的对象,判断⼀个对象是否存活有两种常⽤的办法:
1. 引⽤计数: 每个对象有⼀个引⽤计数属性,新增⼀个引⽤时计数就加1,引⽤什邡市计数就减1,计数为0时就可以回收。

(⽆法解决对象
互相引⽤的问题。

)
2. 可达分析( Reachability Analysis ): 从 GC Roots开始向下搜索,搜索所⾛过的路径被称为引⽤链。

当⼀个对象到GC Roots没有任何引
⽤链相连时,则证明此对象是不可⽤的。

不可达对象。

GC Roots包括:
1. 虚拟机栈中引⽤的对象。

2. ⽅法区中静态属性实体引⽤对象。

3. ⽅法区中常量引⽤的对象。

4. 本地⽅法栈中JNI引⽤的对象。

什么时候触发GC
1. 程序调⽤System.gc时可以触发
2. 系统⾃⾝来决定GC触发的时机(根据Eden区和From Space区的内存⼤⼩来决定。

当内存⼤⼩不⾜时,则会启动GC线程并停⽌应⽤
线程)
GC做了什么事
主要做了清理对象,整理内存的⼯作。

Java堆分为新⽣代和⽼年代,采⽤了不同的回收⽅式。

Java中的垃圾回收

Java中的垃圾回收

Java中的垃圾回收垃圾回收确定对象是否存活?两种确定对象是否存活:引⽤计数算法可达性分析算法引⽤计数算法给对象中添加引⽤计数器,若有⼀个引⽤,则计数值加⼀,若引⽤失效,计数值减⼀。

存在的问题:难以解决循环引⽤问题。

可达性分析算法通过GC Roots作为起始节点,根据引⽤关系向下开始搜索,所有搜索⾛过的路径称为“引⽤链”。

如果⼀个对象没有到达GC Roots的引⽤链,则为不可达,可以认为该对象可以被回收。

GC Roots对象虚拟机栈中引⽤的对象(⽅法中使⽤参数,局部变量,临时变量)⽅法区中类静态属性引⽤的对象⽅法区中常量引⽤的对象(字符串常量池中的引⽤)本地⽅法栈中引⽤的对象虚拟机内部的引⽤(基本数据类型对象的Class对象)被synchronized持有的对象。

引⽤分类强引⽤:引⽤不会被垃圾收集器回收。

通过 new 创建的引⽤。

软引⽤:在内存不⾜时,对于这些进⾏回收。

通过 SoftReference 创建软引⽤。

弱引⽤:对象存活到下⼀次垃圾收集。

通过 WeakReference 创建弱引⽤。

虚引⽤:不影响对象的⽣存周期,⽆法通过虚引⽤获得对象实例。

⽤于在对象被回收时收到系统通知。

回收⽅法区主要是回收:废弃的常量不再使⽤的类型判断⼀个类是否可以被回收的条件该类的所有实例对象已被回收。

(堆中不存在该类及其⼦类的实例)加载该类的类加载器已被回收。

对应的Class对象没有被引⽤。

注:⼤量使⽤反射,动态代理的场景中,需要有类型卸载的能⼒。

垃圾收集算法Java堆的划分:新⽣代:对象创建的区域,每次垃圾收集会回收⼤量的对象。

⽼年代:保存着⽣存周期较长的对象。

垃圾收集分类:Minor GC/Young GC:⽬标为新⽣代的垃圾收集。

Major GC/Old GC:⽬标是⽼年代的垃圾收集。

(CMS)Mixed GC:收集整个新⽣代和部分⽼年代的垃圾收集(G1)三种主要的垃圾收集算法标记-清除算法标记-复制算法标记-整理算法标记-清除算法分为两个阶段:标记处所有需要回收的对象。

Java垃圾回收与回收机制

Java垃圾回收与回收机制

全面分析Java的垃圾回收机制Java的堆是一个运行时数据区,类的实例(对象)从中分配空间。

Java虚拟机(JVM)的堆中储存着正在运行的应用程序所建立的所有对象,这些对象通过new、newarray、anewarray和multianewarray等指令建立,但是它们不需要程序代码来显式地释放。

一般来说,堆的是由垃圾回收来负责的,尽管JVM规范并不要求特殊的垃圾回收技术,甚至根本就不需要垃圾回收,但是由于内存的有限性,JVM在实现的时候都有一个由垃圾回收所管理的堆。

垃圾回收是一种动态存储管理技术,它自动地释放不再被程序引用的对象,按照特定的垃圾收集算法来实现资源自动回收的功能。

垃圾收集的意义在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其它对象;而在Java中,当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾。

JVM的一个系统级线程会自动释放该内存块。

垃圾收集意味着程序不再需要的对象是"无用信息",这些信息将被丢弃。

当一个对象不再被引用的时候,内存回收它占领的空间,以便空间被后来的新对象使用。

事实上,除了释放没用的对象,垃圾收集也可以清除内存记录碎片。

由于创建对象和垃圾收集器释放丢弃对象所占的内存空间,内存会出现碎片。

碎片是分配给对象的内存块之间的空闲内存洞。

碎片整理将所占用的堆内存移到堆的一端,JVM将整理出的内存分配给新的对象。

垃圾收集能自动释放内存空间,减轻编程的负担。

这使Java 虚拟机具有一些优点。

首先,它能使编程效率提高。

在没有垃圾收集机制的时候,可能要花许多时间来解决一个难懂的存储器问题。

在用Java语言编程的时候,靠垃圾收集机制可大大缩短时间。

其次是它保护程序的完整性,垃圾收集是Java语言安全性策略的一个重要部份。

垃圾收集的一个潜在的缺点是它的开销影响程序性能。

Java虚拟机必须追踪运行程序中有用的对象,而且最终释放没用的对象。

《Java高级课件:JVM内存模型与垃圾回收机制》

《Java高级课件:JVM内存模型与垃圾回收机制》

垃圾回收器的选择和G1回收器
垃圾回收器的选择
了解如何选择合适的垃圾回收器来满足应用程序的 需求。
G1垃圾回收器
探索G1垃圾回收器的基本原理和其在大型应用程序 中的优势。
内存泄漏和内存溢出
1
内存溢出的概念和原因
2
探讨了什么是内存溢出,以及导致内存
溢出的常见原因。
3
内存泄漏的概念和影响
解释了什么是内存泄漏以及它对应用程 序的影响。
总结和扩展阅读
现在你已经熟悉了JVM内存模型和垃圾回收机制的基本概念和知识。继续深 入学习和扩展阅读,探索更多关于JVM和内存管理的内容。
Java高级课件:JVM内存 模型与垃圾回收机制
本课程将介绍JVM内存模型的基本概念和作用,内存结构和区域的划分,线 程隔离和内存共享的概念与区别。
JVM内存模型和内存区域
堆和栈
详细介绍了Java Heap和 Java Stack的区别和作用。
方法区和运行时常量池
解释了方法区和运行时常量 池在内存模型中的位置和功 能。
如何防止内存泄漏和内存溢出
提供了一些实用的技巧和方法,以防止 内存泄漏和内存溢出。
代码示例和JVM调优
使用Java代码进行垃圾 回收
示范了如何使用Java代码显 式触发垃圾回收。
JVM调优的基本原则
介绍了JVM调优的基本原则 和一些注意事项。
常用的JVM调ห้องสมุดไป่ตู้工具
提供了一些常用的JVM调优 工具,如VisualVM和 JConsole。
本地方法栈和程序计数 器
探讨了本地方法栈和程序计 数器的作用以及它们在内存 中的位置。
对象分配和回收
1 对象的创建和内存分配 2 垃圾回收的基本原理

第九章、Java中类的生命周期与java垃圾回收机制

第九章、Java中类的生命周期与java垃圾回收机制

初始化
在初始化阶段,JAVA虚拟机执行类的初始化语句,为类的静态变量赋予初始值。在 程序中,静态变量的初始化有两种途径: 1、在静态变量的声明处进行初始化
2、在静态代码块中进行初始化。
public class InitClass{ public static String a = “nihao”; static { } }
java类的生命周期
当我们编写一个java的源文件后,经过编译会生成一个后缀名为 class的文件,这种文件叫做字节码文件,只有这种字节码文件才能够 在java虚拟机中运行,java类的生命周期就是指一个class文件从加载到 卸载的全过程。 一个java类的完整的生命周期会经历加载、连接、初始化、使用 (即对象生命周期)、和卸载五个阶段
异常处理的一般步骤: 异常抛出异常捕获异常处理 1.异常处理是由 try、catch与finally三个关键字所组成的程序块 2.异常类可分为两大类,分别为ng.Exception与ng.Error类。 3.如何一个方法可能会出现异常,且方法内有没有任何的try-catch-finally块来 捕异常时,可以在方法声明处用throws子句来声明抛出异常。相比较try-catch 捕获异常来讲,这种处理异常的方式较消极,所以有时候也该方式叫做异常 的消极处理方式,管try-catch捕获异常叫做积极处理方式 4.Throws和throw的区别
堆内存主要用来存储程序在运行时创建或实例化的对象与变量。例如通 过new关键字创建的对象。而栈内存则是用来存储程序代码中的方法。
补充知识:内部类
内部类(Inner class)是定义在另一个类中的类。ห้องสมุดไป่ตู้
当A类为B类服务时,为不让外界直接访问到A类,可把这个A类定义在 B类的内部,变为内部类。 内部类的基本语法: [修饰符] class 外部类{ [修饰符] class 内部类{ //内部类的类体 } }

java垃圾回收机制

java垃圾回收机制

java垃圾回收机制垃圾收集GC(Garbage Collection)是Java语⾔的核⼼技术之⼀,在Java中,程序员不需要去关⼼内存动态分配和垃圾回收的问题,这⼀切都交给了JVM来处理。

⼀. jvm的内存结构垃圾回收都是基于内存去回收的,因此,先要对内存结构有⼀个⼤概的了解Java内存运⾏时区域⼤概分了三部分其中PC寄存器、java虚拟机栈、本地⽅法栈3个区域是所有线程独有的⼀块区域,随线程⽽⽣,随线程⽽灭。

栈中的栈帧随着⽅法的进⼊和退出⽽有条不紊地执⾏着⼊栈和出栈操作。

每⼀个栈帧中分配多少内存基本上是在类结构确定下来时就已知的,因此这⼏个区域的内存分配和回收都具备确定性,在这⼏个区域内就不需要过多考虑回收的问题,因为⽅法结束或者线程结束,内存⾃然就跟随着回收了。

⽽Java堆和⽅法区则不⼀样,⼀个接⼝中的多个实现类需要的内存可能不⼀样,⼀个⽅法中的多个实现类需要的内存可能不⼀样,⼀个⽅法中的多个分⽀需要的内存也可能不⼀样,只有在程序处于运⾏期间时才能知道会创建哪些对象,这部分内存的分配和回收是动态的,垃圾收集关注的是这部分的内存。

⼆. 内存分配在解垃圾回收之前,得先了解JVM是怎么分配内存的,然后识别哪些内存是垃圾需要回收,最后才是⽤什么⽅式回收。

Java的内存分配原理与C/C++不同,C/C++每次申请内存时都要malloc进⾏系统调⽤,⽽系统调⽤发⽣在内核空间,每次都要中断进⾏切换,这需要⼀定的开销,⽽Java虚拟机是先⼀次性分配⼀块较⼤的空间,然后每次new时都在该空间上进⾏分配和释放,减少了系统调⽤的次数,节省了⼀定的开销,这有点类似于内存池的概念;⼆是有了这块空间过后,如何进⾏分配和回收就跟GC机制有关了。

三. 垃圾检测(标记)算法什么样的对象才是垃圾?如果⼀个对象没有被其他对象所引⽤该对象就是⽆⽤的,此对象就被称为垃圾,其占⽤的内存也就要被销毁。

那么⾃然⽽然的就引出了我们的第⼆个问题,判断对象为垃圾的算法都有哪些?标记垃圾的算法Java中标记垃圾的算法主要有两种,引⽤计数法和可达性分析算法。

Java垃圾回收机制总结

Java垃圾回收机制总结

Java垃圾回收机制总结java垃圾回收机制释放那些不再被任何活动对象引⽤的java对象从GC Root作为起点,进⾏链路访问,可以达到的是活跃对象,达不到的是不活跃对象,会被回收。

被GC Root引⽤的对象:虚拟机栈中引⽤的对象⽅法区中的类静态属性引⽤的对象⽅法区中常量引⽤的对象本地⽅法栈中JNI中引⽤的对象GC的算法:引⽤计数:引⽤了+1,没有引⽤-1,为0就被回收。

缺点:现在不⽤了;每次对象赋值需要维护引⽤计数器,计数器本⾝也是⼀种消耗;较难处理循环引⽤。

复制:Young区--Old区Young区:Eden,From,To第⼀步:当Eden区满时会触发第⼀次GC,把还活着的对象拷贝到Survivor from区,当Eden'区再次触发GC时,会扫描Eden区和From区,对这两个区域进⾏垃圾回收,还存活着的放到To区,同时把年龄加1。

如果到达⽼年的标准,放到Old区。

⼀般是15.第⼆步:清空eden和survivorFrom,复制之后有交换,谁空谁是To。

第三步:To和From互换。

⼀般交换15次还是存活,就放⼊⽼年代。

(MaxTenuringThreshold决定)。

优点是没有碎⽚。

缺点是空间⽤的多。

标记清除(mark-sweep)先标记出要回收的对象,然后统⼀回收这些对象。

优点:节约空间。

缺点:会有碎⽚。

标记整理压缩(mark-compact)先标记,再次进⾏扫描,并往⼀端滑动存活对象。

优点:没有碎⽚。

缺点:需要移动对象的成本。

耗时间四种主要的垃圾收集器:串⾏,并⾏,并发,GC。

它们的具体实现:1. Serial(串⾏):单线程环境下使⽤⼀个线程进⾏GC。

会Stop-the-world。

新⽣代⽤的复制,⽼年代⽤的标记压缩。

简单⾼效,对单个cpu环境并且没有线程交互的开销,性能⽐较好。

开启⽅式:-xx:+useSerialGC。

默认的⽼年代是SerialOld。

2. ParNew(并⾏):多个GC收集器并⾏⼯作。

Java垃圾回收机制

Java垃圾回收机制

Java垃圾回收机制对于Java垃圾回收机制,这个很久前就学过,并且理解过了,好长时间不⽤,就丢到回⽖洼岛了,这⾥还是记下,⽅便以后再次查看,不⽤浪费太多时间。

了解Java垃圾回收机制,就要知道Java各个版本的区别,尤其是随着JDK版本的提升,都⽐较以前版本有哪些改进。

最近,尤其是JDK1.7中加⼊了G1,这个是增加的新的回收⽅式,起始在JDK1.6 40左右的版本的时候就已经加⼊实验性的G1了。

线⾯是我转发的博⽂,⾃⼰写没那么多时间,有两篇不错,两篇各有互补点。

第⼀篇:说的⽐较多,但不是太详细垃圾收集GC(Garbage Collection)是Java语⾔的核⼼技术之⼀,之前我们曾专门探讨过Java 7新增的垃圾回收器G1的新特性,但在JVM 的内部运⾏机制上看,Java的垃圾回收原理与机制并未改变。

垃圾收集的⽬的在于清除不再使⽤的对象。

GC通过确定对象是否被活动对象引⽤来确定是否收集该对象。

GC⾸先要判断该对象是否是时候可以收集。

两种常⽤的⽅法是引⽤计数和对象引⽤遍历。

总的来说,可分为两⼤类引⽤计数收集器引⽤计数是垃圾收集器中的早期策略。

在这种⽅法中,堆中每个对象(不是引⽤)都有⼀个引⽤计数。

当⼀个对象被创建时,且将该对象分配给⼀个变量,该变量计数设置为1。

当任何其它变量被赋值为这个对象的引⽤时,计数加1(a = b,则b引⽤的对象+1),但当⼀个对象的某个引⽤超过了⽣命周期或者被设置为⼀个新值时,对象的引⽤计数减1。

任何引⽤计数为0的对象可以被当作垃圾收集。

当⼀个对象被垃圾收集时,它引⽤的任何对象计数减1。

优点:引⽤计数收集器可以很快的执⾏,交织在程序运⾏中。

对程序不被长时间打断的实时环境⽐较有利。

缺点:⽆法检测出循环引⽤。

如⽗对象有⼀个对⼦对象的引⽤,⼦对象反过来引⽤⽗对象。

这样,他们的引⽤计数永远不可能为0.跟踪收集器早期的JVM使⽤引⽤计数,现在⼤多数JVM采⽤对象引⽤遍历。

对象引⽤遍历从⼀组对象开始,沿着整个对象图上的每条链接,递归确定可到达(reachable)的对象。

Java垃圾回收机制

Java垃圾回收机制

Java垃圾回收机制Java垃圾回收机制对象被判定为垃圾:没有被其他对象引⽤⼀、判定对象是否为垃圾的算法1. 引⽤计数算法判断对象的引⽤数量1. 通过判断对象的引⽤数量来决定对象是否可以被回收2. 每个对象实例都有⼀个引⽤计数器,被引⽤则+1,完成引⽤则-13. 任何引⽤计数为0的对象实例可以被当做垃圾收集优点:执⾏效率⾼,程序执⾏受影响较⼩缺点:⽆法检测出循环引⽤的情况,导致内存泄漏2. 可达性分析算法通过判断对象的引⽤链是否可达来决定对象是否可以被回收可以作为GC Root的对象1. 虚拟机栈中引⽤的对象(栈帧中的本地变量表)2. ⽅法区中常量引⽤对象3. ⽅法区中的类静态属性引⽤的对象4. 本地⽅法栈中JNI(Native⽅法)的引⽤对象5. 活跃线程的引⽤对象⼆、垃圾回收算法1. 标记-清除算法(Mark and Sweep)标记:从根集合进⾏扫描,对存活的对象进⾏标记清除:对堆内存从头到尾进⾏线性遍历,回收不可达对象内存缺点:碎⽚化2. 复制算法(Copying)分为对象⾯和空闲⾯对象在对象⾯上创建存活的对象被从对象⾯复制到空闲⾯将对象⾯所有对象内存清除优点:解决碎⽚化问题顺序分配内存,简单⾼效适⽤于对象存活率低的场景3. 标记-整理算法(Compacting)标记:从根集合进⾏扫描,对存活的对象进⾏标记整理:移动所有存活的对象,且按照内存地址次序依次排列,然后将末端内存地址以后的内存全部回收优点:避免内存的不连续不⽤设置⼆块内存互换适⽤于存活率⾼的场景4. 分代收集算法(Generational Collector)垃圾回收算法的组合拳按照对象⽣命周期的不同划分区域以采⽤不同的垃圾回收算法按照对象⽣命周期的不同划分区域以采⽤不同的垃圾回收算法⽬的:提⾼JVM的回收效率三、GC分类1. Minor GC (复制算法)年轻代:尽可能快速地收集掉那些⽣命周期短的对象Eden区两个Survivor区(From、To)对象如何晋升到⽼年代经历⼀点Minor次数依然存活的对象(默认:15)Survivor区中存放不下的对象新⽣成的⼤对象(-XX:+PretenuerSizeThreshole)常⽤的调优参数-XX:SurvivorRatio:Eden和Survivor的⽐值,默认8:1-XX:NewRatio:⽼年代和年轻代内存⼤⼩的⽐例-XX:MaxTenuringThreshold:对象从年轻代晋升到⽼年代经过GC次数的最⼤阈值2. Full GC⽼年代:存放内存周期较长的对象标记-清理算法标记-整理算法Full GC 和 Major GCFull GC⽐Minor GC慢,但执⾏频率低触发Full GC的条件⽼年代空间不⾜永久代空间不⾜(元空间替代了永久代,降低FullGC的频率,减少Full GC的负担,提⾼其效率)CMS GC时出现promotion failed(Minor GC回收时,Survivor放不下 -> ⽼年代也放不下),concurrent mode failure(执⾏CMS GC过程中,对象放⼊⽼年代,⽼年代空间不⾜)Minor GC晋升到⽼年代的平均⼤⼩⼤于⽼年代剩余的空间调⽤System.gc();使⽤RMI来进⾏RPC或管理JDK应⽤,每⼩时执⾏⼀次Full GCStop-the-WorldJVM由于要执⾏GC⽽停⽌了应⽤程序的执⾏任何⼀种GC算法都会发⽣多数GC优化通过减少Stop-the-World发⽣的时间来提⾼程序性能Safepoint分析过程中对象引⽤关系不会发⽣变化的点产⽣Satepoint的地⽅:⽅法调⽤;循环跳转;异常跳转等安全点数量得适中常见的垃圾收集器JVM的运⾏模式ServerClient1. 年轻代常见的垃圾收集器01. Serial收集器(-XX:+UseSerialGC,复制算法)单线程收集,进⾏垃圾收集时,必须暂停所有⼯作线程简单⾼效,Client模式下默认的年轻代收集器02. ParNew收集器(-XX:+UseParNewGC,复制算法)多线程收集,其余的⾏为、特点和Serial收集器⼀样单核执⾏效率不如Serial,在多核下执⾏才有优势03. Parallel Scavenge收集器(-XX:+UseParallelGC,复制算法)吞吐量 = 运⾏⽤户代码时间 / (运⾏⽤户代码时间 + 垃圾收集时间)⽐起关注⽤户线程停顿时间,更关注系统的吞吐量在多核下执⾏才有优势,Server模式下默认的年轻代收集器2. ⽼年代常见的垃圾收集器01. Serial Old收集器(-XX:+UseSerialOldGC, 标记-整理算法)单线程收集,进⾏垃圾收集时,必须暂停所有⼯作线程简单⾼效,Client模式下默认的⽼年代收集器02. Parallel Old收集器(-XX:+UseParallelOldGC, 标记-整理算法)多线程,吞吐量优先03. CMS收集器(-XX:+UseConcMarkSweepGC, 标记-清除算法)1. 初始标记:stop-the-World2. 并发标记:并发追溯标记,程序不会卡顿3. 并发预清理:查找执⾏并发标记阶段从年轻代晋升到⽼年代的对象4. 重新标记:暂停虚拟机,扫描CMS堆中的剩余对象5. 并发清理:清理虚拟机,程序不会停顿6. 并发重置:重置CMS收集器的数据结构04. G1收集器(-XX:+UseG1GC,复制+标记-整理算法)Garbage First收集器的特点并发和并⾏分代收集空间整合可预测的停顿Garbage First收集器将整个Java堆内存划分成多个⼤⼩相等的Region年轻代和⽼年代不在物理隔离。

JVM的生命周期、体系结构、内存管理和垃圾回收机制

JVM的生命周期、体系结构、内存管理和垃圾回收机制

JVM的⽣命周期、体系结构、内存管理和垃圾回收机制⼀、JVM的⽣命周期JVM实例:⼀个独⽴运⾏的java程序,是进程级别JVM执⾏引擎:⽤户运⾏程序的线程,是JVM实例的⼀部分1. JVM实例的诞⽣当启动⼀个java程序时.⼀个JVM实例就诞⽣了,任何⼀个拥有public static void main(string[] args)的函数都可以作为实例的运⾏启点2. JVM实例运⾏main作为程序初始化线程的起点,任何其他线程由其启动。

JVM有两种线程:守护线程和⾮守护线程。

守护线程由JVM使⽤。

main启动后将是⾮守护线程。

3. JVM实例消亡当程序中所有⾮守护线程都中⽌时,JVM退出;若安全管理器允许,程序也可以使⽤Runtime类或者System.exit()退出。

⼆、JVM的体系结构1. Class Loader 类加载器类加载器的作⽤是加载类⽂件到内存,ClassLoader只管加载,只要符合⽂件结构就加载,⾄于说能不能运⾏,则不是它负责的,那是由Execution Engine负责,只要符合《JVM Specification》中式这样定义Class⽂件的结构。

2. Execution Engine 执⾏引擎执⾏引擎也叫做解释器(Interpreter),负责解释命令,提交操作系统执⾏。

3. Native Interface本地接⼝本地接⼝的作⽤是融合不同的编程语⾔为Java所⽤,它的初衷是融合C/C++程序,的具体做法是Native Method Stack中登记native⽅法,在Execution Engine执⾏时加载native libraies。

4. Runtime data area运⾏数据区运⾏数据区是整个JVM的重点。

我们所有写的程序都被加载到这⾥,之后才开始运⾏。

整个JVM框架由加载器加载⽂件,然后执⾏器在内存中处理数据,需要与异构系统交互是可以通过本地接⼝进⾏。

JVM性能优化--Java的垃圾回收机制

JVM性能优化--Java的垃圾回收机制

JVM性能优化--Java的垃圾回收机制⼀、Java内存结构1、Java堆(Java Heap) java堆是java虚拟机所管理的内存中最⼤的⼀块,是被所有线程共享的⼀块内存区域,在虚拟机启动时创建。

此内存区域的唯⼀⽬的就是存放对象实例,这⼀点在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。

java堆是垃圾收集器管理的主要区域,因此也被成为“GC堆”(Garbage Collected Heap)。

从内存回收⾓度来看java堆可分为:新⽣代和⽼⽣代。

从内存分配的⾓度看,线程共享的Java堆中可能划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer,TLAB)。

⽆论怎么划分,都与存放内容⽆关,⽆论哪个区域,存储的都是对象实例,进⼀步的划分都是为了更好的回收内存,或者更快的分配内存。

根据Java虚拟机规范的规定,java堆可以处于物理上不连续的内存空间中。

当前主流的虚拟机都是可扩展的(通过 -Xmx 和 -Xms 控制)。

如果堆中没有内存完成实例分配,并且堆也⽆法再扩展时,将会抛出OutOfMemoryError异常。

2、Java虚拟机栈(Java Virtual Machine Stacks) java虚拟机也是线程私有的,它的⽣命周期和线程相同。

虚拟机栈描述的是Java⽅法执⾏的内存模型:每个⽅法在执⾏的同时都会创建⼀个栈帧(Stack Frame)⽤于存储局部变量表、操作数栈、动态链接、⽅法出⼝等信息。

咱们常说的堆内存、栈内存中,栈内存指的就是虚拟机栈。

局部变量表存放了编译期可知的各种基本数据类型(8个基本数据类型)、对象引⽤(地址指针)、returnAddress类型。

局部变量表所需的内存空间在编译期间完成分配。

在运⾏期间不会改变局部变量表的⼤⼩。

这个区域规定了两种异常状态:如果线程请求的栈深度⼤于虚拟机所允许的深度,则抛出StackOverflowError异常;如果虚拟机栈可以动态扩展,在扩展是⽆法申请到⾜够的内存,就会抛出OutOfMemoryError异常。

Java垃圾回收机制

Java垃圾回收机制

Java垃圾回收机制本⽂转⾃:垃圾回收的意义如果不进⾏垃圾回收,内存迟早会被消耗空。

垃圾回收机制的引⼊可以有效的防⽌内存泄露、保证内存的有效使⽤,也减轻了Java程序员的对内存管理的⼯作量。

内存泄露:指该内存空间使⽤完毕后未回收,在不涉及复杂数据结构的⼀般情况下,Java的内存泄露表现为⼀个内存对象的⽣命周期超出了程序需要它的时间长度,我们有是也将其称为“对象游离”。

垃圾回收机制中的算法垃圾回收算法需要做的基本事情:发现⽆⽤对象回收被⽆⽤对象占⽤的内存空间,使该空间可被程序再次使⽤1. 可达性检测算法1.1 引⽤计数法(Reference Counting Collector)引⽤计数是垃圾收集器中的早期策略。

此⽅法中,堆中的每个对象都会添加⼀个引⽤计数器。

每当⼀个地⽅引⽤这个对象时,计数器值+1;当引⽤失效时,计数器值-1。

任何时刻计数值为0的对象就是不可能再被使⽤的。

这种算法⽆法解决对象之间相互引⽤的情况。

⽐如对象有⼀个对⼦对象的引⽤,⼦对象反过来引⽤⽗对象,它们的引⽤计数永远不可能为0。

public class Main {public static void main(String[] args) {MyObject object1 = new MyObject();MyObject object2 = new MyObject();object1.object = object2;object2.object = object1;object1 = null;object2 = null;}}最后⾯两句将object1和object2赋值为null,也就是说object1和object2指向的对象已经不可能再被访问,但是由于它们互相引⽤对⽅,导致它们的引⽤计数器都不为0,那么垃圾收集器就永远不会回收它们。

1.2 根搜索算法(可达性分析算法)由于引⽤计数法存在缺陷,所有现在⼀般使⽤根搜索算法。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
//承关系而获得的资源
}
卸载
在类使用完之后,如果有下面的情况,类就会被卸载: 该类所有的实例都已经被回收,也就是java堆中不存在该类的任何实例。 加载该类的ClassLoader已经被回收。 该类对应的ng.Class对象没有任何地方被引用,无法在任何地方通 过反射访问该类的方法。 如果以上三个条件全部满足,jvm就会在方法区垃圾回收的时候对类进行 卸载,类的卸载过程其实就是在方法区中清空类信息,java类的整个生命 周期就结束了。
堆区:用于存放类的对象实例。
栈区:也叫java虚拟机栈,是由一个一个的栈帧组成的后进先出的栈式结构, 栈桢中存放方法运行时产生的局部变量、方法出口等信息。当调用一个方法时, 虚拟机栈中就会创建一个栈帧存放这些数据,当方法调用完成时,栈帧消失, 如果方法中调用了其他方法,则继续在栈顶创建新的栈桢。
ቤተ መጻሕፍቲ ባይዱ
java类的生命周期
finalize()方法。通常在该方法内包括了释放系统资源的代码段。 finalize( )方法在类ng.Object中实现
如: protected void finalize ( ) throws throwable{
…… // clean up code for this class super. finalize( ); //清除对象使用的所有资源,包括由于继
Demo1 Demo2
在类的初始化阶段,只会初始化与类相关的赋值语句和静态语句, 也就是有static关键字修饰的信息,没有static修饰的赋值语句和静态语 句在实例化对象的时候才会运行。
使用(对象生命周期)
当类初始化完成后,根据类信息在堆区中实例化类对象,初始化非静 态变量、非静态代码以及默认构造方法,
加载阶段是类的生命周期中的第一个阶段,加载阶段之后,是连 接阶段。有一点需要注意,就是有时连接阶段并不会等加载阶段完全完成 之后才开始,而是交叉进行,可能一个类只加载了一部分之后,连接阶段 就已经开始了。但是这两个阶段总的开始时间和完成时间总是固定的:加 载阶段总是在连接阶段之前开始,连接阶段总是在加载阶段完成之后完成。
垃圾回收机制
垃圾回收是Java程序设计中内存管理的核心概念,JVM的内存管理机制被称为 垃圾回收机制。
一个对象创建后被放置在JVM的堆内存中,当永远不再引用这个对象时,它 将被JVM在堆内存中回收。被创建的对象不能再生,同时也没有办法通过程 序语句释放它们。
在做Java应用开发时经常会用到由JVM管理的两种类型的内存:堆内存和 栈内存。简单来讲,堆内存主要用来存储程序在运行时创建或实例化的对象 与变量。例如通过new关键字创建的对象。而栈内存则是用来存储程序代码中 声明为静态或非静态的方法。
格式: new 类的构造方法

new Rectangle(100, 200);
Rectangle rect = new Rectangle(100, 200);
3、初始化对象
每个类都至少有一个构造函数,当创建对象时调
用指定的构造函数来初始化对象

Rectangle rect = new Rectangle();
Rectangle rect = new Rectangle(100, 200);
在定义类时如未定义构造函数系统,java会自动构造一个没
有参数的构造函数。
对象的使用
使用对象包括: 从对象中获得信息 改变对象的状态 使对象执行某些操作
实现途径: 引用对象的变量 调用对象的方法
引用对象变量的格式:
当我们编写一个java的源文件后,经过编译会生成一个后缀名为 class的文件,这种文件叫做字节码文件,只有这种字节码文件才能够 在java虚拟机中运行,java类的生命周期就是指一个class文件从加载到 卸载的全过程。
一个java类的完整的生命周期会经历加载、连接、初始化、使用 (即对象生命周期)、和卸载五个阶段
创建对象 对象的使用
清除对象
创建对象
通过创建一个对象可创建类的一个实例, 也称实例化此类。
例Rectangle rect = new Rectangle();
创建一个对象包括三部分: 声名部分 实例化部分 初始化部分
1、对象声明并不创建新的对象。
例:
Rectangle rect;
2、实例化对象
操作符new通过为新对象分配存储空间来实例化类
public static void main(String[] args) { Parcel1 p = new Parcel1(); p.ship("Hello");
} }
在外部类外访问内部类的基本语法如下所示。 Wai.Nei wn=new Wai().new Nei();
对象引用.对象的变量
SubInitClass2 aClass2=new SubInitClass2(); int b=aClass2.num;
调用对象的方法 格式: 对象引用.对象方法名();
或 对象引用.对象方法名(参数表); 例
Field2 field2=new Field2();
field2.Method();
初始化
在初始化阶段,JAVA虚拟机执行类的初始化语句,为类的静态变量赋予初始值。在 程序中,静态变量的初始化有两种途径:
1、在静态变量的声明处进行初始化
2、在静态代码块中进行初始化。
public class InitClass{ public static String a = “nihao”; //静态变量的声明处进行初始化
static {
//在静态代码块中进行初始化。
System.out.println("初始化InitClass");
}
}
静态变量的声明语句,以及静态代码块都被看做类的初始化语句,java虚拟 机会按照初始化语句在文件中的先后顺序来依次执行他们。 如果有父类,则首先按照顺序运行父类中的变量赋值语句和静态语句。
第九章、JAVA 生命周期和垃圾回收机制
首先来了解一下jvm(java虚拟机)中的几个比较重要的内存区域,这几 个区域在java类的生命周期中扮演着比较重要的角色:
方法区:在java的虚拟机中有一块专门用来存放已经加载的类信息、常量、静 态变量以及方法代码的内存区域,叫做方法区。
常量池:常量池是方法区的一部分,主要用来存放常量和类中的符号引用等信 息。
堆内存主要用来存储程序在运行时创建或实例化的对象与变量。例如通 过new关键字创建的对象。而栈内存则是用来存储程序代码中的方法。
补充知识:内部类
内部类(Inner class)是定义在另一个类中的类。
当A类为B类服务时,为不让外界直接访问到A类,可把这个A类定义在 B类的内部,变为内部类。
内部类的基本语法: [修饰符] class 外部类{
连接—准备
准备:准备阶段的工作就是为类的静态变量分配内存并设为jvm默认的初值, 对于非静态的变量,则不会为它们分配内存。有一点需要注意,这时候,静态 变量的初值为jvm默认的初值,而不是我们在程序中设定的初值。jvm默认的初 值是这样的: 基本类型(int、long、short、char、byte、boolean、float、double)的默认 值为0。 引用类型的默认值为null。 常量的默认值为我们程序中设定的值,比如我们在程序中定义final static int a = 100,则准备阶段中a的初值就是100。
知识回顾
复习java异常处理机制: Throwable
Exception
Error
RuntimeException …… IOException VirtualMachineError …… NullPointerException ArithmeticException …… FileNotFoundException ……
连接
连接阶段比较复杂,一般会跟加载阶段和初始化阶段交叉进行,这个阶段的主要任 务就是做一些加载后的验证工作以及一些初始化前的准备工作,可以细分为三个步 骤:验证、准备和解析。
验证
准备
解析
连接—验证
验证:当一个类被加载之后,必须要验证一下这个类是否 合法,比如这个类是不是符合字节码的格式、变量与方法 是不是有重复、数据类型是不是有效、继承与实现是否合 乎标准等等。总之,这个阶段的目的就是保证加载的类是 能够被jvm所运行。
连接—解析
解析:这一阶段的任务就是把常量池中的符号引用转换为直接引用。 那么什么是符号引用,什么又是直接引用呢?我们来举个例子:我们 要找一个人,我们现有的信息是这个人的身份证号是1234567890。 只有这个信息我们显然找不到这个人,但是通过公安局的身份系统, 我们输入1234567890这个号之后,就会得到它的全部信息:比如湖 北省武汉市武汉大学张三,通过这个信息我们就能找到这个人了。这 里,123456790就好比是一个符号引用,而湖北省武汉市武汉大学张 三就是直接引用。在内存中也是一样,比如我们要在内存中找一个类 里面的一个叫做show的方法,显然是找不到。但是在解析阶段,jvm 就会把show这个名字转换为指向方法区的的一块内存地址,比如 c17164,通过c17164就可以找到show这个方法具体分配在内存的哪 一个区域了。这里show就是符号引用,而c17164就是直接引用。在 解析阶段,jvm会将所有的类或接口名、字段名、方法名转换为具体 的内存地址。
清除对象
java运行使系统有一个垃圾回收进程负责清除不再使用的对象。 垃圾回收器
垃圾回收器定期扫描内存,对于被应用的对象加上标记, 按可能的路径扫描结束后清除未加标记的对象。 被回收的对象是: 不再被任何引用变量引用的对象 引用变量自动放弃 人为地将引用变量置为null
finialize()方法 在一个对象被垃圾回收器回收之前,java解释器会自动调用对象的
相关文档
最新文档