JVM里重要的3各模块是:类加载器,内存空间和垃圾收集器
类加载器负责在编译阶段把java文件加载成class文件
内存空间主要包含:方法区,java虚拟机栈,堆,本地方法栈
方法区:
作用:存储被虚拟机加载的类信息、常量、静态变量、以及即时编译器编译后等数据
java虚拟机栈:
作用:他是用于存放所有java方法执行时的的引用,
组成:由栈帧组成,一个栈帧代表一个方法的执行
生命周期:每个方法从调用到执行完成就对应一个栈帧在虚拟机中从入栈到出栈
堆:
作用:对象和数组的内存都在堆中存储
特点:是虚拟机中最大的一块内存,也是GC要回收的部分,堆内存还分为新生代和老生代,内存空间足够时就存储到新生代,不够了就存到老生代,老生代放不下不好意思,就OOM了
本地方法栈
作用:用于存储本地native方法执行时的引用
内存收集算法:
1.引用计数算法:增加一个引用就做加一操作,减少一个就做减一操作,但是这样有一个问题,如果有这么一个引用,A引用只想B,B引用有指向A,类似这样的无效引用,其实会导致收集不准确
2.可达性算法:从GCRoot顶部往下走,走不到的引用视为无效引用
引用类型:强引用、软引用、弱引用、虚引用,最常使用的强引用和弱引用
GC垃圾回收算法:java虚拟机无法再为新的对象分配内存空间了,低优先级的GC线程,被运行时就会执行GC
1.标记-清除法:对没有引用的对象做标记,然后清除被标记的对象,但是其他指针不动,这样会造成内存碎片化,浪费内存
2.复制算法:将内存分成1:1的两块,每次只使用一块,当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉
3.标记整理算法:对没有引用的对象做标记,让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存(双指针算法,一次遍历)也解决了内存碎片化的问题,但是时间复杂度高一点
顺带提一嘴:Android虚拟机使用的是DVM和ART
DVM使用JIT来将字节码转换成机器码,每次启动都会执行,所以效率低
ART采用AOT预编译技术,只执行一次,所以效率高