JAVA学习篇--Java类加载
由来:
与普通程序不同的是,Java程序(class文件)并非本地的可执行程序(解释性语言)。
当执行Java程序时。首先执行JVM(Java虚拟机),然后再把Javaclass载入到JVM里头执行,负责载入Javaclass的这部分就ClassLoader。
中文叫做类载入器。
类载入器就好比一个代理,你须要什么。我通过类载入器将你须要的内容返回给你!
类载入器有什么作用?
当程序须要的某个类,那么须要通过类载入器把类的二进制载入到内存中.
解释:
类载入器也是Java类,由于其它是java类的类载入器本身也要被类载入器载入,显然必须有第一个类载入器不是java类,这正是BootStrap。
Java虚拟机中的全部类装载器採用具有父子关系的树形结构进行组织。在实例化每一个类装载器对象时,须要为其指定一个父级类装载器对象或者默认採用系统类装载器为其父级类载入。
Java类载入器:
Java中的类载入器大致能够分成两类。一类是系统提供的。另外一类则是由 Java 应用开发者编写的。
系统提供的类载入器主要有以下三个:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVqaW5neXVhbjY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
引导类载入器(bootstrap classloader):
它用来载入 Java 的核心库,是用原生代码来实现的,并不继承自java.lang.ClassLoader。
扩展类载入器(extensions classloader):
它用来载入 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库文件夹。该类载入器在此文件夹里面查找并载入 Java 类。
系统类载入器(system classloader):
它依据 Java 应用的类路径(CLASSPATH)来载入 Java 类。一般来说。Java 应用的类都是由它来完毕载入的。能够过ClassLoader.getSystemClassLoader() 来获取它。
关系:
能够简单理解它们三者之间是父与子的关系。不同的是每一个ClassLoader本身仅仅能分别载入特定位置和文件夹中的类,但它们能够托付其它的类装载器去载入类。这也就是类载入器的托付模式。托付的过程是子类托付父类!
除了系统提供的类载入器以外,开发者能够通过继承java.lang.ClassLoader 类的方式实现自己的类载入器,以满足一些特殊的需求。
类载入器的托付机制(双亲委派机制):
1>当Java虚拟机要载入一个类时,究竟派出哪个类载入器去载入呢?
①首先当前线程的类载入器去载入线程中的第一个类.
②假设类A中引用了类B,Java虚拟机将使用载入类A的类载入器载入类B
③还能够直接调用ClassLoader.loadClass()方法来指定某个类载入器去载入某个类.
2>每一个类载入器载入类时,又先托付给其上级类载入器.
①类装载器一级级托付到BootStrap类载入器,当BootStrap无法载入当前所要载入的类时,然后才一级级回退到子孙类装载器去进行真正的载入。当回退到最初的类装载器时,假设它自己也不能完毕类的装载,那就应报告ClassNotFoundException异常。
简单解释双亲委派机制:
为了安全。java中有String或者其它的核心类,我们想覆盖是覆盖不了的,由于我们自己写的类都属于在classpath路径下。那classpath的装载器都是系统类装载器,即使我们写了一个一模一样的String,它也会一直请求,一直请求到根,假设上面有一个能载入,比如根,那么它就用根载入那个对象给我们返回,我们自己的永远载入不上。这种话我们不至于破坏java的核心库
代码演示样例:
public class Test {
public static void main(String[] args) {
//载入器:sun.misc.Launcher$AppClassLoader
System.out.println(Test.class.getClassLoader().getClass().getName());
//载入器:BootStrap(loader为null的情况)
System.out.println(System.class.getClassLoader());//
System.out.println("----------------查看类载入器的层次结构关系-------------------");
ClassLoader loader = Test.class.getClassLoader();
while(loader != null){
System.out.println(loader.getClass().getName());
loader = loader.getParent();
}
System.out.println(loader);
}
/**
* 执行结果:
* sun.misc.Launcher$AppClassLoader
null
----------------查看类载入器的层次结构关系-------------------
sun.misc.Launcher$AppClassLoader
sun.misc.Launcher$ExtClassLoader
null
*/
}
能不能自己写一个类叫java.lang.System?
为了不让我们写System类,类载入採用托付机制,这样能够保证爸爸优先,也就是使用的永远是爸爸的(系统的)System类,而不是我们写的System类.
设计动机:
Java 虚拟机是怎样判定两个 Java类是同样的呢?
Java虚拟机不仅要看类的全名是否同样,还要看载入此类的类载入器是否一样。
仅仅有两者都同样的情况,才觉得两个类是同样的。即便是同样的字节代码,被不同的类载入器载入之后所得到的类。也是不同的。
比方一个Java 类com.example.Sample。编译之后生成了字节代码文件 Sample.class。两个不同的类载入器 ClassLoaderA 和ClassLoaderB 分别读取了这个 Sample.class 文件,并定义出两个 java.lang.Class 类的实例来表示这个类。这两个实例是不同样的。
对于Java 虚拟机来说,它们是不同的类。
了解了以上这一点之后,就能够理解设计动机了,这样的托付机制是为了保证Java 核心库的类型全。
全部 Java 应用都至少须要引用 java.lang.Object 类。也就是说在执行的时候,java.lang.Object这个类须要被载入到 Java 虚拟机中。假设这个载入过程由 Java 应用自己的类载入器来完毕的话。非常可能就存在多个版本号的java.lang.Object类,并且这些类之间是不兼容的。通过托付机制,对于 Java 核心库的类的载入工作由引导类载入器来统一完毕。保证了
Java 应用所使用的都是同一个版本号的Java 核心库的类。是互相兼容的。
类载入器与 Web 容器:
对于执行在容器中的 Web 应用来说。类载入器的实现方式与一般的 Java 应用有所不同。不同的 Web 容器的实现方式也会有所不同。
以Apache Tomcat 来说,每一个 Web 应用都有一个相应的类载入器实例。该类载入器也使用托付机制,所不同的是它是首先尝试去载入某个类。假设找不到再托付给父类载入器。这与一般类载入器的顺序是相反的。这是
Java Servlet 规范中的推荐做法。其目的是使得 Web应用自己的类的优先级高于 Web 容器提供的类。
这样的托付的一个例外是:Java 核心库的类是不在查找范围之内的。
这也是为了保证 Java核心库的类型安全。
Tomcat载入器:
和第一幅图有什么关系呢?
本图是基于第一幅图(java自带机制)的又一层封装,它是基于第一幅图的,仅仅是tomcat在java的基础上自己定义了一些非核心类库的载入器,以供用户使用!
总结:
绝大多数情况下。对于Web应用的开发者不须要考虑与类载入器相关的细节。可是当出现ClassNotFoundException异常我们能大概了解问题所在。
以下给出几条简单的原则:
每一个 Web 应用自己的 Java类文件和使用的库的 jar 包,分别放在 WEB-INF/classes和 WEB-INF/lib文件夹以下。
多个应用共享的 Java 类文件和 jar包。分别放在 Web 容器指定的由全部 Web 应用共享的文件夹以下。
当出现找不到类的错误时,检查当前类的类载入器和当前线程的上下文类载入器是否正确。这些原则也是依据java类载入器和自己定义载入器的实现方式总结而来。须要我们简单的理解!
版权声明:本文博客原创文章,博客,未经同意,不得转载。
JAVA学习篇--Java类加载的更多相关文章
- JAVA学习篇--JAVA两种编程模式控制
在Drp项目中,解说了两种编程模式Model 1和Model2.以下是对这两种模式的简单理解.以及因为Model2是基于MVC架构的模式,就将我们易混淆的MVC与我们之前学的三层架构进行对照学习一下. ...
- [java学习笔记]java语言核心----面向对象之this关键字
一.this关键字 体现:当成员变量和函数的局部变量重名时,可以使用this关键字来区别:在构造函数中调用其它构造函数 原理: 代表的是当前对象. this就是所在函数 ...
- [java学习笔记]java语言核心----面向对象之构造函数
1.构造函数概念 特点: 函数名与类名相同 不用定义返回值类型 没有具体的返回值 作用: 给对象进行初始化 注意: 默认构造函数 多个构造函数是以重载出现的 一个类中如果 ...
- [ Java学习基础 ] Java构造函数
构造方法是类中特殊方法,用来初始化类的实例变量,它在创建对象(new运算符)之后自动调用. Java构造方法的特点如下: 构造方法名必须与类名相同. 构造方法没有任何返回值,包括void. 构造方法只 ...
- [ Java学习基础 ] Java的继承与多态
看到自己写的东西(4.22的随笔[ Java学习基础 ] Java构造函数)第一次达到阅读100+的成就还是挺欣慰的,感谢大家的支持!希望以后能继续和大家共同学习,共同努力,一起进步!共勉! ---- ...
- [ Java学习基础 ] Java的抽象类与接口
一.抽象类 1. 抽象类 Java语言提供了两种类:一种是具体类:另一种是抽象子类. 2. 抽象类概念: 在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的 ...
- Java基础篇(JVM)——类加载机制
这是Java基础篇(JVM)的第二篇文章,紧接着上一篇字节码详解,这篇我们来详解Java的类加载机制,也就是如何把字节码代表的类信息加载进入内存中. 我们知道,不管是根据类新建对象,还是直接使用类变量 ...
- 8.6(java学习笔记)类加载过程及类加载器
一.类加载 1.加载 将class字节码加载到内存中,同时在方法区形成改类运行时数据结构. 同时在堆中产生一个Class对象,反射就是获取这个对象并对其进行操作. 2.链接 2.1验证:验证加载的类信 ...
- 学习Java第一篇——Java 安装及环境搭配
内容提要: 1.下载JDK: 2.安装JDK: 3.配置JDK; 第一,下载JDK: 1.登陆网址:www.oracle.com 2.点击 Downloads 3.选择 Java SE 4.选择 ...
随机推荐
- sqlserver缓存程序-只能使用一次清除缓存计划
plan cache非常大.将仅仅使用一次的缓存计划清除,而不用清除整个cache. declare @sid varbinary(64) declare cur01 cursor for selec ...
- 将android界面背景设置为黑色
屏幕背景设置为黑色的几种方式: 新建项目时候 第二次next之后(不同sdk版本号可能不同),Background Color项点击可选. 开公布局文件,选择视图查看 就是下边二个选项卡中的第一个(G ...
- netback于kthread遇到cpu affinity问题
最近的升级netback, 在测试过程中,查找vm全双工压力,rx的pps波动很厉害,见rx kthread尽管cpu affinity它是0-7 (dom0 8vcpu), 但往往,她去了物理破坏c ...
- Linux网络编程一站式学习
提要 学过非常多遍计算机网络,依旧不会网络编程. 看完这篇文章之后就不会是这样了. 环境:Ubuntu14.04 64bit 何为Socket 是基于TCP/IP的网络应用编程中使用的有关数据通信的概 ...
- Android应用程序的组成部分和Manifest文件(转)
Android应用程序由松散耦合的组件组成,并使用应用程序Manifest绑定到一起:应用程序Manifest描述了每一组件和它们之间的交互方式,还用于指定应用程序元数据.其硬件和平台要求.外部库以及 ...
- cygwin的163镜像(转)
国内的cygwin源镜像: 1.163源 http://mirrors.163.com/.help/cygwin.html 收录架构 x86 x86_64 收录版本 所有版本 更新时间 每天更新一次 ...
- 基于LINUX的多功能聊天室
原文:基于LINUX的多功能聊天室 基于LINUX的多功能聊天室 其实这个项目在我电脑已经躺了多时,最初写完项目规划后,我就认认真真地去实现了它,后来拿着这个项目区参加了面试,同样面试官也拿这个项目来 ...
- Linux centos 主机名颜色设置 和 别名设置
方便和乐趣写今天.至于为什么主机名颜色设置 和 别名设置放在一起写.这是因为他们的设置是在一个文件中..bashrc. .bashrc放在cd /root 这个文件夹下! 这个文件主要保存个人的一些个 ...
- TFS 2010 使安装更容易,让VSS历史
一转眼VS 2010 RC(Release Candidate)版本号已经公布一月多了,RTM(Release To Manufacturer)版本号也快妥了,已经进入了最后的倒计时,仅仅等4月12号 ...
- hdu4864Task(馋)
主题链接: 啊哈哈.点我 题目: Task Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Ot ...