六、堆外内存
参考:堆外内存使用分析
五、jvm调优
四、Full GC有关问题学习分析
GC,尤其是Full GC,每次都会导致JVM暂停工作,处理垃圾回收任务,短时间内无法响应用户请求,大量的Full GC会导致系统响应速度降低,而且引来OOM的巨大风险。
三、对象 GC
当一个对象到GC Roots没有任何引用链相连时,则证明对象需要被回收.
Java可作为GC Roots的对象包括下面几种:
-
虚拟机栈(栈桢中的本地变量表)中的引用的对象
-
方法区中类静态属性引用的对象
-
方法区中常量引用的对象
-
本地方法栈中JNI引用的对象
二、垃圾收集
回收算法相关内容转自youzhixueyuan.com/detailed-ex…
1、CMS和G1的区别
- CMS中,堆被分为PermGen,YoungGen,OldGen;而YoungGen又分了eden区、两个survivo区域。在G1中,堆被平均分成几个区域(region),在每个区域中,虽然也保留了新老代的概念,但是收集器是以整个区域为单位收集的。
- G1在回收内存后会马上同时做合并空闲内存的工作、而CMS默认是在STW(stop the world)的时候做。
- G1会在Young GC (也在old GC)中使用、而CMS只能在O区使用。
整理:
-
cpu:
-
cms:对cpu敏感,在并发阶段虽不会导致用户线程停顿,但会因为占用了一部分线程使应用程序变慢 g1:并行于并发,G1能充分利用CPU、多核环境下的硬件优势,使用多个CPU来缩短stop-The-World停顿时间 -
应用在:
-
cms:处理老年代,g1:年轻代,老年代 -
垃圾回收算法:
-
cms:标记清理,容易产生垃圾碎片,等达到一定阈值会触发:标记整理 g1:标记整理,不会产生内存碎片 -
stop the world:cms:
-
cms:低停顿 g1:可预测停顿时间,明确指定一个长度为M毫秒的时间片段内,消耗在垃 圾收集上的时间不得超过N毫秒。
2、CMS:以获取最短回收停顿时间为目标的收集器,基于并发“标记清理”
过程:
-
1、初始标记:独占PUC,仅标记GCroots能直接关联的对象
-
2、并发标记:可以和用户线程并行执行,标记所有可达对象
-
3、重新标记:独占CPU(STW),对并发标记阶段用户线程运行产生的垃圾对象进行标记修正
-
4、并发清理:可以和用户线程并行执行,清理垃圾
优点: 并发,低停顿
缺点:
-
1、对CPU非常敏感:在并发阶段虽然不会导致用户线程停顿,但是会因为占用了一部分线程使应用程序变慢
-
2、无法处理浮动垃圾:在最后一步并发清理过程中,用户县城执行也会产生垃圾,但是这部分垃圾是在标记之后,所以只有等到下一次gc的时候清理掉,这部分垃圾叫浮动垃圾
-
3、CMS使用“标记-清理”法会产生大量的空间碎片,当碎片过多,将会给大对象空间的分配带来很大的麻烦,往往会出现老年代还有很大的空间但无法找到足够大的连续空间来分配当前对象,不得不提前触发一次FullGC,为了解决这个问题CMS提供了一个开关参数,用于在CMS顶不住,要进行FullGC时开启内存碎片的合并整理过程,但是内存整理的过程是无法并发的,空间碎片没有了但是停顿时间变长了
3、G1:是一款面向服务端应用的垃圾收集器,基于“标记-整理”算法
注:G1是并发收集器,怎么还会有并行线程数的概念呢? 为什么说并发线程数一定比并行线城数小呢? 即:并发是说gc线程和应用线程一块执行,并行是说多个gc线程一块执行。
特点:
-
1、并行于并发:G1能充分利用CPU、多核环境下的硬件优势,使用多个CPU(CPU或者CPU核心)来缩短stop-The-World停顿时间。部分其他收集器原本需要停顿Java线程执行的GC动作,G1收集器仍然可以通过并发的方式让java程序继续执行。
-
2、分代收集:分代概念在G1中依然得以保留。虽然G1可以不需要其它收集器配合就能独立管理整个GC堆,但它能够采用不同的方式去处理新创建的对象和已经存活了一段时间、熬过多次GC的旧对象以获取更好的收集效果。也就是说G1可以自己管理新生代和老年代了。
-
3、空间整合:由于G1使用了独立区域(Region)概念,G1从整体来看是基于“标记-整理”算法实现收集,从局部(两个Region)上来看是基于“复制”算法实现的,但无论如何,这两种算法都意味着G1运作期间不会产生内存空间碎片。
-
4、可预测的停顿:这是G1相对于CMS的另一大优势,降低停顿时间是G1和CMS共同的关注点,但G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用这明确指定一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒。
(1)、G1堆内存结构
- G1堆内存结构
堆内存会被切分成为很多个固定大小区域(Region),每个是连续范围的虚拟内存。
堆内存中一个区域(Region)的大小可以通过-XX:G1HeapRegionSize参数指定,大小区间最小1M、最大32M,总之是2的幂次方。
默认把堆内存按照2048份均分。
- G1堆内存分配
每个Region被标记了E、S、O和H,这些区域在逻辑上被映射为Eden,Survivor和老年代。
存活的对象从一个区域转移(即复制或移动)到另一个区域。区域被设计为并行收集垃圾,可能会暂停所有应用线程。
如上图所示,区域可以分配到Eden,survivor和老年代。此外,还有第四种类型,被称为巨型区域(Humongous Region)。Humongous区域是为了那些存储超过50%标准region大小的对象而设计的,它用来专门存放巨型对象。如果一个H区装不下一个巨型对象,那么G1会寻找连续的H分区来存储。为了能找到连续的H区,有时候不得不启动Full GC。
(2)、G1收集器的阶段分以下几个步骤:
1)G1执行的第一阶段:初始标记(Initial Marking )
这个阶段是STW(Stop the World )的,所有应用线程会被暂停,标记出从GC Root开始直接可达的对象。
2)G1执行的第二阶段:并发标记
从GC Roots开始对堆中对象进行可达性分析,找出存活对象,耗时较长,这一阶段耗时较长但能与用户线程并发运行。
3)最终标记(标记那些在并发标记阶段发生变化的对象,将被回收)
最终标记阶段需要吧Remembered Set Logs的数据合并到Remembered Set中,这阶段需要停顿线程,但可并行执行。
4)筛选回收(首先对各个Regin的回收价值和成本进行排序,根据用户所期待的GC停顿时间指定回收计划,回收一部分Region)
这一过程同样是需要停顿线程的
最后,G1中提供了两种模式垃圾回收模式,Young GC和Mixed GC,两种都是Stop The World(STW)的。
(3)、G1的GC模式
1. YoungGC年轻代收集
在分配一般对象(非巨型对象)时,当所有eden region使用达到最大阀值并且无法申请足够内存时,会触发一次YoungGC。每次younggc会回收所有Eden以及Survivor区,并且将存活对象复制到Old区以及另一部分的Survivor区。
YoungGC的回收过程如下:
根扫描,跟CMS类似,Stop the world,扫描GC Roots对象。
处理Dirty card,更新RSet.
扫描RSet,扫描RSet中所有old区对扫描到的young区或者survivor去的引用。
拷贝扫描出的存活的对象到survivor2/old区
处理引用队列,软引用,弱引用,虚引用
2. mixed gc
当越来越多的对象晋升到老年代old region时,为了避免堆内存被耗尽,虚拟机会触发一个混合的垃圾收集器,即mixed gc,该算法并不是一个old gc,除了回收整个young region,还会回收一部分的old region,这里需要注意:是一部分老年代,而不是全部老年代,可以选择哪些old region进行收集,从而可以对垃圾回收的耗时时间进行控制。
G1没有fullGC概念,需要fullGC时,调用serialOldGC进行全堆扫描(包括eden、survivor、o、perm)
一、类的加载
1、解析(resolve)就是将一个符号引用转换成直接引用的一个过程。
当一个java文件编译成class之后,方法都是以符号引用的方式保存。而在加载类时,部分符合条件的符号引用会被转换成**“直接引用”,这个过程我们称之为“解析(Resolution)”**。