一、什么是JVM:
Java虚拟机(JVM)是Java技术的核心,它为Java程序提供了一个独立于硬件和操作系统的执行环境。JVM是一个高度优化的虚拟机,负责解释和执行Java源代码或字节码,将Java程序转化为底层平台可执行的指令。
二、核心点:
一、类加载器:
类加载器分为四种:
1、BootstrapClassLocader:
这个加载器并不是java提供的,而是由C++提供的,用来加载java本地类的,比如String,Date类等,这些类通常在jre/lib/rt.jar中,不是ClassLoader的子类。
2、ExtensionClassLocader:
这个是一个扩展类的加载器,负责加载java平台中扩展功能
的一些jar包(JAVA_HOME/jre/lib/ext、或-Djava.ext.dirs指定目录下的jar包)。由Java实现
,派生自ClassLoader类。
3、ApplicationClassLocader:
应用程序加载器,自定义的类,都是通过这个类加载器来加载的,由java实现,派生自ClassLoader类。
4、自定义加载器:
自己实现ClassLoader接口的类加载,
二、双亲委派机制:
(重点)双亲委派机制可以保护程序的安全性,避免重复类的加载
假设没有用户自定义加载器,我们创建一个Demo.java,在加载的时候,首先是应用程序加载器先拿到这个类,不会立即加载这个类,会将这个类向上委托给扩展类加载器,扩展类加载器也不会立即加载这个类,而是将这个继续向上委托,直到委托给启动类加载器,这个过程叫自底向上委托,然后启动类加载器开始尝试加载,如果能加载,则会立即加载,否则就给下面加载器加载,也就是扩展类加载器,扩展类加载器也尝试加载,如过加载,就会加载进去,否则就给启动加载器,启动类加载器就会加载这个类,如果连启动类加载器,也加载不了,那么就会报一个异常:ClassNotFoundException,这个过程叫自上向下尝试加载。
面试题:为什么这样设计,有什么好处:
可以避免代码的侵入,因为java有个安全机制,叫沙箱模式,假如一个恶意用户,创建一个String类,和java自带的String一样的权限类名,那么在加载这个String类的时候,通过双亲委派机制,用启动类开始加载,就会加载到java自带的String类,而不是恶意用户写的String类,其次可以避免重复类的加载,当一个类被加载过之后,那么类加载器就会记住这个类,下载使用这个类就是直接由相应的类加载器加载了
三、虚拟机栈:
虚拟机栈是线程私有的,一个方法就是一个栈,也被称为栈帧,常听说到的弹栈、压栈、栈溢出等,如果栈溢出,大概率是递归调用进入循环了,或者递归调用导致栈空间满了;栈帧存储的是:局部变量表、操作数栈、方法返回地址、动态连接、一些附加信息。
局部变量表:
存储的是一些局部变量,比如8中基本数据类型和引用数据类型。
操作数栈:
记录方法执行过程中根据字节码指令记录当前操作的数据,将它们入栈或出栈。用于保存计算过程的中间结果,同时作为计算过程中变量的临时存储空间
方法返回地址:
当前方法执行完之后,需要一个返回地址,方法返回地址存储当前方法调用完毕后下一条指令的地址
动态链接:
可以知道当前帧执行的是哪个方法。
指向运行时常量池中方法的引用
一些附加信息:
栈帧中还允许携带与Java虚拟机实现相关的一些附加信息。例如,对程序调试提供支持的信息。
四、本地方法栈:
记录被native关键字的方法
五、PC程序计数器:
线程私有的,记录每个线程当前执行指令,就是一个指针,指向方法区中的方法字节码
六、方法区:
在jdk1.6被称为永久代,在jdk8被称为元空间,存储了类型信息,方法信息,域信息,JIT缓存代码
七、堆区:
堆区主要有分代空间:
年轻代/新生代/新生区:
主要有三个区:
EdenArea(伊甸园区):创建出的对象都是存放在这里的
Survivor0Area(幸存者0区)和Survivor1Area(幸存者1区)
老年代/老年区:
存放一些经历过多次GC,还存活下的对象
元空间:
存放的是方法区那些数据,元空间逻辑上是在=堆中的,物理上是在本地缓存中
八、本地方法接口:
执行那些native方法,去调用本地方法库执行
九、执行引擎:
解释器:
编译代码之后,负责解释编译后的代码,逐行解释运行。
JIT即使编译器:
负责将热点代码缓存起来,下次就不需要再次解释该代码了,比如while循环
三、总结:
这是jvm中的一小部分,我还有很多没讲到,其中堆区有很多没详细讲,还有GC,希望这边文章能够帮助你简单快速的理解JVM,如果需要详细的讲解,请私信我。看到这里,就给我点个免费的赞和关注吧,谢谢。