比如在代码运行过程中 我们 new Student() 对象
1. 是否加载过该类的Class对象
加载过:分配内存,创建该类的对象
没加载过:使用双亲委派机制加载该类的字节码文件并且变为Class对象存放到 方法区中,校验该字节码文件是否正确,解析字节码文件并且静态方 法和静态参数的引用放到方法区,初始化参数(对象为null,bool为 false等),静态对象创建对象并且放到堆内存。
2. 分配内存
分析内存逃逸:比如执行的该方法中内存是只在这个方法中引用,运行完了该方法这个对象的生命周期就完成了那么就会给栈中分配内存(栈满了就会发生full gc)
堆中分配内存: 计算该对象大小,如果内存中是比较完整使用指针碰撞,将指针移动对象大小的位置分配内存,这样适用于标记-复制算法。如果是不连续的那么就只能使用一个列表标记那个区域是可以用的并且在该列表中找到适合Student对象大小的内存分配,适用于标记-清楚算法
分配过程中可能有线程安全问题:jvm使用cas自旋和每个线程都分配一个小的堆空间(类似于ThreedLocal)默认大小是Eden的1%
3. 初始化
将对象中的属性赋值
4. 分配内存时的垃圾回收
分配内存时如果Eden区满了就会对年轻代进行垃圾回收,这段时间会发生STW但是因为没有对老年代回收所以时间比较短,用户感知不太出来停顿,将收集到的Eden和没空的S区对象都放到另外一块空的S区,并且如果对象大于Eden的50%就会直接放到老年代,
在发生young gc时:比如最大分代年龄此时是 14,那么年龄为 1 + 2 + 3 + 5这是这几代的对象相加就已经超过s区的50%,那么就会将第六代到第14代对象放到老年代。如果Eden区中一批对象大于S区其中一块的50%就会直接放到老年代。在每次young gc时老年代都会计算如果当前年轻代大小是否大于老年代的可用空间,如果大于那么就会判断是否大于之前每次放到老年代的平均值(默认开启,可以使用参数设置),都成立的话就会发生full gc
5. 垃圾回收
jdk8默认:parallel
jdk9开始默认 G1
parallel是多线程收集的,
还有 parNew(年轻代)+ CMS(老年代)算法
G1推荐大内存情况下使用,可以指定最大停顿时间,提高用户体验减少单次gc停顿时间