jvm 之 自动内存管理
一.内存区域
私有的: 虚拟机栈,本地方法栈,程序计数器
公有地: 堆(heap),方法区(元空间包含方法区),运行时常量池(方法区的一部分),直接内存(directMemory,NIO产生,不包含在堆中)
Hotspot虚拟机的对象布局:
1. 每个线程在堆中都有一块分配对象的缓冲区 -XX:+/-TLAB来设定是否启用
2. 对象在堆中分为三部分:对象头,实例数据,对齐填充
3. 对象头中包括哈希值,gc分代年龄,锁状态,线程持有的...,
4. Hotspot没有句柄池,这样比较快,栈的本地变量的reference直接引用到堆里的对象,对象在引用到方法区的对象类型数据
二.GC
判断对象是否存活的算法
1. 计数算法 没引用一次,数量加一,为0则可以gc
2. 可达性分析 通过一系列GCroot分析是否能找到对象
GCRoots包括
1. Vm栈中引用的对象 如线程使用到的各种变量
2. 方法区中的静态属性
3. 方法区的常量属性 如 String常量池中
4. 虚拟机内部引用 如基本类型对应的Class对象 常驻的异常对象 类加载器
5. 被synchronize持有的的对象
6. 反映虚拟机内部情况的JMXBean,JVMMTI中的注册回调本地代码等
引用的分类: 强软弱虚
1.强 new关键字 永远不会被gc
2.软 SoftReference 堆不足时会被GC
3.弱 WeakReference GC时一定被GC
4.虚 PhantomReference 只是为了被GC时收到通知
方法区也是可以回收的 主要是卸载类
当前GC收集器大都采用分代收集,它建立在两个假说之上: 大多数对象很短暂,熬过越多次GC的对象越难失效
GC算法
1.标记-收集 缺点: 1.若对象很多且大多需要收集,那标记时间会很久 2.空间碎片化
2.标记-收集-复制(一般是新生代) 缺点: 只能使用一部分内存 一般来说8:1:1
3.标记-收集-整理 (一般是老年代) 相对于复制,把对象向一端移动
GC算法的实现者,垃圾收集器
新生代:
1.单线程的Serial(标记-复制) 用于CPU核心数较少(1-2)
2.多线程的ParNew(Serial并发版本 标记-复制)
3.吞吐量优先Parallel Scavenger (与parNew相似,标记-复制) 只能与parallel Old配合
老年代:
1.serial old (标记-整理) 只能与serial配合
2.parallel old(标记-整理) 可以与 scavenger 与serial 配合
3.CMS (并发标记收集器,标记-清除,产生碎片) 目标为低延迟 , 无法处理浮动垃圾,可能导致一次FullGC(stw),需要设置一个阈值(jdk6之后92%)
不区分,一个就够了
1.G1 遵循分代,内存划分为region(区域),每个region各自扮演新生代的Eden,survivor,老年代,专门的humongous存大对象,可以设置GC停顿
2.ZGC 内存占用大,可以管理很大的内存,最大4T, 停顿可以在10ms,无法处理浮动垃圾,可能导致FullGC
3.Shenandoah 只在openJDK里有
4.Epsilon只管分配不管清理的收集器
三.工具
命令行
1.jps java进程状态 jps -l hostid
2.jstat java虚拟机统计信息监视工具 jstat -gc vmid 250(间隔.毫秒) 20(次数)
3.jinfo java配置 jinfo -flag pid
4.jstack java jstack -l vmid
可视化工具 visualVM

浙公网安备 33010602011771号