无极修仙网站,为什么文件打开后是乱码,免费ui设计网站,外链查询网站目录
JVM三大问题
一、JVM内存区域划分
编辑 二、JVM类加载机制
双亲委派模型#xff08;常考)
类加载的格式#xff0c;类卸载
三、垃圾回收#xff08;GC)
具体垃圾回收GC步骤
1.判定对象是否为垃圾
方案1:引用计数
方案2#xff1a;可达性分析
2.释放对象的…目录
JVM三大问题
一、JVM内存区域划分
编辑 二、JVM类加载机制
双亲委派模型常考)
类加载的格式类卸载
三、垃圾回收GC)
具体垃圾回收GC步骤
1.判定对象是否为垃圾
方案1:引用计数
方案2可达性分析
2.释放对象的内存
1.标记-清除直接释放
2.复制算法
3.标记整理
4.JVM的垃圾回收机制 JVM三大问题 一、JVM内存区域划分 首先来到第一个问题什么是JVM呢 JVM可以说是java的虚拟机也可以叫做java的一个进程每一个java进程都是JVM实例 堆栈方法区程序计数器 成员变量-堆 局部变量引用类型也包括-栈 静态变量-方法区 一个进程的运行过程中就要从操作系统这里申请一些内存资源JVM也是如此搞了一大块内存供java代码执行的时候使用JVM吧这一块内存又划分出几个区域作为不同用途。 二、JVM类加载机制 把类从硬盘文件加载到内存中 JAVA程序最开始是写.java文件编译成.class文件字节码),运行java程序JVM就会读取.class文件把文件的内容放到内存中并且构造成.class对象类对象) 1.加载 找到.class文件打开文件读取文件内容并且尝试解析格式 在JAVA代码中是直接的使用类 2.验证 验证当前.class文件是否符合要求 介绍一下上面的字段意思: access_flags(相当于是不是public) attribute注解 minor_version:小版本号 constant-pool:常量池 java文件里写的信息有什么.class文件有所体现。 3.准备 给类对象分配内存最终的目标就是构建出完整的类对象分配内存初始化。 4.解析 主要是初始化类对象涉及到一些字符串常量其实字符串常量在.class文件就有了直接读到内存中就行了。 常量池内符号引用替换为直接引用的过程。相对位置经过偏移换到真实的内存地址) 相对位置是什么意思我们去看电影我知道电影的位置吗不知道因为我不知道他那个厅是怎么样的但是我知道我坐在小美的旁边。 5.初始化 对类对象进行更具体的初始化操作初始化静态成员初始化静态代码块加载父类 双亲委派模型常考) 描述在类加载过程中如何寻找.class文件。java圈子喜欢高大上的名字比如自动装箱拆箱其实不过也只是一个类型转换), JVM加载.class文件的时候需要用到类加载器模块JVM带了三个类加载器 Bootstrap ClassLoader 负责加载标准库的类JAVA有标准文档描述了都要提供哪些类 Extension ClassLoader 负责加载JVM扩展的库除了标准库之外实现JVM厂商还会添加一些类 Application ClassLoader 负责加载第三方库像之前用到的mysql,jdbc,servlet自己代码中写的类) 此处父子不是父类子类继承而是对象有一个parent引用指向父类类加载器实例 1. 从Application ClassLoader开始但是他并不会立即搜索第三方库的目录而是把加载任务委派给父亲让父亲先加载 2.到了Extension ClassLoader也不会立即搜索扩展库目录也是把加载任务委派给父亲也让父亲先尝试加载。 3.到了Bootstrap ClassLoader,也不想理机搜索标准库而是也想把任务给父亲但是他没有父亲只能自己动手来搜索了 如果找到了这个类会进行后续的加载也就和Application和Extension没关系了)没找到则把任务还给孩子给Extension完成 4.任务再次回到Extension ClassLoader手上他就要搜索扩展库的目录看没有匹配的,.class文件找到走没找到就给他的孩子 5.任务回到了Application ClassLoader,就要搜索第三方库的目录往往是你的项目目录以及和jvm一些配置项有关-classpath有关系 找到了就进行后续的加载找不到就要抛异常) 类加载中更重要更关键的是针对.class文件的解析校验。 类加载的格式类卸载 一个类什么时候会被加载呢懒汉模式 当我用到了才会加载 1.构造类的实例 2.使用了类的静态方法/静态属性 3.子类的加载会触发父类 类加载后后续就不必加载了 类卸载把类对象干掉) 属于是特殊情况 一般来说 一般来说类加载过后就不必考虑卸载。一直保存到程序运行结束 但是有的特殊场景可能用到卸载操作 有的服务器需要打“热补丁” 代码有bug,正常操作是修改代码重新编译用新的版本来去代替旧版本重启服务器有些特殊情况服务器不方便重启可以通过打补丁的方式通过一些特殊手段把需要替换的类给卸载掉直接用加载好的类去替换新版代码 有些情况不方便去重启服务器就可以通过“打补丁”的方式把需要替换的类替换掉直接用加载好的类卸载掉直接用加载好的新的类替换新版代码 热“并不需要重启也不需要重新编译” 冷“不需要重新编译但是需要重启“ JAVA这里用的补丁较少游戏可能会多一点比如不停服更新 三、垃圾回收GC) 于是JAVA引入了垃圾回收机制自动去判定某个内存是否会被继续使用如果不会就把这个内存当成垃圾 JVM有好多内存分区那么GC回收的是哪里的对象呢 栈首先不需要GC去回收栈里面包含很多栈帧 栈不需要GC回收吗栈里包含很多”栈帧“一个栈帧对应一个方法该方法执行结束此时这个栈帧就销毁了栈帧上的局部变量啥的自然销毁。 程序计数器同理线程销毁自然也跟着销毁 方法区类对象很少会涉及到对象的卸载 堆才是GC的主要战场 具体垃圾回收GC步骤 1.判定对象是否为垃圾 判定对象是否是垃圾的方式-看是否有引用指向他 方案1:引用计数 给这个对象安排一个计数器每次有引用指向他它就把计数器1每次引用被销毁计数器-1当计数器为0的时候意味着该对象就是垃圾了。 下列代码是对应的过程。 引用计数的两个明显的缺陷 1.空间利用率比较低浪费更多的内存空间 如果给引用计数分配了两个字节对象本体才四个字节的话引用计数就浪费了50%的空间如果代码中都是这些小对象并且数量众多此时浪费非常明显了就。 2.可能存在循环引用的问题导致对象不能被正确识为垃圾 如下图类似于死锁这种 方案2可达性分析 JVM首先会从现有代码中能直接访问到的引用出发尝试访问遍历所有能访问的对象只要对象能访问到都可以标记成可达。完成遍历之后可达之外的东西也就是不可达可就是垃圾咯 更多的是看能不能到达不能到达就给你置空 2.释放对象的内存 1.标记-清除直接释放 这种问题假如不去处理还是挺严重的内存碎片随着程序的运行越来越多越来越碎内存越来越难申请。 2.复制算法 复制算法通过冗余的内存空间把有效的对象复制到另一部分空间来避免内存碎片 把一个内存分成两份用一份丢一份把左侧区域中有效的对象复制到右侧接下来就可以使用右侧区域了用了一段时间之后也会有很多对象也是相同的道理把有效对象复制到左边把右侧区域统一释放 3.标记整理 顺序表删除元素搬运 实际有用的只有135 把没用的都迁移到后面然后后面的元素进行删除。 4.JVM的垃圾回收机制 于是设计JVM的大佬研究出了一个方法集百家之长 按照对象的年龄来制定不同的回收策略 GC是周期性进行扫描每个对象没经过一轮GC就称为涨了一岁。 新生代的扫描频次是比较高的老年代的扫描频率就降低了 但是上述情况中还有一个特殊的情况“如果这个对象的体积特别的大”会直接进入老年代大的对象不适合复制算法