前言:一只努力习七七八八的code girl大喵,从这篇文章开始记录java的学习的过程。欢迎大家一起打卡监督。好啦,话不多说,直接上总结硬货!!!
整个JVM分为以下几个部分
- 堆区
- 栈区
- 方法计数器
- 方法区
- 堆外内存
如下图帮助记忆
堆区
新生代与老年代 内存默认比例1:4,可通过-XX:NewRatio调整
新生代
1. 分为一个eden区,两个survivor区
2. 新生代对象朝生夕死
3. 垃圾回收算法为复制算法,即每次只用一个eden区和survivor区。当进行垃圾回收时,把当前使用的eden区和survivor区的存活对象复制到未使用的survivor区,然后把当前的eden区和survivor区清空,接下来再使用被清空的eden区和survivor区
4. 垃圾回收器有三种:serial(单线程),parNew(多线程),parallel scavenge(多线程)
5. Eden区和survivor区默认内存比例为8:1,这个比例可通过-XX:survivorRadio参数调整
老年代:
1. 垃圾回收算法有两种:标记清除和标记整理
2. 垃圾回收器有三种:serial old(单线程),parallel old(多线程),cms(多线程,注意可以与用户线程并发执行采用标记清除垃圾回收会产生空间碎片)
3. 此年代对象存活时间久
4. 进入此年代的对象有三种方式:
1) 新生代对象经过15次垃圾回收依然存活晋升到老年代
2) 大对象直接进入老年代,超过参数-XX:PretenureSizeThreshold({-XX:参数名=参数 值}/或者格式为{-XX:+/- 参数名 [+代表使用此功能 -代表关闭此功能]})则为大对象
3) 动态年龄判断:如果当前survivor区处于同一年龄的对象所占用的空间超过当前survivor区大小的一半,超过此年龄的对象进入老年区,不必等到15岁
栈区
虚拟机方法栈
一个虚拟机方法栈对应一个线程,每个方法都是线程中的一个线帧,随着方法的执行不断出栈,入栈。
本地方法栈
方法计数器
记录方法的调用信息,以及返回地址信息
方法区
1. 存储类的信息(class文件在内存中的存储格式)
2. 常量池(不包括字符串常量池(JDK1.7及之后放在堆区))
堆外内存
本机直接内存,间接受java虚拟机的垃圾回收管理,申请/释放消耗大,适用于较长时间存活对象,且可以避免不必要的内存复制