jvm学习笔记(三)

jvm学习笔记(三)

1.全部笔记链接

JVM学习笔记(一)
JVM学习笔记(二)
JVM学习笔记(三)
JVM学习笔记(四)

(待更新…)

2.堆

是被线程共享的一块内存区域,创建的对象和数组都保存在 Java 堆内存中,也是垃圾收集器进行

垃圾收集的最重要的内存区域。由于现代 VM 采用分代收集算法, 因此 Java 堆从 GC 的角度还可以

细分为: 新生代(Eden 区From Survivor 区To Survivor 区)和老年代。

2.1堆的划分

关于堆的划分,需要明确一点:

  • 逻辑上堆是包含新生代,老年代和永久代(JDK1.8叫元空间)
  • 物理上应该是:新生代+老年代,在JDK1.8后,永久代变成了元空间,并且元空间被移到本地内存,而不再虚拟机内存中。
使用JVM参数查看划分
-Xms1024m -Xmx1024m -XX:+PrintGCDetails

一般查看PrintGCDetails都会带上PermGen区(永久代),虽然可以查看打印信息中有Young Generation,Old Generation,PermGen(或者Metaspace),当是计算的时候会发现Heap=Young Generation+Old Generation

永久代:(方法区,不属于java堆,另一个别名为“非堆Non-Heap”)

Hotspot堆内存划分图(JDK8之前)

在这里插入图片描述

Heap划分为:

  • Young Generation(占1/3)
  • Old Generation(占2/3)

Young Generation又划分为:

  • Eden Space(伊甸园,占8/10)
  • From Space(幸存区1,占1/10)
  • To Space(幸存区2,占1/10)

From Space和To Space是两个幸存区,而这两个区域并非一成不变,这两个区域在GC的过程会进行交换。

2.2 GC对堆的回收

GC的种类

GC用来回收堆中不再使用的对象,GC分两种:

  • MinorGC(轻GC)
  • MajorGC (重GC)

一般情况下,会触发MinorGC,MajorGC 不会频繁执行。

之前看复习资料以为GC单纯两种,后来发现还要其他GC模式,然后上网查阅了相关资料,然后得出以下结论:

以下内容来自知乎: https://www.zhihu.com/question/41922036

针对HotSpot VM的实现,它里面的GC其实准确分类只有两大种:

  • Partial GC:并不收集整个GC堆的模式

    • Young GC:只收集young gen的GC
    • Old GC:只收集old gen的GC。只有CMS的concurrent collection是这个模式
    • Mixed GC:收集整个young gen以及部分old gen的GC。只有G1有这个模式
  • Full GC:收集整个堆,包括young gen、old gen、perm gen(如果存在的话)等所有部分的模式。

Major GC通常是跟full GC是等价的,收集整个GC堆。但因为HotSpot VM发展了这么多年,外界对各种名词的解读已经完全混乱了,当有人说“major GC”的时候一定要问清楚他想要指的是上面的full GC还是old GC。

作者:RednaxelaFX
链接:https://www.zhihu.com/question/41922036/answer/93079526
来源:知乎

MinorGC的过程

由于频繁创建对象,所以新生代会频繁触发MinorGC 进行垃圾回收。当 Eden 区内存不够的时候就会触发 MinorGC,对新生代区进行一次垃圾回收。MinorGC使用的是复制算法,过程如下:

  1. MinorGC会把Eden Space+From Space扫描一边
  2. 扫描过后将存活的对象复制到 To Space 区域,并对对象的年龄进行+1
  3. 然后清空Eden Space+From Space的对象
  4. 最后,将To Space和From Space标志互换(不移动对象,区域的标志更换,就是To变成From),To Space等待下次MinorGC的回收。
MajorGC的过程(Old GC)

老年代的对象比较稳定,所以 MajorGC 不会频繁执行。大部分对象会在MinorGC过程中消亡,而一般只有部分的能进入老年代。在进行 MajorGC 前一般都先进行了一次 MinorGC,使得有新生代的对象晋身入老年代,导致空间不够用时才触发。MajorGC 通常采用标记清除算法或标记整理算法(其实也不能说MajorGC就是标记清除算法,使用哪种算法对老年代进行垃圾回收完全取决于使用的那种垃圾回收器),垃圾回收器将在其他学习笔记中的介绍,现在先说一下标记清除算法,标记清除算法过程如下:

  • 首先扫描一次所有老年代,标记出存活的对象。
  • 然后回收没有标记的对象。
Full GC

当准备要触发一次young GC时,如果发现统计数据说之前young GC的平均晋升大小比目前old gen剩余的空间大,则不会触发young GC而是转为触发full GC(因为HotSpot VM的GC里,除了CMS的concurrent collection之外,其它能收集old gen的GC都会同时收集整个GC堆,包括young gen,所以不需要事先触发一次单独的young GC);或者,如果有perm gen的话,要在perm gen分配空间但已经没有足够空间时,也要触发一次full GC;或者System.gc()、heap dump带GC,默认也是触发full GC。

作者:RednaxelaFX
链接:https://www.zhihu.com/question/41922036/answer/93079526

2.3 一些调节参数

调节堆

#调节大小
-Xmx -Xms
#控制Eden和Survivor的比例
-XX:SurvivorRatio
#调节Young和Old的比例
-XX:NewRatio
#调节永久代初始大小(JDK1.8不用了)
-XX:PermSize
#调节永久代大小最大值
-XX:MaxPermSize

垃圾回收的一些参数

#垃圾最大年龄
-XX:MaxTenuringThreshold

3. OOM

3.1 简介

OOM,全称“Out Of Memory”,源于java.lang.OutOfMemoryError。当JVM因为没有足够的内存来为对象分配空间并且垃圾回收器也已经没有空间可回收时,就会抛出这个error。

3.2 排错

内存快照分析工具,MAT,Jprofiler。作用分析Dump内存文件,快速定位内存泄漏。

输出Dump文件

#内存泄漏时输出dump文件
-XX:HeapDumpOnOutOfMemoryError
#重GC前输出dump文件
-XX:+HeapDumpBeforeFullGC
#指定dump文件目录
-XX:HeapDumpPath=xxx

输出Dump文件**

#内存泄漏时输出dump文件
-XX:HeapDumpOnOutOfMemoryError
#重GC前输出dump文件
-XX:+HeapDumpBeforeFullGC
#指定dump文件目录
-XX:HeapDumpPath=xxx

dump出来的内存文件,用Jprofiler可以查看到其内存分配情况,并且通过线程快照 可以查看到在哪一行代码导致内存泄漏。

posted @   鸭梨的药丸哥  阅读(2)  评论(0编辑  收藏  举报  
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示