1.JVM是啥a?
JVM是java虚拟机,可以在任何拥有jvm的平台运行java的字节码文件【.class文件】,JVM实现了java跨平台特性。
我们编写的Java源代码首先需要通过Java编译器生成字节码文件,然后由JVM负责解释执行这些字节码。
2.重点理解:JVM内存机制
JVM的内存组成 ?
(1)堆:一块内存,被所有线程共享。存放【生成的对象】
所以为什么会有堆内存占满的问题出现,和对象内存回收有很大关联
(2)栈:虚拟机栈和本地方法栈
虚拟机栈:线程私有,存放【基本类型变量+对象引用变量】
包装类型(Integer,Character)都是普通对象,放堆内存
创建完对象,这个对象名作为变量存在这里 栈中数据是共享的
本地方法栈:为虚拟机中使用的Native方法服务
虚拟机栈为虚拟机执行Java方法(字节码)服务
栈的深度如果超过虚拟机允许的深度,抛出StackOverflowError异常
扩展虚拟机栈时,扩展无法申请到足够的内存 抛出OutOfMemoryError
【这里OOM依旧和内存是否充足有关】
(3)方法区:存放.class字节码文件,包含所有虚拟机加载的类、常量、静态变量等,存的都是整个程序中唯一的元素(static变量、class)
(4)程序计数器:线程私有的,理解为:维护当前这个线程执行的字节码的行号
2. JVM内存模型
jdk1.8之后JVM内存模型将永久代替换--元空间,常量池依旧在方法区
垃圾回收机制是这样的:
(1) 新产生的对象放在Eden区里
(2) eden区满了,存活的对象复制到from区中
【如果存活对象from放不下,这些存活对象全部进入老年代,之后的eden区内存回收掉】
(3) 继续分配到eden,eden再次满了 eden+from 存活对象复制到to区
【to满则进入老年代,eden/from 内存都回收】
(4) 默认情况,一个对象复制15次,就进入老年代
(5) 老年代满了或放不下,进行一次full GC
垃圾回收
1.Minor GC
新生代回收:不影响老年代,需要速度快:复制算法
2.Full GC
老年代回收:整个堆的内存回收,标记-清除,标记-压缩
垃圾回收算法常见的几种:
(1) 复制算法:
从根集合节点扫描,标记所有存活对象,将这些存活对象复制到一块新的内存,然后把原来的内存回收
eden:from: to 一般是8:1:1,eden满了则把对象复制到from ,然后回收eden内存,eden/from 满了则复制到to,然后回收eden/from
(2) 标记-清理 算法:
先从根节点开始 标记所有对象,没标记的就是未被引用的对象,清除阶段,清除所有的未标记对象
【适合清除老年代,但容易产生内存碎片,扫描空间两次(标记/清除)】
(3) 标记-压缩 算法:
先从根节点做一次标记,然后把存活对象压缩到内存的一段,
清除阶段:清理边界外的所有空间,减少了碎片内存产生
(4) 分代收集算法:
不同代用不同的算法,新生代-复制算法;老年代-标记压缩