• 虚拟机JVM


    虚拟机

    1、定义
    
    • 1

    jvm 假想计算机 运行在操作系统之上 和硬件之间没有直接交互
    包括 一套字节码指令、寄存器、栈、垃圾回收、堆 一个存储方法域
    jvm:承担一个翻译工作,动态的将java代码编译成操作系统可以识别的机器码。
    从软件层面屏蔽了不同操作系统在底层硬件与指令上的区别
    jre:java 运行时环境 提供类库

    
    
    • 1

    类加载机制:7步

    
    加载-验证-准备-解析-初始化-使用-卸载
    加载:通过全限定类名来获取定义此类的二进制字节流/
              将字节流所代表的静态存储结构转化为方法区的运行时数据结构
    验证:验证文件等格式
    准备:变量字符开辟空间
    解析:解析引用关系
    初始化:赋值
    启动类加载器 bootstrap ClassLoader c++ lib包 虚拟机能够识别的类库
    扩展类加载器 exe lib/ext 能够被java使用
    应用类加载器 appcation classpath 用户类路径 应用 的三方类库
    不是继承关系 组合关系
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/3d313949db56488da7a97e445022e019.png)
    
    
    运行时数据区
    执行引擎
    2、java代码执行:
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    javac编译为.class文件
    classLoader装载class
    解释执行 编译执行class文件

    3、内存管理
    
    • 1

    3.1结构
    共享:
    堆:创建的对象和数组都保存在堆内存中 采用分代收集算法
    方法区:永久代,用于存储被jvm加载的类信息、常量、静态变量、即时编译后的代码等数据。
    私有:栈、本地方法栈、程序计数器
    栈:每个方法在执行的同时都会创建一个栈帧(用来存储数据和部分过程结果的数据结构),用来存储局部变量表,操作数栈,动态链接,方法出口等信息,
    每一个方法从调用直至执行完成的过程,就应对着一个栈帧在虚拟机栈中入栈到出栈的过程。
    在这里插入图片描述
    运行时数据区

    栈:
    
    • 1

    filo:first in last out
    和方法调用相关
    反汇编 javap -c math.class
    局部变量表 istore_1 赋值
    操作数栈 :iconst_1,iload(加载值),bipush(操作结果压栈)
    动态链接:符号引用 方法区和栈之间(方法名称、类名都是一些符号)
    方法出口:栈帧和栈帧之间 方法执行完回到主方法的栈位置
    在这里插入图片描述

    在这里插入图片描述

    `

    程序计数器

    `私有,记录程序运行行数位置,因为java是多线程运行,可能当前线程运行一半,过来一个比当前线优先执行的线程,这样当前线程挂起,执行另一个线程,执行完后继续从当前虔诚的位置执行当前线程。字节码执行器动态修改
    在这里插入图片描述

    在这里插入图片描述
    调优工具
    jmap jstack arthas(*阿里巴巴)
    stw:为了防止对象变量从垃圾和非垃圾之间来回切换
    动态年龄判断机制 :如果对象大小大于s区百分之50,直接挪到老年代
    内存比值
    3.2内存分配 new Object
    首选TLAB:(Thread Local Allocation Buffer)线程本地分配缓冲区

    https://zhuanlan.zhihu.com/p/393972460
    堆上分配(可能存在多线程安全问题)
    new Object() 在堆内存中开辟一块内存空间,多线程并发在堆中开辟空间存在安全问题,但
    加锁又会影响性能
    所以就引出了 TLAB
    new 对象会在堆中的eden区进行分配,分配结束后会进行一次yong gc ,如果对象没有被回收,存活年龄加1,达到15次,才会晋升到老年代,TLAB在eden区分配出私有的TLAB,并发创建也就不需要加锁了,如果分配的TLAB被用完,就会在公用的Eden区分配内存空间,所以堆区严格上说并不是线程共享。

    栈上分配
    在这里插入图片描述

    垃圾回收
    
    • 1

    1、如何区分垃圾
    引用计数法
    可达性分析法:将gc roots对象作为起点,向下搜索引用的对象,找到的都标记为非垃圾对象
    gcRoots 根节点:线程的本地变量、静态变量、本地方法栈的变量等
    2、回收算法
    1、标记清除法 碎片化严重
    2、复制算法 解决碎片化 但效率低
    3、标记整理算法 标记好不清楚 将存活的对象移动到内存的一端 然后清除端边界外的对象
    4、常用的分代收集算法
    核心思想:根据对象存活的不同生命周期将内存划分为不同的域
    一般情况下将 GC 堆划分为老生代(Tenured/Old Generation)和新生代(Young
    Generation)。老生代的特点是每次垃圾回收时只有少量对象需要被回收,新生代的特点是每次垃圾回收时都有大量垃圾需要被回收,因此可以根据不同区域选择不同的算法
    新生代:复制算法
    老年代 :标记复制算法
    方法区的永生区 存储class类、常量方法 主要回收废弃的常量无用的类
    5、分区收集算法
    分为连续的不同小区间 每个小区间独立使用 独立回收

    垃圾回收器
    
    • 1

    1、Serial 连续垃圾回收器(单线程、复制算法)
    他工作其余的工作线程暂停 效率高,所以仍然是java虚拟机运行在client模式下默认的新生代垃圾回收器
    2、ParNew 垃圾回收器(Serial+多线程 复制算法)
    也需要暂停所有工作线程
    ParNew垃圾收集器是很多 java虚拟机运行在 Server 模式下新生代的默认垃圾收集器
    3、Parallel Scavenge 收集器(多线程复制算法、高效)
    平行清除
    它重点关注的是程序达到一个可控制的吞吐量(Thoughput,CPU 用于运行用户代码
    的时间/CPU 总消耗时间,即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)),高吞吐量可以最高效率地利用 CPU 时间,尽快地完成程序的运算任务,主要适用于在后台运算而不需要太多交互的任务。自适应调节策略也是 ParallelScavenge 收集器与 ParNew 收集器的一个重要区别
    4、Serial Old 单线程标记整理算法
    是serial 老年代版本 使用标记整理算法 默认老年代client的收集器
    在 Server 模式下,主要有两个用途:

    1. 在 JDK1.5 之前版本中与新生代的 Parallel Scavenge 收集器搭配使用。
    2. 作为年老代中使用 CMS 收集器的后备垃圾收集方案。
      5、parallel Old收集器 多线程标记标记整理算法
      是parallel Scavenge 的老年代版本 1.6之后提供的
      两者搭配保障吞吐量
      6、CMS 收集器 多线程标记清除算法
      Concurrent mark sweep 老年代垃圾收集器
      7、G1收集器 多线程标记整理算法

    java引用
    强引用 把一个对象赋给一个引用变量,这个引用变量就是强引用,它处于可达状态不可能被回的 所以强引用是造成java内存泄漏的主要原因之一

  • 相关阅读:
    python毕设选题 - 大数据商城人流数据分析与可视化 - python 大数据分析
    破解wifi密码 暴力破解 保姆式教学
    基于SCL语言的模拟量平均值滤波FB库功能介绍及创建FB库的具体方法
    【学习笔记】无人机系统(UAS)的连接、识别和跟踪(一)-3GPP TS 23.256 技术规范概述
    纸牌游戏设计制作《摸鱼2》(C语言)
    Selenum八种常用定位(案例解析)
    Ubuntu下运行adb devices找不到设备的问题
    多 Activity 多 Page 的 UI 架构
    Unity延时函数
    Linux驱动开发:掌握SPI通信机制
  • 原文地址:https://blog.csdn.net/weixin_44019875/article/details/136203704