先来看下百度百科的解释:java
JVM 是 Java Virtual Machine(Java 虚拟机)的缩写,JVM 是一种用于计算设备的规范,它是一个虚构出来的计算机,是经过在实际的计算机上仿真模拟各类计算机功能来实现的。数据库
晦涩难懂有没有,简单理解就是说虚拟机是物理机的软件实现。编程
Java 的设计理念是 WORA(Write Once Run Anywhere,一次编写处处运行)。编译器将 Java 文件编译为 Java .class 文件,而后将 .class 文件输入到 JVM 中,JVM 执行类文件的加载和执行,最后转变成机器能够识别的机器码进行最终的操做。数组
JVM体系结构图缓存
一、加载安全
加载指的是将类的class文件读入到内存,并为之建立一个java.lang.Class对象,也就是说,当程序中使用任何类时,系统都会为之创建一个java.lang.Class对象。网络
类的加载由类加载器完成,类加载器一般由JVM提供,这些类加载器也是前面全部程序运行的基础,JVM提供的这些类加载器一般被称为系统类加载器。除此以外,开发者能够经过继承ClassLoader基类来建立本身的类加载器。数据结构
经过使用不一样的类加载器,能够从不一样来源加载类的二进制数据,一般有以下几种来源。jvm
2.连接
当类被加载以后,系统为之生成一个对应的Class对象,接着将会进入链接阶段,连接阶段负责把类的二进制数据合并到JRE中。类连接又可分为以下3个阶段。布局
1)验证:验证阶段用于检验被加载的类是否有正确的内部结构,并和其余类协调一致。Java是相对C++语言是安全的语言,例如它有C++不具备的数组越界的检查。这自己就是对自身安全的一种保护。验证阶段是Java很是重要的一个阶段,它会直接的保证应用是否会被恶意入侵的一道重要的防线,越是严谨的验证机制越安全。验证的目的在于确保Class文件的字节流中包含信息符合当前虚拟机要求,不会危害虚拟机自身安全。其主要包括四种验证,文件格式验证,元数据验证,字节码验证,符号引用验证。
2)准备:类准备阶段负责为类的静态变量分配内存,并设置默认初始值。
3)解析:将类的二进制数据中的符号引用替换成直接引用。说明一下:符号引用:符号引用是以一组符号来描述所引用的目标,符号能够是任何的字面形式的字面量,只要不会出现冲突可以定位到就行。布局和内存无关。直接引用:是指向目标的指针,偏移量或者可以直接定位的句柄。该引用是和内存中的布局有关的,而且必定加载进来的。
3.初始化
初始化是为类的静态变量赋予正确的初始值,准备阶段和初始化阶段看似有点矛盾,实际上是不矛盾的,若是类中有语句:private static int a = 10,它的执行过程是这样的,首先字节码文件被加载到内存后,先进行连接的验证这一步骤,验证经过后准备阶段,给a分配内存,由于变量a是static的,因此此时a等于int类型的默认初始值0,即a=0,而后到解析(后面在说),到初始化这一步骤时,才把a的真正的值10赋给a,此时a=10。
负责加载class文件,class文件在文件开头由特定的文件标识,将class文件字节码内容加载到内存中,并将这些内容转换成方法区中的运行时数据结构而且ClassLoader只负责class文件的加载,至于它是否能够运行,则由Execution Engine(执行引擎)决定。
四种类加载器
虚拟机自带的加载器
Bootstrap ClassLoader是由C/C++编写的,它自己是虚拟机的一部分,因此它并非一个JAVA类,也就是没法在java代码中获取它的引用,JVM启动时经过Bootstrap类加载器加载rt.jar等核心jar包中的class文件,以前的int.class,String.class都是由它加载。而后呢,咱们前面已经分析了,JVM初始化sun.misc.Launcher并建立Extension ClassLoader和AppClassLoader实例。并将ExtClassLoader设置为AppClassLoader的父加载器。Bootstrap没有父加载器,可是它却能够做用一个ClassLoader的父加载器。好比ExtClassLoader。这也能够解释以前经过ExtClassLoader的getParent方法获取为Null的现象
System.out.println(new Object().getClass().getClassLoader()); //这也就是为何这段代码打印出结果为null的缘由
ExtClassLoader称为扩展类加载器,主要负责加载Java的扩展类库,默认加载JAVA_HOME/jre/lib/ext/目录下的全部jar包或者由java.ext.dirs系统属性指定的jar包.放入这个目录下的jar包对AppClassLoader加载器都是可见的(由于ExtClassLoader是AppClassLoader的父加载器,而且Java类加载器采用了委托机制).
AppClassLoader应用类加载器,又称为系统类加载器,负责在JVM启动时,加载来自在命令java中的classpath或者java.class.path系统属性或者CLASSPATH操做系统属性所指定的JAR类包和类路径.
public class AppClassLoaderTest { public static void main(String[] args) { ClassLoader classLoader = Test.class.getClassLoader(); System.out.println(classLoader); System.out.println(classLoader.getParent()); } private static class Test { } } //执行结果以下 sun.misc.Launcher$AppClassLoader@73d16e93 sun.misc.Launcher$ExtClassLoader@15db9742 //从上面的运行结果能够得知AppClassLoader的父加载器是ExtClassLoader
用户自定义的加载器
JVM的类加载机制主要有以下3种:
双亲委派机制的做用
一、防止重复加载同一个.class。经过委托去向上面问一问,加载过了,就不用再加载一遍。保证数据安全。 二、保证核心.class不能被篡改。经过委托方式,不会去篡改核心.class,即便篡改也不会去加载,即便加载也不会是同一个.class对象了。不一样的加载器加载同一个.class也不是同一个Class对象。这样保证了Class执行安全。