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

 

posted @ 2020-08-20 16:31  julian^-^  阅读(133)  评论(0)    收藏  举报