JVM学习9·对象在内存的分配
image.png几乎所有的对象都在堆分配
1虚拟机的优化技术
1.1逃逸分析
逃逸分析的原理:分析对象动态作用域,当一个对象在方法中定义后,它可能被外部方法所引用。 比如:调用参数传递到其他方法中,这种称之为方法逃逸。甚至还有可能被外部线程访问到,例如:赋值给其他线程中访问的变量,这个称之为线程逃逸。 从不逃逸到方法逃逸到线程逃逸,称之为对象由低到高的不同逃逸程度。
如果确定一个对象不会逃逸出线程之外,那么让对象在栈上分配内存可以提高 JVM 的效率。
然后我们通过设置jvm参数来开启和关闭逃逸分析,发现运行效率差距很大,那为什么有这个影响?
因为如果是逃逸分析出来的对象可以在栈上分配的话,那么该对象的生命周期就跟随线程了,就不需要垃圾回收,如果是频繁的调用此方法则可以得到很大的性能提高。
采用了逃逸分析后,满足逃逸的对象在栈上分配
2.新生代的gc
更加详细的会在下一篇学习讲解
新生代的gc 较为复杂,采用的是复制算法,在复制的过程中对象的年龄+1,超过年龄阈值(默认15),就会进入到老年代。
2.1 为什么新生代内存需要有两个Survivor区
有一片帖子写的较为详细,供参考https://blog.csdn.net/antony9118/article/details/51425581
2.2复制算法的思想
将原有的内存空间划分成两块,每次只使用其中一块,在垃圾回收的时候,将正在使用的内存中的存活对象复制到另一块内存区域中,然后清除正使用过的内存区域,交换两个区域的角色,完成垃圾回收。
2.3为什么要在新生代中使用复制算法?
因为新生代gc比较频繁、对象存活率低,用复制算法在回收时的效率会更高,也不会产生内存碎片。但复制算法的代价就是要将内存折半,为了不浪费过多的内存,就划分了两块相同大小的内存区域survivor from和survivor to。在每次gc后就会把存活对象给复制到另一个survivor上,然后清空Eden和刚使用过的survivor。
3.空间分配担保:
如上图悲观策略就是 新生代gc之后,老年代gc
空间分配担保就是每次新生代gc完之后,判断下老年代是否放的下新生代gc过来的垃圾,如果放得下那老年代就不gc,放不下老年代再gc;
这样对比下来的话悲观策略每次老年代都要跟着新生代的gc而gc这样效率会较低,性能也有所消耗;而担保策略则会效率更高点。