J2EE JVM加载class文件的原理机制
1.Java中的所有类,必须被装载到jvm中才能运行,这个装载工作是由jvm中的类装载器完成的,类装载器所做的工作实质是把类文件从硬盘读取到内存中
2.java中的类大致分为三种:
1.系统类
2.扩展类
3.由程序员自定义的类
3.类装载方式,有两种
1.隐式装载, 程序在运行过程中当碰到通过new 等方式生成对象时,隐式调用类装载器加载对应的类到jvm中,
2.显式装载, 通过class.forname()等方法,显式加载需要的类
隐式加载与显式加载的区别:
两者本质是一样?,
4.类加载的动态性体现
一个应用程序总是由n多个类组成,Java程序启动时,并不是一次把所有的类全部加载后再
运行,它总是先把保证程序运行的基础类一次性加载到jvm中,其它类等到jvm用到的时候再加载,这样的好处是节省了内存的开销,因为java最早就是为嵌入式系统而设计的,内存宝贵,这是一种可以理解的机制,而用到时再加载这也是java动态性的一种体现
5.java类装载器
Java中的类装载器实质上也是类,功能是把类载入jvm中,值得注意的是jvm的类装载器并不是一个,而是三个,层次结构如下:
Bootstrap Loader - 负责加载系统类
|
- - ExtClassLoader - 负责加载扩展类
|
- - AppClassLoader - 负责加载应用类
为什么要有三个类加载器,一方面是分工,各自负责各自的区块,另一方面为了实现委托模型,下面会谈到该模型
6. 类加载器之间是如何协调工作的
前面说了,java中有三个类加载器,问题就来了,碰到一个类需要加载时,它们之间是如何协调工作的,即java是如何区分一个类该由哪个类加载器来完成呢。
在这里java采用了委托模型机制,这个机制简单来讲,就是“类装载器有载入类的需求时,会先请示其Parent使用其搜索路径帮忙载入,如果Parent 找不到,那么才由自己依照自己的搜索路径搜索类”,注意喔,这句话具有递归性
/**
* @author Jamson Huang
*
*/
publicclass TestClass {
/**
* @param args
*/
publicstaticvoid main(String[] args) throws Exception{
//调用class加载器
ClassLoader cl = TestClass.class.getClassLoader();
System.out.println(cl);
//调用上一层Class加载器
ClassLoader clParent = cl.getParent();
System.out.println(clParent);
//调用根部Class加载器
ClassLoader clRoot = clParent.getParent();
System.out.println(clRoot);
}
}
Run, Console中出现的log信息如下:
sun.misc.Launcher$AppClassLoader@7259da
sun.misc.Launcher$ExtClassLoader@16930e2
null
可以看出TestClass是由AppClassLoader加载器加载的
AppClassLoader的Parent 加载器是 ExtClassLoader
但是ExtClassLoader的Parent为 null 是怎么回事呵,朋友们留意的话,前面有提到Bootstrap Loader是用C++语言写的,依java的观点来看,逻辑上并不存在Bootstrap Loader的类实体,所以在java程序代码里试图打印出其内容时,我们就会看到输出为null
【注:以下内容大部分引用java深度历险】
弄明白了上面的示例,接下来直接进入类装载的委托模型实例,写两个文件,如下:
/**
* @author Jamson Huang
*
*/
publicclass Test1 {
/**
* @param args
*/
publicstaticvoid main(String[] args)throws Exception {
System.out.println(Test1.class.getClassLoader());
Test2 test2 = new Test2();
test2.print();
}
}
/**
* @author Jamson Huang
*
*/
publicclass Test2 {
publicvoid print(){
System.out.println(Test2.class);
System.out.println(this.getClass());
System.out.println(Test2.class.getClassLoader());
}
}
Run,Console出现log如下:
sun.misc.Launcher$AppClassLoader@7259da
class com.java.test.Test2
class com.java.test.Test2
sun.misc.Launcher$AppClassLoader@7259da
7. 预先加载与依需求加载
Java 运行环境为了优化系统,提高程序的执行速度,在 JRE 运行的开始会将 Java 运行所需要的基本类采用预先加载( pre-loading )的方法全部加载要内存当中,因为这些单元在 Java 程序运行的过程当中经常要使用的,主要包括 JRE 的 rt.jar 文件里面所有的 .class 文件。
当 java.exe 虚拟机开始运行以后,它会找到安装在机器上的 JRE 环境,然后把控制权交给 JRE , JRE 的类加载器会将 lib 目录下的 rt.jar 基础类别文件库加载进内存,这些文件是 Java 程序执行所必须的,所以系统在开始就将这些文件加载,避免以后的多次 IO 操作,从而提高程序执行效率。
图( 2 )我们可以看到多个基础类被加载, java.lang.Object,java.io.Serializable 等等。
相对于预先加载,我们在程序中需要使用自己定义的类的时候就要使用依需求加载方法( load-on-demand ),就是在 Java 程序需要用到的时候再加载,以减少内存的消耗,因为 Java 语言的设计初衷就是面向嵌入式领域的。
8. 自定义类加载机制
之前我们都是调用系统的类加载器来实现加载的,其实我们是可以自己定义类加载器的。利用 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();
}
我们通过自定义的类加载器实现了 TestClassA 类的加载并调用 method ()方法。分析一下这个程序:首先定义 URL 指定类加载器从何处加载类, URL 可以指向网际网络上的任何位置,也可以指向我们计算机里的文件系统 ( 包含 JAR 文件 ) 。上述范例当中我们从 file:/d:/test/lib/ 处寻找类;然后定义 URLClassLoader 来加载所需的类,最后即可使用该实例了。
9. 类加载器的阶层体系
讨论了这么多以后,接下来我们仔细研究一下 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 和由哪个类加载器加载没有关系。
下面的图形可以表示三者之间的关系:
BootstrapLoader <---(Extends)----AppClassLoader <---(Extends)----ExtClassLoader
这三个加载器就构成我们的 Java 类加载体系。他们分别从以下的路径寻找程序所需要的类:
BootstrapLoader : sun.boot.class.path
ExtClassLoader: java.ext.dirs
AppClassLoader: java.class.path
这三个系统参量可以通过 System.getProperty() 函数得到具体对应的路径。大家可以自己编程实现查看具体的路径。
转载于:https://blog.51cto.com/longx/1288256
J2EE JVM加载class文件的原理机制相关推荐
- JVM加载class文件的原理机制
阅读目录 1.JVM 简介 2.JVM 的组成部分 3.JVM加载class文件的原理机制 在面试java工程师的时候,这道题经常被问到,故需特别注意. 回到顶部 1.JVM 简介 JVM 是我们Ja ...
- 常见Java面试题之JVM加载class文件的原理机制
JVM加载class文件的原理机制 JVM中类的装载是由类加载器(ClassLoader)和它的子类来实现的,Java中的类加载器是一个重要的Java运行时系统组件,它负责在运行时查找和装入类文件中的 ...
- 描述一下JVM加载class文件的原理机制
Java中的所有类,都需要由类加载器装载到JVM中才能运行.类加载器本身也是一个类,而它的工作就是把class文件从硬盘读取到内存中.在写程序的时候,我们几乎不需要关心类的加载,因为这些都是隐式装载的 ...
- java文件读入原理_描述一下JVM加载class文件的原理机制
1.JVM 简介 JVM 是我们Javaer 的最基本功底了,刚开始学Java 的时候,一般都是从"Hello World "开始的,然后会写个复杂点class ,然后再找一些开源 ...
- Java提高篇——JVM加载class文件的原理机制
阅读目录 1.JVM 简介 2.JVM 的组成部分 3.JVM加载class文件的原理机制 在面试java工程师的时候,这道题经常被问到,故需特别注意. 回到顶部 1.JVM 简介 JVM 是我们Ja ...
- 面试常备题---JVM加载class文件的原理机制
在面试java工程师的时候,这道题经常被问到,故需特别注意. Java中的所有类,都需要由类加载器装载到JVM中才能运行.类加载器本身也是一个类,而它的工作就是把class文件从硬盘读取到内存中.在写 ...
- Java - 描述一下JVM加载class文件的原理机制
分享一个大牛的人工智能教程.零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请点击http://www.captainbed.net JVM中类的装载是由类加载器(ClassLoader ...
- java虚拟机及加载class文件的原理机制
2019独角兽企业重金招聘Python工程师标准>>> (点击获取更多资料的下载) java 虚拟机 2007年4月23日,14:18:00 | chenweicai ...
- JVM加载class文件的原理简述
JVM中类的装载是由ClassLoader和它的子类来实现的,Java ClassLoader 是一个重要的Java运行时系统组件.它负责在运行时查找和装入类文件的类. Java中的所有类,都需要由类 ...
最新文章
- F5 Priority Group Activation
- IIC总线上挂载多个从机的程序实现
- iis里面的mime没有php扩展,IIS - 无后缀(无扩展名)的MIME类型配置
- IOS之学习笔记二(块)
- 【C语言】你可能对 sizeof() 有点误解。。。
- 最好用的手机端C/C++语言编程软件, 不要说没电脑就不学编程了!
- linux 重复执行脚本,防止shell脚本重复执行的代码
- [net]ftp ssh http telnet https服务及端口
- Navicat 常用快捷键
- rsync结合inotify工具实现实时同步传输文件
- 计算机二级ms模拟考试系统,全国计算机等级考试二级MS Office高级应用模拟考试系统...
- 非技术类:分享蓝牙音频接收器转音箱的使用
- matlab中princ,基于MATLAB_SIMLINK的Turbo交织器的仿真实现
- 风力发电机组的基本结构
- 接口测试项目(非常值得练手)
- redis源码--SDS结构解析
- 总所周知,Github是一个读小说的网站!《Re0:从零开始的异世界生活》Web版
- 下次激活策略10_宋楠:解读北汽新能源EU5R550核心技术之低温充电预热策略
- 《道德经的人生智慧》读书笔记
- 个人总结感想系列 - 2014年总结