dwcc网站前台脚本怎么做音频,如何查网站处罚过,给赌场做网站,怎样把网站推广出去1. JVM 内存区域划分
一个 Java 写的程序#xff0c;跑起来就得到了一个 Java 进程#xff08;资源分配的基本单位#xff09; JVM 上面运行的字节码指令
1) 程序计数器#xff08;比较小的空间#xff09;#xff0c;保存了下一条要执行的指令的地址
这个不是 CPU 的…1. JVM 内存区域划分
一个 Java 写的程序跑起来就得到了一个 Java 进程资源分配的基本单位 JVM 上面运行的字节码指令
1) 程序计数器比较小的空间保存了下一条要执行的指令的地址
这个不是 CPU 的寄存器而是内存空间这里的 “下一条要执行的指令” 是 Java 的字节码不是 cpu 的 二进制 的机器语言
2) 堆
JVM 上最大的空间new 出来的对象都在 堆 上
3) 栈Stack Overflow
函数中的局部变量函数的形参函数之间的调用关系
Java 虚拟机栈JVM 之上运行的 Java 代码的方法调试关系
本地方法栈JVM 里C 代码的函数调用关系
4) 元数据区方法区
Java 程序中的指令指令都是包含在类的方法中
保存了代码中涉及到的 类的相关信息
类的 static 属性
分析
在一个 Java 进程中元数据区和堆都是只有一份的同一个进程中的所有线程都是共用同一份数据的共用同一份内存空间
程序计数器和栈则可能有多份当一个 Java 进程中有多个线程的时候每个线程都有自己的程序计数器和栈
线程就代表一个 “执行流”每个线程就需要保存自己的 “程序计数器”每个线程也需要记录自己的调用关系 例以下代码中创建的变量处于哪个内存区域
class test {private int a;private Test b new Test();private static int c;private static Test d new Test();public static void main(String[] args) {int e 10;Test f new Test();}
} tip一个变量处于哪个内存区域和变量是不是 “内置类型” 无关而是和变量的形态有关
1) 局部变量 - 栈
2) 成员变量 - 堆
3) 静态成员变量 - 元数据区方法区
2. JVM 类加载的过程
2.1 概述 加载一个 .class 文件就会创建一个对应的类对象
基于该类对象就可以创建该类的实例类对象其实就是“对象”的说明书/蓝本
类对象例就包含了 .class 文件中的各种信息如
类的名字
类里有哪些属性每个属性名字每个属性的类型public/private
类里有哪些方法每个方法的名字、参数public/private
继承的父类是啥
实现的接口有哪些
...
2.2 类加载的具体步骤重要
五个环节 / 三个环节将中间3个环节合为1个
1. 加载
把 .class 文件找到代码中先找到类的名字再找到对应的 .class 文件涉及到一系列目录查找的过程打开并读取文件内容
2. 验证
验证读到的 .class 文件中的数据是否正确合法Java 标准文档中明确定义了 .class 文件的格式
Java 标准文档 3. 准备分配内存空间
最终需要得到类对象 需要内存
把刚才读取到的内容确定出类对象需要的内存空间申请这样的内存空间并把内存空间中所有的内容都初始化为 0Java 操作C/C 申请到的内存不会进行置 0 操作
置 0 操作是为了避免上次残留的数据被当前程序误使用
4. 解析主要针对类中的字符串常量进行处理
解析阶段是 Java 虚拟机将常量池内的 “符号引用(字符串常量已经在 .class 文件中)” 替换为 “直接引用(里面保存了变量的地址)” 的过程也就是初始化常量的过程 5. 初始化针对类对象做最终的初始化操作
执行静态成员的赋值语句 执行类中的静态代码块
针对 父类 也要加载
3. 面试题双亲委派模型
3.1 概念
是类加载五个步骤中第一个步骤里面的一个环节给定 类全限定名找到 对应的 class 文件位置
类加载器 JVM 中已经内置了一些类加载器JVM 中的功能模块完成上述的 “类加载” 过程 JVM 默认有三个类加载器 爷爷BoorsrtapClassLoader 负责加载标准库中的类标准库的类也是有一个专门存放位置的 爸爸ExtensionClassLoader 负责加载扩展类JVM 厂商对 Java 功能做出的一些扩展 儿子ApplicationClassLoader 负责加载第三方库中的类 / 自己写的代码中的类 tip上面三者不是 Java 中父类子类的继承关系而是在类加载器中有一个 parent 这样的引用指向父亲
3.2 双亲委派模型的工作流程
输入类的全限定名字符串类似于 java.lang.String
输出找到对应的 .class 文件 这样设定的最核心目的防止用户自己写的类把标准库的类给覆盖掉
保证标准库的类被加载的优先级最高扩展库其次最后是第三方库
4. 垃圾回收机制GC
4.1 引子
C/C 中malloc/new 一个对象后都需要手动释放内存 free/delete如果不释放就可能产生内存泄漏头号职业杀手后果可能很严重排查非常不好搞
C 中针对内存泄漏直接摆烂了
C 中针对内存泄漏给出了一个方案“智能指针”然而它并不太智能
在 Java 中对内存泄漏给出更系统更完整的解决方案在 Java 之前也有一些语言使用了这样的方案
垃圾回收有了它程序员可以放心大胆的 newJVM 会自动识别哪些 new 完的对象再也不用了就会把这样的对象自动释放掉
其他语言一看都觉得香纷纷投入到 垃圾回收 的怀抱如Go、Python、PHP、JS...主流语言中大部分都是内置了 GC
但是GC 也是有代价的C 不是搞不了 GC而是开发 C 的大佬们评估了之后不愿承担这些代价 GC 需要 JVM 中引入额外的逻辑 1) 消耗不少 CPU 开销进行垃圾的扫描和释放 2) 进行 GC 的时候可能会触发 STWStop The World问题导致程序卡顿对于性能要求高的场景就会影响很大 因此GC 就会 提高开发效率影响运行效率
4.2 Java 的垃圾回收
JVM 中有好几个内存区域GC 主要负责的是 堆
其中 程序计数器和栈 是跟随线程的元数据区一个程序里面要加载的类都是有上限的不会出现无限增长的情况
垃圾回收也就是回收内存是以对象为维度进行回收的回收对象 4.3 GC 具体怎样回收
1) 先找出谁是垃圾
需要针对每个对象分别判定是否为垃圾
在 Java 中使用一个对象一般都是通过 “引用” 来使用的如果一个对象没有引用指向了就可以认为这个对象是垃圾了
方案一引用计数 给每个对象分配一个计数器衡量有多少个引用指向 每增加一个引用计数器 1 每减少一个引用计数器 - 1 当计数器减为 0此时对象就是垃圾了 这样做是可以回收垃圾但是假设 Test 类就只有一个 int 成员4字节此时为了引入引用计数少说得搞个 short2字节内存多占用了 50%
上述引用计数方案在 Java 中JVM没有采纳因为其存在两个问题
1) 消耗额外的空间
2) 引用计数可能导致 “循环引用”使得上述的判定出错和死锁类似如下示例 以上的循环引用也是有解的但是需要引入更多机制环路检测代价就更大了 方案二可达性分析用时间换空间
JVM 中专门搞了一些线程周期性的扫描代码中的所有对象判定某个对象是否是 “可达”可以被访问到对应的不可达的对象就是垃圾了 如上图JVM 中进行可达性分析的线程就是在做这样的事从 root 出发尽可能的通过 root 访问到更多的对象相当于遍历的过程严格来说不是 “树的遍历”而是 “图的遍历” 可达性分析的起点称为 GC root一个程序中 GC root 不是只有一个而是有很多个例如 1) 栈上的局部变量引用类型 2) 方法区中静态的成员引用类型 3) 常量池引用指向的对象 把所有的 GC root 都遍历一遍针对每一个都尽可能往下延申... 可达性分析是很消耗时间的尤其是当程序中对象特别多的情况下 2) 释放垃圾的内存空间
a) 标记-清除直接针对内存中的对应对象进行释放 当标记到垃圾位置并对其清除时会引入 “内存碎片问题”哪些对象要释放是随机的很可能要释放的位置对于整个内存来说不是连续的虽然将上述内存释放掉了但是整体这些空闲内存并没有连在一起后续申请内存的时候就可能申请不了申请的内存一定是连续的
例如上述回收完垃圾后空闲内存一共 3M现要申请 2M 的空间时就会失败不考虑未分配空间
因此尽量避免内存碎片是释放内存的关键问题 b) 复制算法 将内存一分为二同一时刻只使用其中的一半
当要回收垃圾时将不是垃圾的对象拷贝到另一侧确保这些被拷贝的对象是连续的
然后将要回收一侧的空间全部释放掉
虽然能解决 “内存碎片化” 的问题但是其缺点也很明显
1) 内存空间利用率低
2) 如果存活下来的对象比较多复制成本也比较大 c) 标记-整理
非常类似于顺序表中删除中间的元素 缺点这样搬运的开销依旧不小 d) 分代回收
JVM 中真正的解决方案是把上面几个方案综合一下取长补短
JVM 根据对象的年龄把对象区分成新生代年轻的、老年代年老的
tip可达性分析是周期性的每经过一轮扫描对象仍然存活不是垃圾年龄 1 根据经验规律
1. 绝大部分的新对象活不过第一轮 GC留存下来的对象拷贝到幸存区
2. 幸存区是两个相等的空间也是按照复制算法反复进行多次
新生代中真正要拷贝的对象不多经验规律内存利用率低
3. 如果一个对象在幸存区已经反复拷贝多次不是垃圾年龄不断增长达到一定程度之后对象就要拷贝到老年代了
4. 根据经验规律老年代中的对象生命周期都比较长老年代的对象肯定还会进行可达性分析但是进行 GC 的频率就会降低
另外老年代也是通过标记整理的需要整理的次数不多
4.4 JVM 中的垃圾回收器
分代回收是 JVM 中 GC 的基本思想方法具体落实到 JVM 的实现层面上JVM 还提供了多种 “垃圾回收器” 对上述的分代回收做进一步的扩充和具体实现 1. CMS GC
CMS 设计理念把整个 GC 过程拆分成多个阶段能和业务线程并发运行的就尽量并发尽可能减少 STW 的时间 2. G1 GC G1 是把内存分成很多块不同的颜色字母表示这一小块是新生代伊甸区/幸存区、老年代
进行 GC 的时候不要求一个周期就把所有的内存都回收一遍而是一轮 GC 只回收其中的一部分就好限制一轮 GC 花的时间/工作量使 STW 的时间在可控范围之内
这些方案的主要目的降低 STW 的影响ZGC目前比较新的垃圾回收器目前可以把 Java STW 的时间降低到 1ms 以内