目录
程序在执行之前先要把java代码转换成字节码文件(class文件),jvm首先需要把字节码通过一定的方式 类加载器(ClassLoader) 把文件加载到内存中 运行时数据区(Runtime Data Area) ,而字节码文件是jvm的一套指令集规范,并不能直接交个底层操作系统去执行,因此需要特定的命令解析器 执行引擎(Execution Engine) 将字节码翻译成底层系统指令再交由CPU去执行,而这个过程中需要调用其他语言的接口 本地库接口(Native Interface)来实现整个程序的功能。
注意:运行时数据区好比作是制作一道菜需要的食材、工具、调味料等,而执行引擎可以比作是一个厨师,厨师将准备好的东西制作成一道精品菜肴就好比是成功运行Java
引用程序。
含义:类加载器是一个用来加载类文件的类
类加载器作用:在运行时加载类,其会将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区运行时数据结构,然后在堆中生成一个代表这个类的java.lang.class对象作为方法区中类数据的访问入口
- //系统类加载器(system类加载器)
- ClassLoader a = ClassLoader.getSystemClassLoader();
- //扩展类加载器(extension类加载器)
- ClassLoader b = a.getParent();
- //根加载器(bootstrap类加载器)
- ClassLoader c = b.getParent();
注意:Bootstrap类加载器是由c来写的,java调用不到,其他的类加载器都是由java.lang.classloader来实现的
加载阶段
- 加载类的信息到jvm方法区
- 在堆区中实例化一个java.lang.class类指向方法区中对应的类
连接阶段
- 验证阶段:验证类是否合法
- 准备阶段:为类的静态变量分配内存,并设置初始值
- 解析阶段:把常量池中的引用(标识符)转化为内存地址
初始化阶段
- 执行类构造器
()方法的过程。类构造器 ()方法是由编译期自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并产生的(类构造器是构造类信息的,不是构造类对象的构造器) - 虚拟机会保证一个类的
()方法在多线程的环境中被正确加锁和同步 - 当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发父类初始化
- 初始化工作包括由上而下依次执行类中的静态赋值语句和静态代码块(可能在解析之后)
使用阶段
使用类时只有直接引用的一个类才会将该类初始化,间接引用不会造成该类的初始化
卸载阶段
在jvm垃圾回收时,若检测到类不会再被使用时卸载该类
作用:用来执行java生成的.class字节码,解析编译成各种cpu能执行的二进制指令
解释器:Java虚拟机启动时,会根据预定义的规范对字节码采用逐行解释的方式执行,将每条字节码文件中的内容编译为对应平台的机器指令执行。
即时编译器:虚拟机将字节码直接编译成和本地机器平台相关的机器语言。
- 中间代码生成器:生成中间代码
- 代码优化器:负责优化上面生成的中间代码
- 目标代码生成器:负责生成机器代码或本地代码
- 分析器:一个特殊组件,负责查找热点,即该方法是否被多次调用;
垃圾收集器:用来回收垃圾
含义:在java运行时jvm虚拟机拿到自己能支配的的内存之后将内存进行了割分,分为了5部分,分别为栈区、堆区、方法区、本地方法栈、程序计数器
垃圾回收机制:主要是对内存的释放,因为在创建对象时要申请一个空间。
内存泄漏:内存一直被占着却不能使用。
System.gc(); //提醒JVM的垃圾回收执行GC,但是不确定是否马上执行GC
每个对象都有一个引用计数属性,新增一个引用时,计数加一,引用释放时,计数减一,引用计数为0时可以回收,此方法简单,无法解决循环依赖问题。
从GC根节点开始向下搜索,搜索走过的路径称为引用链。当一个对象到GC根节点没有任何引用链相连时则证明此对象是不可用的不可达对象。
注意:由于引用计数算法不能解决循环依赖问题,JVM并没有使用引用计数算法作为GC中判断对象是否存活的算法,用的是可达性分析。
将可用的内存按照容量分为大小相等的两块,每次只使用其中的一块,这一块内存用完时就将还存活的对象复制到另一块上面去,然后把已经用过的内存空间一次清理掉(如此循环往复)。
标记阶段:从根节点开始标记所有的可达对象,未被标记的为垃圾对象。
清除阶段:清除所有未被标记的对象
注意:标记清除算法容易产生内存碎片(就是内存有,但是相对太小不能用)
标记阶段:从根节点开始标记所有的可达对象,未被标记的为垃圾对象。
整理阶段:将所有存活的对象压缩到内存的一端,之后清理边界外的所有空间。
java采用了分代垃圾收集,这种方法会跟java对象生命周期将堆内存划分为不同的区域,在垃圾收集过程中可能会将对象移到不同的区域。
新生代
- 伊甸园区
- 存活区
老生代
注意:
一般情况下新建的对象均会被分配到伊甸园区(一些大对象特殊处理)这些对象经过第一次gc后,如果仍然存活将会被迁移到存活区,如果存活区有数据的部分和伊甸园区都满了,那么就会发生一次MinorGC,将没有被清理的对象移到另一块存活区如此循环往复。存活区启用复制算法15次的对象如果仍然存活那么就会直接放入老生代,大对象直接进入老生代(大对象指的是需要大量连续内存空间的对象),这样做的目的是避免在伊甸园区和两个存活区之间发生大量的内存拷贝。老生代如果内存也满了那么就会发生一次FullGC
方法区的回收价值很低,主要回收废弃的常量和无用的类