4. JVM内存管理

news/2024/11/28 9:40:11/

JVM是什么?
JVM是一种规范.

JVM用来干什么?
Java虚拟机将字节码文件(.class)编译成操作系统可以识别的机器码.

Java程序的执行过程
java程序首先经过javac编译成.class文件,然后jvm将其翻译成操作系统可以识别的机器码.

JVM、JRE、JDK之间的关系
JVM只是一个翻译,将字节码文件翻译成机器识别的代码
JRE除了包含JVM外,提供了很多类库(jar包)
JDK除了包含JRE外,还提供了一些非常好用的小工具,如:javac(编译代码)、javap(反编译代码)、jar(打包代码)、java

运行时数据区(除此之外还有:直接内存)

  • 方法区 (线程共享区)
  • (线程共享区)
  • 虚拟机栈 (线程私有区)
  • 本地方法栈 (线程私有区)
  • 程序计数器 (线程私有区)

每个私有线程包含一个虚拟机栈,每个虚拟机栈中可以包含多个栈帧,我们代码中执行的每个方法会被封装成一个个的栈帧

栈帧的组成部分

  • 局部变量表

  • 操作数栈

  • 动态连接

  • 返回地址

    程序计数器的作用(只会记录虚拟机栈,不会记录本地方法栈)
    程序计数器用于记录栈帧中字节码代码执行的偏移量,有些字节码代码可能会占多行,所以计数器在记录的时候可能中间存在缺失某个行号的情况,如12345679,中间没有执行第8行代码,因为第7行代码占2个偏移量,所以后面接9

    操作数栈的作用
    操作数栈用于在栈帧中定义变量和运算时,将定义的变量放到操作数栈,然后在将这个变量从操作数栈取出,存放到局部变量表中.

    局部变量表的作用
    局部变量表用于将操作数栈的数据存入到局部变量表中,局部变量表是以索引和变量的值的形式来做存储的.

    返回地址的作用
    一个方法在执行完成后,会将局部变量表中的索引给返回出来,通过这个索引就可以拿到该位置存储的变量的值.

方法区
存字节码文件(如:Tearcher.class,类加载的时候放方法区)、静态变量、常量

JVM内存处理全流程

  • JVM申请内存
  • 初始化运行时数据区
  • 类加载
  • 执行方法
  • 创建对象


堆空间的分代划分

Java对象的分配与垃圾回收机制

JVM中对象的创建过程

  • 检查加载
  • 分配内存 (划分内存方式、并发安全问题)
  • (内存空间)初始化 (‘零’值)
  • 设置 (对象头)
  • 对象初始化 (构造方法)

划分内存的方式

  • 指针碰撞
  • 空闲列表

解决并发安全

  • CAS加失败重试
  • 本地线程加缓冲

对象

  • 对象头
    • 存储对象自身的运行时数据(Mark Word)
      • 哈希码
      • GC分代年龄
      • 锁状态标识
      • 线程持有的锁
      • 偏向线程ID
      • 偏向时间戳
    • 类型指针
    • 若对象为数组,还应该有记录数组长度的数据
  • 实例数据
  • 对其填充(非必须)

对象的访问定位 到对象类型数据的指针、对象的实例数据

  • 使用句柄 (搞不明白) 堆内存包括:句柄池和实例池
  • 直接指针 (搞不明白) 堆内存

判断对象的存活

  • 引用计数法 (缺陷:对象相互引用)
  • Class回收条件 (回收条件比较苛刻,需要满足以下所有条件)
    1. class new出的所有对象都要被回收掉(反射创建的对象)
    2. 对应的类加载器也要被回收掉
    3. 类,java.lang.class对象
    4. 任何地方都没有被引用,并且无法通过反射调用这个类的方法
    5. 参数控制(-Xnoclassgc参数需要关闭)
  • 可达性分析(根可达GC roots)
    • 静态变量
    • 线程栈变量(局部变量)
    • 常量池
    • JNI指针
    • 内部引用:Class对象、异常对象Exception、类加载器
    • 同步锁,synchronized对象
    • 内部对象,JMXBean
    • 临时对象:跨代引用
  • finalize

堆内存划分(新时代占1/3,老年代占2/3)

  • 新时代 EdenFrom(S0) To(S1 ) 内存占用比例:8:1:1
  • 老年代 Tenured

对象的分配策略

  • 对象的分配原则
    • 对象优先分配到Eden区
    • 空间分配担保
    • 大对象直接进入老年代
    • 长期存活的对象进入老年代
    • 动态对象年龄判定
  • 虚拟机的优化技术
    • 逃逸分析 + 触发JIT(热点数据)
    • 本地线程分配缓冲

垃圾回收算法

  • 复制回收算法 (Appel式复制回收算法(利用Eden、S0、S1):提高空间利用率和空间分配担保)

    实现简单、运行高效
    没有内存碎片(将GC Roots对象复制到另外一半空间,然后清除之前的那一半空间)
    空间利用率只有一半

  • 标记-清除算法

    位置不连续、产生碎片(清除垃圾对象后剩余空间不连续)
    可以做到不暂停(在清理垃圾对象时,GC Roots对象仍然可以正常操作)

  • 标记-整理算法

    没有内存碎片(标记-整理-清除,将GC Roots对象整理成连续的对象,然后再清除垃圾对象,剩余的空间就是连续的)
    指针需要移动

CMS(Concurrent Mark Sweep)-并发垃圾回收器
标记清除算法,用于减少Stop The World(SWT)响应时间
专门用来处理堆内存中老年代垃圾
清理垃圾步骤

  • 初始标记
  • 并发标记 (可能包含了预清理、并发可中断预清理、CMS日志查看)
  • 重新标记
  • 并发清除

CMS中的问题

  • CPU敏感 (需要4核CPU及以上的处理器)
  • 浮动垃圾 (在并发清理阶段可能产生新的垃圾,而这些新的垃圾只能等到下一次垃圾清理的时候再处理,所以CMS需要预留一片内存空间,用于存放并发清理时产生的垃圾.)
  • 内存碎片 (标记清除算法导致的)

JVM硬核调优技巧
1.JVM内存的分代划分?
新生代、老年代和持久代(永久代/元空间占1~1.5 倍活跃数据大小)
依据活跃数据来分配新生代、老年代的大小,堆内存大小为活跃数据的4倍,新生代为活跃数据的1-1.5倍,老年代为活跃数据的2-3倍大小
如:
活跃数据占300M
总堆: 300M * (3~4倍) = 1.2G
新生代: 300M * (1~1.5倍) = 450M
老年代: 300M * (2~3倍) = 750M

2.扩充新生代或 Eden区能提高GC效率吗?
一般情况下是可以提高GC效率的,因为新生代扩容后,内存达到一原来2倍的容量时才会进行垃圾回收,所以GC回收的时间间隔会变长;而大部分对象都是新生代的,由于新生代扩容,可能这些对象在增长的这段GC回收时间间隔内,由GC Roots对象变成了可回收的垃圾对象,所以能更高的对垃圾对象进行回收.
还有因为容量小时候,短时间内对对象进行GC回收,会扫描Eden区中的GC Roots对象,然后将他们复制到S0或S0,复制相较与扫描,会花费更多的时间;扩容新生代后明显能减少复制的时间.

3.JVM如何避免Minor GC会扫描全堆的?
利用卡表(card table)存储老年代中是否有新生代的引用,解决新生代与老年代跨代扫描问题,就只需要扫描新生代和卡表,而不需要再扫描整个堆内存(新生代+老年代)

常量池?

  • Class常量池 (通过javap反编译.class文件可以看到Constant pool中的数据)
  • 运行时常量池 (符号引用->直接引用)
  • 字符串常量池 (String)

String

  • 为什么说String是不可改变的?

    这个类final类型的
    public final class String
    同时里面的数组value也是final类型的
    private final char[] value;

  • String的创建方式
    • String str = “abc”;
      代码在编译加载时,会在常量池中创建常量“abc”,运行时,返回常量池中字符串的引用.
    • String str = new String("abc");
      代码编译加载时,会在常量池中创建常量“abc”;
      在调用new时,会在堆中创建String对象,并引用常量池中的字符串对象char[]数组(String源码中本就是char[] value),并返回String对象的引用

http://www.ppmy.cn/news/68974.html

相关文章

尚硅谷JUC

文章目录 1. 什么是JUC1.1 JUC简介1.2 进程和线程基本概念2.1 Synchronized2.1.1 Synchronized关键字2.1.2 synchronized实现三个线程卖30张票 2.2 Lock2.2.1 什么是Lock2.2.2 使用Lock实现买票功能2.2.3 两者的区别 3. 线程间通信及定制化通信3.1 使用synchronized实现线程之间…

Nginx总结

目录 Nginx介绍 Nginx的作用 反向代理 项目架构 实战:访问nginx服务器反向代理到另一台虚拟机上的tomcat服务器 负载均衡 项目架构 实战:访问nginx服务器,是否反向代理到集群中的任意一台tomcat服务器,停止一台tomcat服务器&…

Redisson锁的分析

文章目录 一、分布式锁概念1、实现思路2、出现死锁问题如何避免死锁问题 锁过期和释放当前不属于当前线程的锁解决不是加锁线程释放锁锁的过期时间如何解决 二、Redisson分布式锁Redis的部署方式对锁的影响集群模式Redlock实现高可靠的分布式锁 三、代码分析V1代码无锁V2代码单…

基于AT89C51单片机的电子密码锁设计与仿真

点击链接获取Keil源码与Project Backups仿真图: https://download.csdn.net/download/qq_64505944/87779960?spm=1001.2014.3001.5503 源码获取 主要内容: 设计一个单片机电子密码锁,根据输入的数值判断是否正确,正确显示密码正确;错误时报警器发出蜂鸣。由单片机系统…

RabbitMQ养成记 (6. spingboot 集成 rabbitMQ,生产者/消费者)

Springboot集成 搞springboot的那群人 不喜欢造轮子,就喜欢搞各种集成。 首先创建一个springboot项目: 之前我们在方法中 创建工厂类配置, 现在直接在application.yml 中配置即可: spring:rabbitmq:host: **********username:…

Nvidia技术路线和卷积神经网络介绍

1.Nvidia技术路线概述 2.卷积神经网络介绍 软硬件平台 目的:用卷积神经网络(CNNs)将车前部摄像头捕捉到的原始像素图映射为汽车的方向操控命令。 训练:这套端到端学习系统使用了NVIDIA DevBox, 用Torch 7进行训练。 操作:一台 NVIDIA DRIVE PX 自动驾驶汽车计算…

Ch3.栈、队列、数组

文章目录 1.栈1.栈的基本概念2.栈的性质卡特兰数栈的出栈顺序3.栈的实现1.顺序栈 (栈的顺序存储实现)共享栈2.链栈(栈的链式存储实现)4.栈的应用(1) 括号匹配(2) 表达式求值(中缀表达式→后缀表达式)(3)递归(4)进制转换2.队列1.队列的概念2.队列的性质3.队列的实现(1)顺序队…

滨州软件著作权申请

各省、自治区、市版权局负责本辖区作者或者其他作权人作品的登记。国家版权局负责外国、台湾、香港、澳门作者或者其他作权人作品的登记。受国家版权局委托,中国版权保护中心负责外国、台湾、香港、澳门作者或者其他作权人作品的登记。 作者或者其他享有作权的公民所…