JVM整体结构:
1.方法区和堆是多个线程共享的,Java栈、程序计数器、本地方法栈是每个线程独有一份。
2.执行引擎:由解释器、编译器后端(即时编译器)、垃圾回收器组成。相当于将高级语言翻译成cpu可以运行的机器指令。
JVM生命周期:
1.启动:通过引导类加载器创建一个初始类来完成的。
2.执行:程序执行它就执行
3:结束:
程序正常结束、程序报错或出异常、操作系统错误导致、
Java编译器输入的指令流的两种架构:
1.基于栈式架构:
设计和实现简单,使用于资源受限的系统;
不需要硬件的支持,可移植性好,更好的实现跨平台,指令集小但指令多
2.基于寄存器架构:
指令集架构完全依赖于硬件,可移植性差,性能更优秀,执行更高效
Java虚拟机:
1.Sun Classic VM:
该虚拟机只提供了解释器,效率低下。如果要使用jit编译器,就需要进行外挂,但是解释器就不在工作,解释器和jit编译器不能配合工作。现在hotspot中内置了该虚拟机。
2.Exact VM:(Exact Memory Management:准确性内存管理)
该虚拟机可以知道内存中某个位置的数据具体是什么类型。
热点探测;解释器和编译器混合工作模式。
3.HotSpot VM:(**)
通过计数器找到最具编译价值的热点代码,触发即时编译或栈上替换;
通过编译器和解释器协同工作,在最优化响应时间和最佳执行性能中取得平衡。
4.JRockit VM:(*)
专注于服务端应用,内部不包含解释器,全部代码都靠即时编译器编译后执行,是世界上最快的JVM。
5.J9:(*)
广泛应用于IBM的各种java产品。
解释器:将字节码逐行进行解析成本地机器指令,不需要等待。
JIT即时编译器:先将字节码进行编译成本地机器指令,放入缓存中(方法区的CodeCache),需要等待编译完成后再执行。(二者需要协同工作才能提高效率)
JVM的架构图:
类加载的过程:
加载 ———>动态链接(验证————>准备(该阶段会为类变量设置默认初始值)————>解析)————>初始化(该阶段会为类变量设置初始化的值)
eg: private static int a = 1; prepare: a = 0 ----> init: a = 1;
初始化:初始化阶段就是执行类构造器方法()过程,此方法不需要定义,它将自动收集类中所有的变量的赋值动作和静态代码块中的语句合并而来,不同于类构造器。
一个类的()方法在多线程下被同步加锁;只会加载一次。
类加载器的分类:
1.引导类加载器(BootstrapClassLoader);该类加载器包含自定义类加载器;获取不到,由c/c++编写的。
2.自定义类加载器:将所有直接继承或间接继承ClassLoader抽象类的类加载器都划分为自定义类加载器;包含了:扩张类加载器(ExtensionClassLoader) 系统类加载器(SystemClassLoader)
public class ClassLoaderTest {
public static void main(String[] args) {
//获取系统类加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);//sun.misc.Launcher$AppClassLoader@18b4aac2
//获取其上层:扩展类加载器(包含关系,非继承关系)
ClassLoader extClassLoader = systemClassLoader.getParent();
System.out.println(extClassLoader);//sun.misc.Launcher$ExtClassLoader@1b6d3586
//获取其上层:获取不到引导类加载器
ClassLoader bootStrapClassLoader = extClassLoader.getParent();
System.out.println(bootStrapClassLoader);//null
//对于用户自定义类来说:(发现和系统类加载器对象相等)默认使用系统类加载器进行加载
ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
System.out.println(classLoader);//sun.misc.Launcher$AppClassLoader@18b4aac2
//String类使用引导类加载器进行加载的。 ---->java的核心类库都是由引导类加载器加载的
ClassLoader classLoader1 = String.class.getClassLoader();
System.out.println(classLoader1);//null
}
}
JVM加载字节码文件的方式:
对class文件采用的是按需加载的方式,而且加载某个类的class文件时,采用的是双亲委派模式,即把请求交由父类处理,它是一种任务委派模式。
双亲委派机制原理:(避免类的重复加载)(保护程序安全,防止核心API被随意篡改)
沙箱安全机制:
比如自定义一个String类,但是在加载自定义String类的时候会使用启动类加载器加载核心类库中的String类。这样可以保证对java核心源代码的保护。
JVM中表示两个class对象是否为同一个类的必要条件:
1.类的完整类名必须一致
2.加载这个类的classLoader对象必须相同