《java虚拟机》----垃圾收集、内存分配
No1:
程序计数器、虚拟机栈、本地方法栈3个区域随线程而生,随线程而灭:栈中的栈帧随着方法的进入和退出而有条不紊的执行着出栈和入栈操作。每一个栈帧中分配多少内存基本上市在类结构确定下来时就已知的,因此这几个区域的内存分配和回收都具备确定性,在这几个区域内就不需要过多考虑回收的问题,因为方法结束或者线程结束时,内存自然就跟随着回收了。
而java堆和方法区则不一样,一个接口中的多个实现类需要的内存可能不一样,一个方法中的多个分支需要的内存也可能不一样,我们只有在程序处于运行期间才能知道会创建哪些对象,这部分内存的分配和回收都是动态的,垃圾收集器所关注的是这部分内存。
No2:
引用计数算法:给对象中添加一个引用计数器,当有一个地方引用它时,计数器就+1,当引用失效,则-1,任何时刻计数器为0的对象就是不可能再被使用的。
No3:
可达性分析算法:基本思路就是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。
在java语言中,可作为GC Roots的对象包括下面几种:
1.虚拟机栈(栈帧中的本地变量表)中引用的对象
2.方法区中类静态属性引用的对象
3.方法区中常量引用的对象
4.本地方法中JNI引用的对象
No4:
1.强引用就是指在程序代码中普遍存在的,只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象
2.软引用描述一些还有用但并非必需的对象。在系统将要发生内存溢出出异常之前,将会把这些对象列进回收范围之中进行第二次回收。
3.弱引用也是描述非必需对象。当垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象
4.为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。
No5:
可达性分析算法
第一次收集:当对象可达性分析后发现没有与GC Roots相连,则进行第一次筛选:没有复写finalize()方法或已经调用过finalize()方法,则进行标记为没有必要执行;如果判定为有必要执行finalize()方法,则对象将被放置在一个F-Queue队列中
第二次收集:只要对象在finalize()中重新与引用链上任何一个对象建立关联即可移除“即将回收”的集合,如果没有逃脱,基本就真的被回收了
No6:
在堆中,新生代进行一次垃圾收集一般可回收70%~95%的空间,而永久代的垃圾收集效率远低于此。
永久代的垃圾收集主要回收两部分内容:废弃常量和无用的类。
No7:
类需要同时满足下面3个条件才能算是“无用的类”:
1.该类所有的实例都已经被回收,也就是java堆中不存在该类的任何实例
2.加载该类的ClassLoader已经被回收
3.该类对应的java.lang.Class对象没有在任何地方被引用,无法再任何地方通过反射访问该类的方法
No8:
垃圾收集算法:标记-清除算法
两个不足:
1.效率问题。标记和清除两个过程的效率都不高
2.空间问题。标记清除猴会产生大量不连续的内存碎片,空间碎片太多可能会导致需要分配大对象时,无法找到足够的连续内存而不得不提前出发一次垃圾收集动作
No9:
垃圾收集算法:复制算法(为了解决效率而生)
将内存分为大小相等的两块,每次只用其中一块,当其中一块用完,就将存活对象复制到另外一块上面,然后将原内存空间一次清理掉。代价是内存缩小为原来的一半,另外较多的复制也会将效率变低
所以此算法常用来回收新生代
No10:
垃圾收集算法:标记-整理算法
标记过程和标记-清除算法一样,但后续步骤是让所有存活对象向一端移动,然后直接清理掉端边界以外的内存
此算法常用来回收老年代
No11:
分代收集算法:新生代选用复制算法,老年代选用标记-清除或标记-整理算法
No12:
安全点设置:
1.抢先式中断:GC发生时,先中断所有线程,发现有线程不在安全点上,就恢复跑到安全点。这种方式已经不用了
2.主动式中断:仅仅简单设置一个标志,各个线程执行时主动轮询这个标志,发现标志为真就自己中断挂起,轮询标志地方和安全点是重合的。
No13:
安全区域是指在一段代码片段之中,引用关系不会发生变化。在这个区域中的任意地方开始GC都是安全的。
No14:
收集器:Serial收集器(单线程收集器)
特点:简单而高效
常用来回收新生代,收集几十兆甚至一两百兆的新生代,停顿时间完全可控制在十几毫秒最多一百多毫秒以内。
No15:
收集器:ParNew收集器(Serial的多线程版本)
新生代首选收集器
No16:
并行(Parallel):多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态
并发(Concurrent):用户线程与垃圾收集线程同时执行(不一定是并行的,可能会交替执行),用户程序在继续运行,而垃圾收集程序运行于另一个CPU上。
No17:
收集器:Parrel Scavenge收集器(新生代收集器,使用复制算法,并行多线程)
它的目标是达到一个可控制的吞吐量(吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间))
高吞吐量可以高效率的利用CPU时间,尽快完成程序的运算任务,主要适合在后台运算而不需要太多交互的任务
虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量,这种调节方式称为GC自适应的调节策略。自适应调节策略也是Parallel Scavenge收集器与ParNew收集器的一个重要区别。
No18:
收集器:Serial Old是Serial收集器的老年代版本(单线程,使用标记-整理算法)
No19:
收集器:Parallel Old收集器(Parallel Scavenge收集器的老年代版本,多线程、使用标记整理算法)
No20:
收集器:CMS收集器(标记-清除算法)
是一种以获取最短回收停顿时间为目标的收集器
步骤:
1.初始标记 仅仅标记GC Roots能直接关联到的对象
2.并发标记 进行GC Roots Tracing的过程(耗时最长)
3.重新标记 修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录
4.并发清除
优点:并发低停顿
缺点:1.当CPU不足4个时,CMS会占用一半的运算能力去执行收集器线程,导致用户程序的执行速度忽然降低了50%
2.无法处理浮动垃圾,可能出现Concurrent Mode Failure(并发模式失败)失败而导致另一次Full GC的产生,这样停顿的时间就很长了
浮动垃圾:CMS并发清理阶段用户线程还在运行着,伴随程序运行自然就会有新的垃圾不断产生,这部分垃圾出现在标记过程之后,CMS无法在当次收集处理掉他们,只好留待下一次GC时再清理掉。
3.当空间碎片太多而提前触发Full GC时,停顿时间也会变长
No21:
收集器:G1收集器
特点:
1.并发与并行 充分利用CPU、多核环境下的硬件优势,使用多个CPU来缩短Stop-The-World停顿的时间
2.分代收集
3.空间整合 整体上基于标记-整理算法,局部(两个Region之间)基于复制算法
4.可预测的停顿 建立可预测的停顿时间模型,能明确指定在长度为M毫秒的时间片段内,垃圾收集消耗时间不得超过N毫秒
运作步骤 1.初始标记 2.并发标记 3.最终标记 4.筛选回收
每个Region都有一个与之对应的Remembered Set,类似对象引用的标示符,为了避免全堆扫描
No22:
新生代GC(Minor GC):发生在新生代的垃圾收集动作,因为java对象大多都具备朝生夕灭的特性,所以Minor GC非常频繁,一般回收速度也比较快
老年代GC(Major GC/Full GC):发生在老年代的GC,出现了Major GC,经常会伴随至少一次的Minor GC(但非绝对的,在Parallel Scavenge收集器的收集策略里就有直接进行Major GC的策略选择过程),Major GC的速度一般会比Minor GC慢10倍以上
No23:
内存分配和回收策略
1.对象优先在新生代Eden区中分配:当Eden区没有足够空间时,虚拟机将发起一次Minor GC
2.大对象直接进入老年代(最典型的大对象就是那种很长的字符串以及数组)
3.长期存活的对象将进入老年代:对象在Survivor区中没熬过一次Minor GC,年龄就增加1岁,当年龄增加到默认15岁时晋升为老年代
4.动态对象年龄判定:如果Survivor空间中相同年龄所有对象大小总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代
5.空间分配担保:当出现大量对象在Minor GC后仍然存活的情况,就需要老年代进行分配担保,把Survivor无法容纳的对象直接进入老年代,否则将尝试进行一次Full GC;(因为新生代使用复制收集算法)
101
《java虚拟机》----垃圾收集、内存分配的更多相关文章
- 《深入理解Java虚拟机》内存分配策略
上节学习回顾 1.判断对象存活算法:引用计数法和可行性分析算法 2.垃圾收集算法:标记-清除算法.复制算法.标记-整理算法 3.垃圾收集器: Serial:新生代收集器,采用复制算法,单线程. Par ...
- java虚拟机的内存分配与回收机制
分为4个方面来介绍内存分配与回收,分别是内存是如何分配的.哪些内存需要回收.在什么情况下执行回收.如何监控和优化GC机制. java GC(Garbage Collction)垃圾回收机制,是java ...
- Java虚拟机:内存分配策略
版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! Java中提倡的自动内存管理机制最终可以归结为自动化的解决两个问题:给对象分配内存和回收分配给对象的内存.在之前的博客中已经详细讲解了内存 ...
- java虚拟机之内存分配
Java 的自动内存管理主要是针对对象内存的回收和对象内存的分配.同时,Java 自动内存管理最核心的功能是 堆 内存中对象的分配与回收. JDK1.8之前的堆内存示意图: 从上图可以看出堆内存分为新 ...
- 【java虚拟机】内存分配与回收策略
作者:平凡希 原文地址:https://www.cnblogs.com/xiaoxi/p/6557473.html 前言 对象的内存分配,往大的方向上讲,就是在堆上分配,少数情况下也可能会直接分配在老 ...
- java虚拟机的内存分配
java程序在执行时,jvm的内存执行方案.
- 从Java虚拟机的内存区域、垃圾收集器及内存分配原则谈Java的内存回收机制
一.引言: 在Java中我们只需要轻轻地new一下,就可以为实例化一个类,并分配对应的内存空间,而后似乎我们也可以不用去管它,Java自带垃圾回收器,到了对象死亡的时候垃圾回收器就会将死亡对象的内存回 ...
- Java虚拟机垃圾收集器与内存分配策略
Java虚拟机垃圾收集器与内存分配策略 概述 那些内存须要回收,什么时候回收.怎样回收是GC须要完毕的3件事情. 程序计数器.虚拟机栈与本地方法栈这三个区域都是线程私有的,内存的分配与回收都具有确定性 ...
- 深入理解JAVA虚拟机 垃圾收集器和内存分配策略
引用计数算法 很多教科书判断对象是否存活的算法是这样的:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1:当引用失效时,计数器值就减1:任何时刻计数器都为0的对象就是不可能再被使用的 ...
- 1 - JVM随笔分类(java虚拟机的内存区域分配(一个不断记录和推翻以及再记录的一个过程))
java虚拟机的内存区域分配 在JVM运行时,类加载器ClassLoader在加载到类的字节码后,交由jvm的执行引擎处理, 执行过程中需要空间来存储数据(类似于Cpu及主存),此时的这段空间的分 ...
随机推荐
- Android 统一配置依赖管理
Android Studio中默认就是使用Gradle来构建管理工程的,当我们在工程构建过程中创建了多个Module时,就可能存在一个问题,那就是每个Module以及Module中一些公用库的依赖存在 ...
- UVA 12063 Zeros and Ones
https://vjudge.net/problem/UVA-12063 题意: 统计n为二进制数中,0和1相等且值为m的倍数的数有多少个 dp[i][j][k] 前i位二进制 有j个1 值模m等于k ...
- 贪心法:K叉哈夫曼树
NOI2015荷马史诗 一部<荷马史诗>中有 n 种不同的单词,从 1 到 n 进行编号.其中第 i 种单词出现的总次数为 wi.Allison 想要用 k 进制串 si 来替换第 i 种 ...
- 使用Java代码发送SMTP邮件
package cn.Douzi.send; import javax.mail.Session; import javax.mail.Transport; import javax.mail.int ...
- Grass is Green
Root 3719 - Grass is Green Time limit: 3.000 seconds This year exactly n <tex2html_verbatim_ma ...
- [转]标准C++中的string类的用法总结
原文地址:http://www.cnblogs.com/xFreedom/archive/2011/05/16/2048037.html 相信使用过MFC编程的朋友对CString这个类的印象应该非常 ...
- 登入时session的处理方式
暂时理解不够彻底 有空在详细介绍,先记录代码 1:创建一个工具类 存取当前登录用户 package com.liveyc.eloan.util; import javax.servlet.http ...
- 从python入门ruby
1.Ruby的函数可以不使用括号 def h(name) puts "hello #{name}" end h "jack" 2.python可以直接访问实例的 ...
- UTF8字符串转换为汉字 c#
using System; /// <summary> /// UTF8字符串转换为汉字用的类 /// 转换如"\\u8d35"之类的字符串为对应的汉字 /// < ...
- C语言回调函数总结
/* Main program ---calls--> Library function ---calls--> Callback funtion */ #include <stdi ...