2021-JVM 知识点重温

1.Hotspot jvm 运行时数据区可划分为5区域 堆、方法区,虚拟机栈、本地方法栈、程序计数器
    (1) 线程共享区: 堆 、 方法区
         > 堆:存储系统创建的对象
         > 方法区:常量、静态变量、编译后的类的元信息

    (2) 线程私有区: 虚拟机栈、本地方法栈、程序计数器
         > java虚拟机栈:每个线程的运行产生一个虚拟机栈,虚拟机栈中存放的是一个个栈帧(方法),一个方法生成一个栈帧
           > 栈帧:【操作数栈】【动态链接】【方法返回】【局部变量表】
             注:vm 会做优化,将操作数栈和局部变量表进行公用当存在操作数传递
         > 本地方法栈: 同java虚拟机栈
         > 程序计数器: 记录程序执行的下一条指令引用地址

    (3) 堆 Hotspot 采用 分代划分的思想
         细分:(1) Eden - from - to ; (2) old
         jdk8 vm 默认采用的是 PSPV 组合,堆自动分配

    (4) OOM out of memory Error
         栈:stack overflow error 出现 栈深度超过配置的栈的大小
         堆溢出:出现内存泄露
         方法区溢出: 不断的创建类
         直接内存溢出: 不合理的资源分配导致

    (5) jvm 内存分配
        5.1 指针碰撞 / 空闲列表
            指针碰撞:适用于内存比较规整的堆 复制算法
            空闲列表:采用标记清除算法的堆区域
            注:并发安全的问题
              指针碰撞采用的 CAS + 重试策略
              空闲列表:线程的本地缓冲 每个线程都会分配一块内存区域,如果分配的不够用才会采用CAS申请

    (6) 常量池
        class常量池: java版本号 / 常量 / 字面量 / 符号引用 类编译后的的字节码 (javap -v Axxx.class)
        运行时常量池: 符号引用的直接引用
        字符串常量池: 字符创
       
   (7) 进程间通信:信号量 管道[命名管道/匿名管道] 消息队列 套接字(unix domain socket) 

2. 对象的创建
   (1)加载验证 (2) 准备 赋初值 (3)分配内存 (4)解析 (5)初始化

   分配内存:(jvm规范中对象的大小必须是8字节的整数倍)
   对象在堆中的结构:
   (1)对象头
        mark word [ hash码,GC分代年龄[1111 最大值 15],锁状态,锁标志位,偏向标识,偏向时间戳 ] / 类型指针 / [数组长度]
   (2)对齐填充
       Object o = new Object(); 在堆中的大小 16 byte [开启指针压缩]
       对象头 mark word 占用 8个字节,class 类型指针占用4字节 填充数据占用 4 字节 16 字节;
        -XX:+UseCompressedClassPointers -XX:+UseCompressedOops

                             对象头(12 / 16)                 对齐填充(4 / 0 )           变量(o)一个变量槽 (4 / 8)
        开启压缩: mark word[8 字节] + classPointer[4字节] + 填充数据 [4字节]   = 16 字节        +    4字节
        关闭压缩: mark word[8 字节] + classPointer[8字节]                    = 16 字节        +     8字节

        o 变量 占用一个变量槽 +UseCompressedOops 占用 4字节,
        -UseCompressedOops 占用 8 字节
        UseCompressedClassPointers requires UseCompressedOops 所以至少 占用 20 字节

   分配内存的策略:
       (1)指针碰撞
           a. 并发冲突的解决:CAS + 重试机制
       (2)空闲列表
           b. 本地线程缓冲 Thread local allocate buffer TLAB技术

   对象引用方式:
      (1)直接指针
      (2)句柄池   堆中维护映射列表,记录引用地址和对象的堆中地址的映射关系 (好处当对象发生变化时,对象的引用不会发生变化,缺点,多一次寻址性能略低)

3. 对象的回收
   什么对象是垃圾?GC 才会回收?
   没有引用指向的对象, jvm
   (1)引用计数法 (缺点:无法解决循环引用)
   (2)可达性分析 以GCRoots为根开始扫描标记存活对象(也可标记需要清除对象)然后清除存活对象之外的对象

   GCRoots根对象的范围:
   (1)虚拟机栈 / 本地方法栈(native方法) 中引用的对象
   (2)方法区中静态变量引用的对象
   (3)方法区常量引用的对象
   (4)Class类类型对象 / ClassLoader对象 / 跨代引用对象
   (5)异常 / error 对象

   方法区中对象的回收?条件是比较苛刻的
   (1)Class类型的所有对象都已经被回收
   (2)改类的ClassLoader的类加载器已经被回收
   (3)在任何地方 使用反射也不能访问改对象内部信息
   (4)开启类型的回收-XXnoclassgc(建议关闭 提高GC效率)

   Object.finalize()
   尝试挽救一下对象,但是执行等级比较低,JVM并不证成功,而且只能执行一次,不推荐使用
   System.gc() // 实际开发中 禁用

   GC算法:         优点                    缺点
      标记-清除: 效率高,利用率 100%      产生内存碎片
      标记-整理: 利用率 100%,无碎片      由于要移动对象效率低于标记清除,移动重新标记 利用率 100%
      复制-算法: 简单高效,无碎片         每次使用一份将存活的对象拷贝到另一份省去了移动而且避免了内存碎片化

   注1:
    (1)jvm 采用的 伸缩式划分新生代区域根据新生代产生对象的特性:
        绝大所数对象为生命周期较短 每次GC 后存活下来的对象较少,将新生代区域划分为 Eden / s1 / s2 三部分
        对象优先分配在 Eden区,当Eden区存满时进行一次 新生代GC 存活的对象被拷贝到 s1 或 s2 之一,从而降低发生GC的频率,每次stw需要暂停用户线程
        GC要解决的就是尽量 缩短 STW 的时间获取最好的用户体验。

    (2)空间分配担保:
        GC后s区中已经无法满足 存活对象时,需要晋升到老年代
        需要晋升到老年代对象:
        (1)GC分代年龄达到最大值 15 (由来:对象头中标识对象分代年龄的 二进制位 4位 即10进制中的15)【CMS中为6】maxThreashold
        (2)当某一个分代的年龄对象总大小超过 s区 的一半时这些对象直接晋升
        (3)大对象
    (3)old 区
        根据采用的 垃圾收集器的不同 算法也不同
        标记-清除
        标记-整理

   注2: 由于gc算法各有优劣使用的场景也都有
    堆的采用分代的设计思路,而且【新生代】产生的对象多为 "短" 生命周期对象,回收的频率相对 ”长“ 生命周期的对象 ”频繁“
    新生代采用复制算法 Eden / from(s1) / to (s2)
    复制算法: 简单高效不会产生内存碎片, 浪费一半内存

   对象的分配策略
       <<<< 几乎所有的对象都在 堆上进行分配 >>>>>
        (1) 逃逸分析 -XX:+DoEscapeAnalysis
        (2) 栈上分配
        (3) 标量替换
    注:如果某个简单类型的对象,对象的作用域都没有逃出当前栈帧(方法),jvm 采取优化措施将对象打散在栈上进行分配,不存在 GC 出栈就被回收
   对象引用类型的分类:
        (1) 强引用 显示的 new 关键字创建的对象引用
        (2) 软引用 存活到下一次GC之后,如果还是不能满足所需空间则,会再次GC回收掉
        (3) 弱引用 一旦发生GC就会被回收
              如: ThreadLocal ThreadLocalMap 中的key 对当前ThreadLocal对象的弱引用
        (4) 虚引用 最弱的一种
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值