一、什么是JVM?
JVM的全称是Java virtual machine,它是属于JRE(Java运行环境)的一部分。我们平时运行一个java应用程序,就是由JVM来负责管理的,每一个java应用程序都会有属于自己的JVM实例。
二、JVM的组成。
- ClassLoader。
- JVM memory。
- Execute Engineer。
二、JVM的作用。
- 加载class文件,将class加载到JVM中。【ClassLoader】
- 内存管理,分配内存空间,内存空间分为堆区、栈区、方法区、本地方法栈、程序计数器。【JVM memory】
- 执行引擎,由解释器、JIT编译器、GC垃圾回收器组成,主要用于解释class文件的字节码,回收无用(无引用)对象。
三、延伸知识点。
- ClassLoader的加载机制,双亲委托机制,由下加载,但先往上层层转发代理,由最上层开始查找class,找到就直接return掉。这样的好处是,会优先加载核心的java,我们就算我们创建了一个与jdk库里的一样的java类,也不会被加载到。
- 内存管理,主要是得知道,JVM的内存划分为堆区、栈区、方法区、本地方法栈、程序计数几大块,以及他们分别存储的是什么:
- 方法区【线程共享】:存储的是类的相关信息,包括类名,直接父类信息(如果有),变量、静态变量。
- 堆区【线程共享】:我们在java程序里所new出来的对象,就存储在堆区。
- 栈区【不共享】:用来存储局部变量,以及方法的调用次序。比如,A方法调了B方法,B方法调了C方法,则在栈里表现为【栈底】->A->B->C->【栈顶】。每个线程的栈的空间是有限的,如果栈空间的大小是固定值,当栈的大小无法满足分配时,则会抛出StackOverflowError。如果栈空间是动态增长的,则会一直分配到内存溢出,抛出OutOfMemoryError .
- 本地方法栈【不共享】:与栈区原理相同,区别是本地方法栈,用于存储Native层的信息。
- 程序引用计数器【不共享】:用来存储指向下一条指令的地址,在多线程环境中,在回到当前线程时,通过该计数器来记住之前执行的位置,以确保指令的执行次序是正确的。
3. GC垃圾回收器。
- 引用计数算法: 对被引用的对象计数加1,取消引用时减1,在回收时,对引用计数为0的对象进行回收。优点:简单易用。缺点:无法解决两个对象互相引用的场景,会导致内存泄露。
- 可达性分析算法: 将对象划分为几大类,每一类,都建有一个Root,从Root开始对被引用的对象进行关联。垃圾回收时,从Root开始遍历,对被访问到对象进行标记。标记完成后,回收那些没有被标记的对象。对于互相引用的场景,他们没有与Root有任何关联,所以就会被回收到,可以解决引用计数算法的内存泄露问题。现在,大部分的主流JVM都采用这种回收算法。