JDK、JRE、JVM简介
JVM
JVM运行时数据区
- 不论有多少线程,方法区和Heap堆只有一份
- 程序计数器 虚拟机栈 本地方法栈为每个线程独有一份
线程私有部分
虚拟机栈: 存储当前线程运行方法所需的数据,指令和返回地址
类中每一个方法对应一个栈帧,栈帧还可以划分为局部变量表 操作数栈 动态链接 返回地址
// 方法进出栈帧复合FILO原则,即先进后出
// x y i变量存储在局部变量表里,局部数据表是32位的 如果是存储double需要占用两个
// 局部变量表第一位存储的都是this,还有对象 的引用
public class Demo {
public static void main(String[] args) {
Demo demo = new Demo();
demo.calc(1, 4);
}
public int calc(int x, int y) {
int i = 2*x + y;
return i;
}
}
程序计数器: 当前线程正在执行的字节码指令的地址
本地方法栈: 存储当前线程运行Native方法所需的数据,指令和返回地址
线程公共部分
方法区: 存放编译后的.class字节码文件,常量和静态变量(永久代,元空间)
Heap堆: 对象或者数组的实例
堆指的就是新生代和老年代,新创建的对象在eden0,满了还有引用的对象放入s0,当年龄到15的时候放入老年代,新生代和老年代的比例为1:2
垃圾回收
通过配置堆内存大小可以模拟内存溢出的场景,并且打印GC详情
首先堆空间满了,会回收新生代
Full Gc的话会回收所有,堆+元空间
Gc回收不了的时候报错OutOfMemoryError
复制算法
用于新生代,将一半的空间预留,只复制不可回收的对象到预留区域,然后开启预留区域,并格式化使用区域
标记-清除算法
用于老年代,两个操作 先标记哪些可回收,再执行清楚操作
标记-整理算法
用于老年代,标记 清除 整理,内存整理时实实在在的内存移动,消耗性能
Tips:注意内存溢出和内存泄漏的区别