JVM 全称是Java Virtual Machine ,Java 虚拟机,也就是在计算机上再虚拟一个计算机。java
这和咱们使用 VMWare 不同,那个虚拟的东西你是能够看到的,这个JVM 你是看不到的,它存在内存中。程序员
计算机的基本构成是:运算器、控制器、存储器、输入和输出设备。编程
JVM 也是有这成套的元素:框架
运算器 -固然是交给硬件CPU 还处理了jvm
为了适应“一次编译,随处运行”的状况,须要作一个翻译动做,因而就用了JVM 本身的命令集。编程语言
这与汇编的命令集有点相似,每一种汇编命令集针对一个系列的CPU ,函数
好比8086 系列的汇编也是能够用在8088 上的,可是就不能跑在8051 上。url
JVM 的命令集则是能够处处运行的,由于JVM根据不一样的CPU ,翻译成不一样的机器语言。spa
存储器 - JVM 是一个内存中的虚拟机,那它的存储器就是内存了。操作系统
咱们写的全部类、常量、变量、方法都在内存中。
类加载器的做用是加载类文件到内存,
好比编写一个HelloWord.java 程序,而后经过javac 编译成class 文件,
那怎么才能加载到内存中被执行呢?Class Loader 承担的就是这个责任。
Class Loader 只管加载,只要符合文件结构就加载,
至于说能不能运行,则不是它负责的,那是由Execution Engine 负责的。
也叫作解释器(Interpreter) ,负责解释命令,提交操做系统执行。
本地接口的做用是融合不一样的编程语言为Java 所用,它的初衷是融合C/C++ 程序
目前该方法使用的已经比较少见了,由于如今的异构领域间的通讯很发达,
好比可使用Socket 通讯,也可使用Web Service 等等
4) Runtime data area 运行数据区
运行数据区是整个JVM 的重点。咱们全部写的程序都被加载到这里,以后才开始运行
整个JVM 框架由加载器加载文件,而后执行器在内存中处理数据,须要与异构系统交互是能够经过本地接口进行,一个完整的系统诞生了。
这个装载工做是由jvm中的类装载器完成的,类装载器所作的工做实质是把类文件从硬盘读取到内存中。
1) 系统类
2) 扩展类
3) 由程序员自定义的类
1) 隐式装载。 程序在运行过程当中当碰到经过new 等方式生成对象时,
隐式调用类装载器加载对应的类到jvm中。
2) 显式装载。 经过class.forname()等方法,显式加载须要的类。
隐式加载与显式加载的区别:
一个应用程序老是由n多个类组成,Java程序启动时,并非一次把全部的类所有加载后再 运行.
它老是先把保证程序运行的基础类一次性加载到jvm中,其它类等到jvm用到的时候再加载.
这样的好处是节省了内存的开销.
Java中的类装载器实质上也是类,功能是把类载入jvm中.
值得注意的是jvm的类装载器并非一个,而是三个。
为何要有三个类加载器,一方面是分工,各自负责各自的区块,另外一方面为了实现委托模型。
Bootstrap Loader - 负责加载系统类(用C++语言写的) 搜索路径:sun.boot.class.path
|
ExtClassLoader - 负责加载扩展类 搜索路径:java.ext.dirs
|
AppClassLoader - 负责加载应用类 搜索路径:java.class.path
在这里java采用了委托模型机制.
类装载器有载入类的需求时,会先请示其Parent使用其搜索路径帮忙载入,
若是Parent 找不到,那么才由本身依照本身的搜索路径搜索类。
1)在 JRE 运行的开始会将 Java 运行所须要的基本类采用预先加载( pre-loading )的方法所有加载要内存当中.
主要包括 JRE 的 rt.jar 文件里面全部的 .class 文件
2) 当 java.exe 虚拟机开始运行之后,它会找到安装在机器上的 JRE 环境,而后把控制权交给 JRE .
JRE 的类加载器会将 lib 目录下的 rt.jar 基础类别文件库加载进内存.
3) 相对于预先加载,咱们在程序中须要使用本身定义的类的时候就要使用依需求加载方法
( load-on-demand ),就是在 Java 程序须要用到的时候再加载,以减小内存的消耗.
通常咱们都是调用系统的 类加载器来实现加载的,其实咱们是能够本身定义类加载器的。
利用 Java 提供的 java.net.URLClassLoader 类就能够实现。
try {
URL url = new URL( "file:/d:/test/lib/" );
URLClassLoader urlCL = new URLClassLoader( new URL[]{url});
Class c = urlCL.loadClass("TestClassA" );
TestClassA object = (TestClassA)c.newInstance();
object.method();
}catch (Exception e){
e.printStackTrace();
}
1)Java 的类加载器的工做原理:
当执行 java ***.class 的时候, java.exe 会帮助咱们找到 JRE
接着找到位于 JRE 内部的 jvm.dll ,这才是真正的 Java 虚拟机器
最后加载动态库,激活 Java 虚拟机器
虚拟机器激活之后,会先作一些初始化的动做,好比说读取系统参数等。
一旦初始化动做完成以后,就会产生第一个类加载器―― Bootstrap Loader
Bootstrap Loader 是由 C++ 所撰写而成
Bootstrap Loader 所作的初始工做中,除了一些基本的初始化动做以外,
最重要的就是加载 Launcher.java 之中的 ExtClassLoader ,并设定其 Parent 为 null
表明其父加载器为 BootstrapLoader
而后 Bootstrap Loader 再要求加载 Launcher.java 之中的 AppClassLoader ,
并设定其 Parent 为以前产生的 ExtClassLoader 实体
*Launcher$ExtClassLoader.class 与 Launcher$AppClassLoader.class 都是由 Bootstrap Loader 所加载,
因此 Parent 和由哪一个类加载器加载没有关系。
2)类加载器之间的关系
BootstrapLoader <---(Extends)----AppClassLoader <---(Extends)----ExtClassLoader
这三个加载器就构成咱们的 Java 类加载体系
3) 他们分别从如下的路径寻找程序所须要的类:
BootstrapLoader : sun.boot.class.path
ExtClassLoader: java.ext.dirs
AppClassLoader: java.class.path
这三个系统参量能够经过 System.getProperty() 函数获得具体对应的路径。