JVM虚拟机
jvm的生命周期
- 虚拟机的启动:java虚拟机的启动是通过引导类加载器创建一个初始类来完成的,这个类是由虚拟机的具体实现来指定的。
- 虚拟机的运行:
– 一个运行中的java虚拟机有一个清晰的任务,执行java程序。
– 程序开始执行时他才运行,程序结束时他才停止。
– 执行一个java程序时,真正执行的是一个叫java虚拟机的进程。 - 虚拟机的退出:有如下几种情况
– 程序正常执行结束
– 程序在执行过程中遇到了异常或错误而异常终止
– 由于操作系统错误而导致java虚拟机进程终止
– 某线程调用Runtime类或者System类的exit方法,或Runtime类的halt方法,并且java安全管理器也允许这次exit或halt操作
– 除此之外,JNI规范的描述了用JNI Invocation API来加载或卸载java虚拟机时,java虚拟机退出的情况。
类加载子系统
概述类加载器以及类的加载过程
类加载器子系统作用
如图所示,类加载器子系统总共有三个阶段分别是:加载阶段,链接阶段,初始化阶段。
作用:
- 类加载器子系统负责从文件系统或网络中加载class文件,class文件在文件开头有特定的文件标识
- ClassLoader只负责class文件的加载,至于他是否可以运行,则由ExecuectionEngine决定。
- 加载的类信息存放于一块称为方法区的内存空间,除了类的信息外,方法区还会存放运行时常量池信息,可能还包括字符串字面量和数字常量(这部分常量信息是Class文件中常量池部分的内存映射)
加载:
1.通过一个类的全限定名获取定义此类的二进制字节流
2.将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
3.在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口
链接:
验证(verify):
目的在于确保Class文件的字节流中包含的信息符合当前虚拟机要求,保证类被加载的正确性,不会危害虚拟机自身安全。主要包括以下四种验证:文件格式验证,元数据验证,字节码验证,符号引用验证。
准备(Prepare):
为类变量分配内存并且设置该变量的默认初始值,即零值。这里不包含用final修饰的static,因为final在编译的时候就会分配了准备阶段会显示初始化。这里不会为实例变量分配初始化,类变量会分配在方法区中,而实例变量是会随着对象一起分配到java堆中。
解析(Resolve):
1.将常量池中的符号引用转换为直接引用的过程。
2.事实上,解析操作往往会伴随着jvm在执行初始化之后在执行
3.符号引用就是一组符号来描述所引用的目标。
4.解析动作主要针对类或者接口,字段,类方法,接口方法,方法类型等。
初始化:
-
初始化阶段就是执行类构造器方法()的过程
-
此方法不需要定义,是javac编译器自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并而来
-
构造器方法中指令按照语句在源文件中的顺序执行
-
()不同于类的构造器
-
若该类有父类,jvm会保证子类方法执行前,父类的clinit方法已经执行完毕
-
虚拟机必须保证一个类的clinit方法在多线程下被同步加锁
jvm支持两种类型的加载器引导类加载器和自定义类加载器
双亲委派机制
- 工作原理:
1 .如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行
2 如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归请求最终将达到顶层的启动类加载器
- 如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成类加载任务,子加载器才会尝试自己去加载,这个就是双亲委派模式。
- 优点:
1.避免类的重复加载
2.保护程序安全,防止核心API被随意篡改
沙箱安全机制:自定义String类,但是在加载自定义String类的时候会率先使用引导类加载器加载,而引导类加载器在加载的过程中会先加载jdk自带的文件,(rt.包中java\lang\String.class),报错信息说没有main方法,就是因为加载的是rt.jar中的String类,这样可以保证对java核心源代码的保护,这就是沙箱安全机制