一、Java代码运行机制
我们日常写代码的时候,都是新建一个后缀为User.Java文件。之后我们会把User.java文件编译为User.class文件,之后运行的是这个User.class文件,而不是我们新建的User.java文件。我们一般通过"java -jar"命令来运行我们写好的代码。此时一旦你采用了"Java"命令,实际上此时就会启动一个JVM进程。这个JVM进程就会负责运行这些".class"字节码文件,也就相当于是负责运行我们写好的系统。
所以平时我们写好的某个系统在一台机器上部署的时候,你一旦启动这个系统,其实就是启动了一个JVM,由它来负责运行这台机器上运行的这个系统。接着JVM要运行这些.class字节码文件中的字节码,那是不是首先要把这些.class文件中包含的各种类加载进去?此时”类加载器“会把编译好的那些".class"字节码文件给加载到JVM中,然后供后续代码运行来使用。最后一步,JVM就会基于自己的字节码执行引擎来执行加载到内存中我们写好的类。
二、类加载的过程
一个类从加载到使用,一般会经历的几个过程:加载 ->验证->准备->解析->初始化->使用-> 卸载
加载:当我们需要某个类的时候,这个类才会被加载
验证:校验加载进来的".class"字节码文件的内容,是否符合指定的规范
准备:主要给加载进来的类、类变量分配内存空间,并且给默认的初始值
解析:把符号引用替换为直接引用
初始化:完成配置的读取,然后赋值给这个类的变量。另外静态代码块也会在这个阶段执行。一般 new一个对象的时候,就会触发类的加载到初始化的全过程。
三、双亲委派
1、启动类加载器
Bootstrap ClassLoader:主要负责加载我们在机器上安装的Java目录下的lib目录中的核心类库
2、扩展类加载器
Extension ClassLoader:主要负责加载Java安装目录下的lib\ext目录
3、应用类加载器
Application ClassLoader:主要负责加载ClassPath环境变量所指定的路径中的类
4、自定义类加载器
除上面几种之外,还可以自定义类加载器。
JVM的类加载器是有亲子层级结构的,启动类加载器是最上层,扩展类加载器是在第二层,第三层就是应用类加载器,最后一层是自定义类加载器。
假设你的应用类加载器需要加载一个类,它自己不会尝试加载这个类,而是首先会委派自己的父类加载器-扩展类加载器去加载,但是如果扩展类加载器在自己负责加载的范围内,没有找到这个类,就会继续委派上一层的启动类加载器去加载这个类,启动类加载没有在lib目录中找到这个类,然后就会下推加载权限给扩展类加载器,结果扩张类加载器也没有找到这个需要加载的类,扩展类加载器会继续下推加载权限给应用类加载器,最后应用类加载器在自己负责的范围内找到这个类,就把这个类加载到内存里去了。这就是所谓的--双亲委派模型
借道友法力一用:
========================== stay hungry stay foolish =============================