首先先搞清楚什么是JVM?
我个人觉得,JVM是一个虚拟的计算机,简单来说,他就是把字节码解释成具体平台上的机器指令的一个软件。
JVM的作用?
JVM就是为了解决跨平台即平台无关性来设计的一款软件。他可以把java编译产生的字节码文件解释成本平台上的机器指令。从而实现java的一次编译多次运行。
java编译及运行图解
编译具体
运行
JVM的结构?
程序计数器(Program Counter),Java堆(Heap),Java虚拟机栈(Stack),本地方法栈(Native Stack),方法区(Method Area)
JVM内存管理
JVM------GC的算法
1.引用计数法:
我的理解:就是给对象添加一个计数器,每当这个对象被引用一次,其计数器加一,当引用失效,计数器又减一。所以当计数器值为0时此时说明该对象没有引用了,此时就可以把此对象回收。
优点: 引用计数收集器可以很快的执行,交织在程序运行中。对程序需要不被长时间打断的实时环境比较有利。
缺点:无法检测出循环引用。如父对象有一个对子对象的引用,子对象反过来引用父对象。这样,他们的引用计数永远不可能为0.
2.复制算法:
此算法,把新生区分为三个区域(伊甸园去,幸存0区,幸存1区),会在0区和1区中设置一个空闲区,即会有一个为from,另一个为to(空闲),当伊甸园区有对象存活下来了,此时该对象会进入to,然后,把from中的对象复制到to并清空。最后to和from名称互换。
优点:也不会出现内存碎片
缺点:有效内存只有一半,只有一半存储数据,太浪费空间
3.标记清除:
分为两步:
(1)遍历所有的GC Roots,然后将所有GC Roots可达的对象(我的理解就是还有引用的对象)标记为存活的对象。
(2)再次遍历堆中的所有对象,并把没有标记的对象清除。
注意:jvm并不是真正的把垃圾对象进行了遍历,把内部的数据都删除了,不是这样的,而是把垃圾对象的首地址和尾地址进行了保存,等到再次分配内存时,直接去地址列表中分配,所以清除的效率高。
优点:清除速度快,效率高。
缺点:会产生大量的内存碎片(就是很多不连续的内存空间),如果放入一个大的数组的时候,没有连续的内存放置大的数组,就会出现内存溢出,但是所有的内存碎片加起来可以放置一个大的对象,所有说内存使用率低,造成内存不连续。
4.标记整理(压缩)算法:
及改良了标记清除算法的产生大量内存碎片的缺点。增加了一步。
即在清除之前,先把存活的对象移动到内存的一端,再清理边界以外的垃圾对象。
优点:不会出现内存碎片,提高了内存的利用率
缺点:清除速度慢,因为在整理期间会有对象的拷贝和移动,并且引用内存的对象的地址要进行改变。
其实还有一个改良版本,即先清除,待清除数量带到一定数量,再进行存活对象的位置。
总结:
内存效率:复制算法>标记整理>标记清除
内存整齐度:复制算法=标记整理>标记清除
内存利用率:复制算法=标记整理>标记清除
5.分代回收算法:
(1)新生代使用复制算法
(2)老年代标记清除或者整理算法
对象什么时候进入老年?
1、对象的分代年龄到了15岁(默认情况下,可以自己设置)。
2、大对象直接进入老年代,就是大对象在新生代放不下,进行minor GC之后还是不够的情况下,会直接放入老年代。