JVM官方介绍:
1)JVM是JAVA平台基石,负责屏幕操作系统跟硬件,保护我们的程序免受恶意攻击。
2)JVM是虚拟的计算机,独立的指令集及不同运行内存区域。
3)JVM对JAVA的语法不感冒,JVM只在乎Class File 字节码文件。
4)JVM能够运行有效的Class file的文件,JVM是一个多语言平台
java文件到运行在JVM过程如图下:
java到Class过程:
javac解析过程:词法分析器->语法分析器->语法树/抽象语法树->语义分析器->注解抽象语法树->字节码生成器->生成Class文件
JVM的跨语言平台
java是通过javac解析成class文件遵行JVM规范文件就可以在jvm中运行
Groovy是通过GroovyC解析成class文件遵行JVM规范文件就可以在jvm中运行
所以只要任何语言遵行JVM规范文件就可以在jvm中运行都可以在JVM上运行
Class文件到JVM过程:
JVM的三大机制:如图下
加载:查找和导入class字节码文件,通过一个类的全路径名指定这样的一些路径之下的找这样的一些类,然后把这个类通过字节流方式加载二进制的字节流。然后在我们堆区生成class对象入口。
链接:是通过三个步骤组成【验证,准备,解析】
1)验证:验证就是去判断这个字节码文件合法性,安全性检查,是否满足遵行JVM规范文件等等相关的信息。
2)准备:准备阶段是为了给静态变量分配内存,并且将它的初始值进行默认值的初始化。
3)解析:解析阶段是把类当中的符号引用,转换成直接引用。
(符号引用实在Class文件里面用一组符号描述目标关系引用,可以是任意符号,任何字面量表示)
(直接引用就是在运行阶段一个真正的目标指针的偏移量或者说通过一种方式去定位到目标的具体实现)
初始化:【为类的静态变量赋值,然后执行类的初始化(static)语句】
1)如果类还没有被加载和链接,那就先进行加载和链接。
2)如果类存在父类,并且父类还没有初始化,那就先初始化直接父类
3)如果类中存在初始化语句,顺序执行初始化语句
Class的初始化时机(6种触发)
1)创建类的实列(四种方式)
(1)new的方式(2)反射的方式(3)克隆的方式clone(4)通过反序列化的方式
2)访问类中的某个静态变量,或者对静态变量进行赋值(也会触发初始化时机)
3)主动调用类的静态方法
4)Class.forName(“包类名”)
5)完成子类的初始化,也会完成对类的初始化(接口列外)
6)该类是程序引导入口(mian入口或者test入口)
类加载器是类加载流程的实现者(JDK 自带的Class Loader)
1)Bootstrap ClassLoader:【启动类加载器】
JVM自带的引用类加载器,由C/C++的语言实现,在java种打印时null。
加载java的核心类库,$JAVA_HOME种jre/lib/rt。jar,resource.jar 或者java程序运行指定的Xbootclasspath目录下jar包。
指定加载java,javax,sum等开头的包名类。
2) Extension ClassLoader:【扩展类加载器】
java语言编写的类加载器 sun.misc.LauncherJAVA_HOME中 jre/lib/ext 或 -Djava.ext.dirs指定目录下的jar包(如果我们自定义的Class需要交给Ext类加载可以放置到ext的目录下)
3) Application ClassLoader:【应用程序类加载器】
java语言编写的类加载器 sun.misc.Launcher$AppClassLoader
该加载器是java程序默认的类加载器,java应用的类都是该类加载器加载的
指定Extension ClassLoader 为parent加载器–>getParent()可以获取Extension ClassLoader
负责加载环境变量Classpath指定的目录,或者java.class.path指定的目录类库
双亲委派的原则:
1)检查某个类是否已加载
自底向上,从Application ClassLoader到BootStrap ClassLoader逐层检查,只要某个Classloader已加载,就视为已加载此类,保证此类只所有Classloader加载一次
2)加载的顺序,向上委托
自顶向下,也就是由上层来逐层尝试加载此类
为啥是双亲委派
-避免类的重复加载
-保护程序安全,防止核心的JAVA语言环境遭受破坏
自定义ClassLoader
extends ClassLoader 重写loadClass方法
extends UrlClassLoader
通过学习总结出来的经验,希望能帮助到大家。