第三部分 深入理解JVM
Java代码的执行过程
Java源码编译机制
javac 将java源码转换成java class字节码
java 运行java class字节码
Java编译后产生的是字节码,在运行的时候将字节码转换成机器码。
Java类加载机制
类加载的任务就是.class文件加载到到JVM转换成 java.lang,.class类
类加载过程:装载、链接和初始化。
a.装载:找到.class二进制字节码并加载到JVM,JVM通过类的全限定名以及类加载器完成类加载;
b.链接:对二进制字节码的格式进行校验,初始装载类的静态变量以及解析类中的接口、类。
c.初始化:执行类中的静态初始化代码、构造模块以及静态属性的初始化。
Java类执行机制
字节码解释执行:将源码编译成JVM字节码的形式,JVM对其进行执行
编译执行:将.class转换成机器码后,进行执行
反射执行:通过反射机制获取类的字节码后,进行执行
注:Java编译后产生的是字节码,在运行的时候将字节码转换成机器码。
内存管理
Java内存区域(运行时数据区)
共享的:
方法区:类的共有属性 (包括常量缓存区、运行时常量池)。
JVM堆:对象、数组
隔离的:(“双栈”是隔离的)
本地方法栈:Natitve 方法
虚拟机栈(JVM方法栈):局部变量区和操作数栈
存放基本类型的数据和对象的引用
注:每一个线程都会生成PC寄存器(存放指令偏移量)和虚拟机栈。
垃圾回收机制
垃圾回收的算法:
a.标记-清除算法:效率偏低
b.复制算法:效率高,但是占用2倍内存 (预留一块内存 将还存活的对象放到该内存)
c.标记-整理算法:效率偏低(是对标记-清除算法的改进,让存活的对象向一段移动)
d.分代收集算法:把Java堆分为新生代和老年代,根据年代将特征选择上述算法。
老年代通常使用:a、c
新年代通常使用:b
GC分为2个部分:
Minor GC:收集新年代的区域
Full GC:收集 新年代和老年代的区域
注:
a.触发 Full GC的条件:持久代满了、老年代满了 、System.gc()
b.新年代满了,会放至到空闲的Survivor区,只有所有的Survivor区满了才会放到老年代。
Java垃圾回收器:
a.串行垃圾回收器:单线程 “牵一发动全身”
b.并行垃圾回收器:多线程
c.并发标记扫描垃圾回收器 CMS:利用多线程对需要回收的对象进行标记并回收。
d.G1垃圾回收器:对比较大的进行回收,可以先压缩再回收。
既然有 GC 机制,为什么还会有内存泄露的情况:
存在无用但可达的对象,比如Hibernate中的Session,如果不及时flush()或者close(),可能引发内存泄露。
System.gc()和Runtime.gc()会提示JVM要进行垃圾回收。但是,立即回收还是延迟回收是取决于JVM的。