1.私有:
Java栈(自己写的方法)
栈中保存的主要内容是栈帧,每个方法在执行时都会创建一个栈帧用于存储局部变量表(方法入参,局部变量),操作数栈(保存计算过程中的中间结果和临时存储空间),帧数据区(常量池指针,异常处理,正常方法的返回)等
本地方法栈(原生native的方法)
pc计数器:对于非native方法是当前线程所执行的行号的字节码的行号指示器(每个方法都有自己的)对于native方法是undefined。
唯一一个在虚拟机中没有outofmemoryError情况的区域
公有:
Java堆(存对象):Java堆可以分为新生代(eden区s0区s1区)老年代
对象首先分配在eden区,在一次新生代GC回收后,如果对象还存活,则会进入s0或s1,没经历一次新生代GC,年龄+1,年龄累计到一定数,会存到老年代
方法区(放一些类信息,类运行时的常量池):jvm的规范,所有虚拟机必须遵守的,方法区的大小决定了系统可以放多少个类,jdk8之前叫永久代,之后叫元空间
永久代:内存的永久保存的区域,主要存放class和元数据的信息,class在被加载的时候放入永久代,g c不会在主程序进行期间对永久区域进行清理,导致永久代会根据加载class的增多而胀满,抛出omm异常
元空间:与永久代的区别是使用堆外内存,不在虚拟机中。不指定大小默认情况下虚拟机会耗尽所有可用内存。
为什么用永久代替换成元空间:字符串常量池存在于永久代,大量使用字符串会导致oom;永久代大小难以确定,太小容易溢出,太大java虚拟机内存紧张。
2.类加载的过程
加载(读取一个文件需要先加载到内存里)
验证(验证类的一些东西是不是正确)
准备(
解析(符号引用变为直接引用)
初始化(赋值)
3.垃圾回收算法
对象的三种状态
可触及:从根节点开始,可以到达某个对象
可复活:对象的引用被释放,但是在finalize()方法中可能会复活
不可触及:错过finalize()方法中的复活机会
引用的四种类型:
强引用软引用(空间不足的时候会回收)弱应用(无论空间足不足都会回收)虚引用(与没有引用一样)
垃圾回收算法:
引用计数法:(jvm没有采用)
任何对象引用了a,a的引用计数器+1,引用失效-1。无法处理循环引用;性能消耗
标记清楚法:(老年代)
清楚之后空间碎片的问题
复制算法:(新生代)
分为AB两个内存,A gc时,将存活对象存入B。
缺点:只能使用一半内存
新生代使用的复制算法eden:s0:s1 8:1:1 新生代老年代1:2
eden+s0->s1
eden+s1->s0
对象是大对象或老对象或s0/s1放不下会进入老年代
标记压缩算法:(老年代)
先标记存活的对象,然后将所有存活的对象压缩到内存的一端,然后清除所有存活对象之外的空间。
分代算法:
新生代:回收频率高,耗时短;老年代:回收频率低,耗时长
分区算法:
将堆空间划分为不同的小区间,每个小区间独立分配使用,回收。
垃圾回收器:
主要记G1,java11用的。
G1优先回收垃圾比例最高的区域。G1将堆划分为多个区域,每次收集部分区域来减GC产生停顿的时间
G1收集过程:
新生代GC-》并发标记周期-〉混合回收
整体来看采用标记整理法,局部来看采用复制算法