一、JVM管理内存,主要是两大类,线程共享和线程独享
1.线程共享:堆、方法区
2.线程独享:虚拟机栈,本地方法栈、程序计数器
虚拟机栈包含栈帧,栈帧包含局部变量表、操作数栈、动态链接、方法出口
方法区(永久代):类信息、常量、 静态变量、即时编译器编译后的代码等数据,运行时常量池
新生代分eden区和Survivor区,Survivor区又划分了to和from区
Survivor区是存放minorgc的幸存对象
eden区是存放新生对象,如果对象不够放,就直接放到老年代
老年代触发majorgc,采用标记清除算法
1.8中,类的元数据放入native memory中,字符串池和类的静态变量放入java堆中
二、怎么判断对象死亡
1.引用计数法
2.可达性分析法(gc root)
三、垃圾收集算法
- 标记复制算法
- 标记清除算法
- 标记整理算法
- 分代收集算法
四、垃圾收集器
- serial,单线程,复制算法,用于新生代
- serial old,单纯种,标记整理算法,用于老年代
- parNew,多线程,复制算法,默认跟CPU数目相同的线程数,可调整,用于新生代
- parallel Scavenge,多线程,复制算法,自适应调节策略,关注吞吐量,用于新生代
- parallel old,多线程,标记整理算法,用于老年代,如果对吞吐量有要求,可以用parallel Scavenge+parallel old
- cms,多线程,标记清除算法,分四个阶段:初始标记,并发标记,重新标记,标记清除,初始标记和重新标记都需要stw,为了解决漏标对象,采用增量更新
- g1,优先级列表,也分为四个阶段:初始标记,并发标记,最终标记,筛选回收,除了并发标记,其它都stw,最终标记和筛选回收是多线程,多了一块把Humongous Region区,专门用来存储大对象,存放只要大小超过了一个 Region容量一半的对象即可判定为大对象,为了解决漏标对象,采用原始快照(STAB),分了YoungGC,MixedGC,FullGC
- zgc,不分代,分四个阶段:并发标记、并发预备重分配、并发重分配、并发重映射,维护了转发表
五、强引用、软引用、弱引用和虚引用
强引用:将一个对象赋给一个引用变量,那这个对象就成为强引用,不可被回收
软引用:SoftReference类来实现,内存足够时,不会被回收
弱引用:WeakReference类来实现,垃圾回收一运行,即可被回收
虚引用:PhantomReference类来实现
六、java对象分配规则
1.进行逃逸分析
2.分配到栈上(如果够放)
首先会判断eden区是否放得下,分配担保机制,如果放不下,就直接old区,如果不是则以下逻辑
3.Eden区会为每个线程分配一个TLAB区域,这个属于线程私有
4.Eden区的公共区域
5.old区
七、类的生命周期
加载>>验证>>准备>>解析>>初始化>>使用>>卸载
1.加载.class文件,一个类的全限定名来获取其定义的二进制字节流
2.验证,包括文件格式验证,元数据验证,字节码验证,符号引用验证
3.准备,静态变量分配内存,并将其初始化为默认值,内存分配的仅包括类变量(static),而不包括实例变量,数据类型默认的零值
4.解析,类中的符号引用转换为直接引用,解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符7类符号引用进行
5.初始化
6.使用
7.卸载
ClassLoader.loadClass()只加载到jvm中,Class.forName(name, initialize, loader),initialize为true时加载static块