JVM虚拟机:类加载子系统,执行引擎,垃圾回收子系统,运行时
一,类加载子系统
当new或者调用静态变量的时候虚拟机就会去校验是否加载过使用的类,加载一个类的过程为
加载类的要使用的类加载器ClassLoader,它使用的是双亲委派模型(如下图)
为什么使用双亲委派模型?
防止类的重复加载,类的唯一性确定是靠的是同一个类加载器加载和同一个class文件
二 执行引擎
执行加载完成的class字节码,使他们变成机器码然后运行,有以下两种方式
1,解释器
一条一条解释执行,执行的慢
2,JIT(Just In Time) 即使编译器
按照解释器的方式去执行,对于热点class,将class编译成机器码,加快执行速度,缺点是编译时间比较长
三 垃圾回收子系统
1,确定对象是否还被在使用两种方式,引用计数(缺点循环引用),引用链(从root处开始计算引用,没有连接则没有被引用)
2,清除对象的算法
停止-复制
将内存分为两片区域,当一片使用满了则停止然后把可以使用的对象复制到另一片(内存利用率不高)
标记-清除
将没有使用的对象直接清除(清除后内存不连续,不利于大对象的分配)
标记-整理
将没有使用的对象清除,整理这样清空后的内存是连续的
3,虚拟机使用的清除算法
整个堆分为了新生代和老年代(占比1:2)
所有新创建的对象都创建在新生代新生代分为三个区域Eden s0 s1(占比8:1:1)
新生代使用的清除算法为 停止-复制 比如Eden s0存储满了那么停止,将对象存储到s1中,然后等待Eden和s1存储满了在进程回收操作,如果对象经过好几个新生代的gc达到了一定数值那么他将进入老年代,如果分配大对象也有可能直接分配到老年代
为什么要这么分?
因为新生代对象创建,消亡是很正常的状态大部分对象都不会存活太久
老年代使用算法为标记-整理
四 运行时
1,方法区(存储常量 class static string 多线程内存共享)
2,堆(存储对象 多线程内存共享)
3,栈(方法,和局部变量 内部有栈针用于存储方法和局部变量 多线程内存不共享)
4,本地方法栈(本地方法存储 多线程内存不共享)
5,程序计数器(用于存储程序执行位置 多线程内存不共享)