参考:http://www.importnew.com/6581.html

Java 编译器会为虚拟机转换源指令。虚拟机代码存储在以 .class 为扩展名的类文件中,每个类文件都包含某个类或者接口的定义和代码实现。这些类文件必须由一个程序进行解释,该程序能够将虚拟机的指令集翻译成目标机器的机器语言。

虚拟机值加载程序执行时所需要的类文件。

类加载机制并非只使用单个的类加载器。每个 Java 程序至少拥有三个类加载器:

引导类加载器

扩展类加载器

系统类加载器(有时也称为应用类加载器)

引导类加载器负责加载系统类(通常从 JAR 文件 rt.jar 中进行加载)。它是虚拟机不可分割的一部分,而且通常是用 C 语言来实现的。引导类加载器没有对应的 ClassLoader 对象。

扩展类加载器用于从 jre/lib/ext 目录加载 “标准的扩展”。可以将 JAR 文件放入该目录,这样即使没有任何类路径,扩展类加载器也可以找到其中的各个类。

系统类加载器用于加载应用类。它在由 CLASSPATH 环境变量或者 -classpath 命令行选项设置的类路径中的目录里或者是 JAR/ZIP 文件里查找这些类。

在 Oracle 的 Java 语言实现中,扩展类加载器和系统类加载器都是用 Java 来实现的。它们都是 URLClassLoader 类的实例。

警告:如果将 JAR 文件放入 jre/lib/ext 目录中,并且在它的类中有一个类需要调用系统类或者扩展类,那么就会遇到麻烦。扩展类加载器并不使用类路径。

除了所有已经提到的位置,还可以从 jre/lib/endorsed 目录中加载类。这种机制只能用于将某个标准的 Java 类库替换为更新的版本(例如那些支持 XML 和 CORBA 的类)。

类加载器有一种父/子关系。除了引导类加载器外,每个类加载器都有一个父类加载器。根据规定,类加载器会为它的父类加载器提供一个机会,以便加载任何给定的类,并且只有在其父类加载器加载失败时,它才会加载该给定类。

某些程序具有插件架构,其中代码的某些部分是作为可选的插件打包的。如果插件被打包为 JAR 文件,那就可以直接用 URLClassLoader 类的实例去加载这些类。

 package classloader;

 import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader; public class URLDemo { public static void main(String[] args) throws MalformedURLException, ClassNotFoundException, InstantiationException, IllegalAccessException {
URL url= new URL("file:\\E:\\project_neon1\\Demo2\\commons-codec-1.9.jar");
URLClassLoader pluginLoader = new URLClassLoader(new URL[] {url});
Class<?> c1 = pluginLoader.loadClass("org.apache.commons.codec.binary.Base64");
} }

因为在 URLClassLoader 构造器中没有指定父类加载器,因此 pluginLoader 的父亲就是系统类加载器。

大多数时候,你不必操心类加载的层次结构。通常,类是由于其他的类需要它而被加载的,而这个过程对你是透明的。

偶尔,你也会需要干涉和指定类加载器。

考虑下面的例子:

你的应用的代码包含一个助手方法,它要调用 Class.forName(classNameString)。

这个方法是从一个插件类中被调用的。

而 classNameString 指定的正是一个包含在这个插件的 JAR 中类。

插件的作者很合理地期望这个类应该被加载。但是,助手方法的类是由系统类加载器加载的,这正式 Class.forName 所使用的类加载器。而对于它来说,在插件 JAR 中的类是不可视的,这种现象被称为类加载器倒置。

要解决这个问题,助手方法需要使用恰当的类加载器,它可以要求类加载器作为其一个参数传递给他。或者,它可以要求将恰当的类加载器设置成为当前线程的上下文类加载器。

每个线程都有一个对类加载器的引用,称为上下文类加载器。主线程的上下文类加载器是系统类加载器。当新线程创建时,它的上下文类加载器会被设置成为创建该线程的上下文类加载器。因此,如果你不做任何特殊的操作,那么所有线程就都将它们的上下文类加载器设置为系统类加载器。

可以通过下面的调用将上下文类加载器设置成为任何类加载器。

 Thread t = Thread.currentThread();
t.setContextClassLoader(loader);

然后助手方法可以获取这个上下文类加载器:

 Thread t = Thread.currentThread();
ClassLoader loader = t.getContextClassLoader();
Class cl = loaser.loadClass(className);

当上下文类加载器设置为插件类加载器时,问题依旧存在。应用设计者必须作出决策:通常,当调用由不同的类加载器加载的插件类的方法时,进行上下文类加载器的设置是一种好的思路;或者,让助手方法的调用者设置上下文类加载器。

如果你编写了一个按名字来加载类的方法,那么让调用者在传递显示的类加载器和使用上下文类加载器之间进行选择就是一种好的做法。不要直接使用该方法所属的类的类加载器。

在同一个虚拟机中,可以有两个类,它们的类名和包名都是相同的。类是由它的全名和类的加载器来确定的。这项技术在加载来自多处的代码时很有用。例如 servlets 和 EJB 的 “热部署”。

我们可以编写自己的用于特殊目的的类加载器,这使得我们可以在向虚拟机传递字节码之前执行定制的检查。

如果要编写自己的类加载器,只需要继承 ClassLoader 类,然后覆盖下面这个方法

findClass(String className)

ClassLoader 超类的 loadClass 方法用于将类的加载操作委托给其父类加载器去进行,只有当该类尚未加载并且父类加载器也无法加载该类时,才调用 findClass 方法。

如果要实现该方法,必须做到以下几点:

1) 为来自本地文件系统或者其他来源的类加载其字节码

2) 调用 ClassLoader 超类的 defineClass 方法,向虚拟机提供字节码

JavaSE--类加载器的更多相关文章

  1. javaSE高级篇4 — 反射机制( 含类加载器 ) — 更新完毕

    反射机制 1.反射机制是什么?----英文单词是:reflect.在java.lang包下---这才是java最牛逼的技术 首先提前知道一句话----在java中,有了对象,于是有了类,那么有了类之后 ...

  2. 第42天学习打卡(Class类 Class类的常用方法 内存分析 类的加载过程 类加载器 反射操作泛型 反射操作注解)

    Class类 对象照镜子后得到的信息:某个类的属性.方法和构造器.某个类到底实现了哪些接口.对于每个类而言,JRE都为其保留一个不变的Class类型的对象.一个Class对象包含了特定某个结构(cla ...

  3. Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论

    Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论 创建用户自定义的类加载器 要创建用户自定义的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的f ...

  4. Java中的类加载器

    转载:http://blog.csdn.net/zhangjg_blog/article/details/16102131 从java的动态性到类加载机制   我们知道,Java是一种动态语言.那么怎 ...

  5. Java基础-类加载机制与自定义类Java类加载器(ClassLoader)

    Java基础-类加载机制与自定义类Java类加载器(ClassLoader) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 关于类加载器的概念和分类我就不再废话了,因为我在之前的笔 ...

  6. Java虚拟机类加载器及双亲委派机制

    所谓的类加载器(Class Loader)就是加载Java类到Java虚拟机中的,前面<面试官,不要再问我"Java虚拟机类加载机制"了>中已经介绍了具体加载class ...

  7. 彻底搞懂JVM类加载器:基本概念

    本文阅读时间大约9分钟. 写在前面 在Java面试中,在考察完项目经验.基础技术后,我会根据候选人的特点进行知识深度的考察,如果候选人简历上有写JVM(Java虚拟机)相关的东西,那么我常常会问一些J ...

  8. Java-JVM 自定义类加载器

    一.sun.misc.Launcher (ExtClassLoader 与 AppClassLoader 的创建) public Launcher() { Launcher.ExtClassLoade ...

  9. 深入理解java:1.1. 类加载器

    从java的动态性到类加载机制   我们知道,Java是一种动态语言. 那么怎样理解这个“动态”呢? 或者说一门语言具备了什么特性,才能称之为动态语言呢? 对于java,我是这样理解的. 我们都知道J ...

  10. 类文件的结构、JVM 的类加载过程、类加载机制、类加载器、双亲委派模型

    一.类文件的结构 我们都知道,各种不同平台的虚拟机,都支持 "字节码 Byte Code" 这种程序存储格式,这构成了 Java 平台无关性的基石.甚至现在平台无关性也开始演变出 ...

随机推荐

  1. Python MySQL 删除表

    章节 Python MySQL 入门 Python MySQL 创建数据库 Python MySQL 创建表 Python MySQL 插入表 Python MySQL Select Python M ...

  2. springmvc无法访问JS,CSS等文件

    配置好web.xml中的dispatchservlet后,js,css,都不能正常显示 web.xml配置文件 <!-- 核心控制器 --> <servlet> <ser ...

  3. linux系统pid的最大值研究

    内核源码探查 通过对linux内核源码的追踪,可以看到对pid最大值的限定最终集中到include/linux/threads.h文件中的PID_MAX_DEFAULT上了,代码如下: /* * Th ...

  4. intellij idea 怎么全局搜索

    1.Ctrl+N按名字搜索类 相当于eclipse的ctrl+shift+R,输入类名可以定位到这个类文件,就像idea在其它的搜索部分的表现一样,搜索类名也能对你所要搜索的内容多个部分进行匹配,而且 ...

  5. softmax、交叉熵

    Softmax是用于分类过程,用来实现多分类的 它把一些输出的神经元映射到(0-1)之间的实数,并且归一化保证和为1,从而使得多分类的概率之和也刚好为1. Softmax可以分为soft和max,ma ...

  6. 20 ~ express ~ 前台内容分页展示

    一,后台路由文件 /router/main.js var express = require('express') var router = express.Router() var Category ...

  7. tableau-参数

    tableau参数可用在计算字段.筛选器和参考线中替换常量值得动态值. 三种方式:1.在计算字段中使用筛选器 案例动态替换计算字段中设定的目标值. 创建参数 以参数值创建计算字段 2.筛选器中使用参数 ...

  8. 15. react UI组件和容器组件的拆分 及 无状态组件

    1.组件的拆分 组件拆分的前提 当所有的逻辑都出现在一个组件内时 组件会变得非常复杂 不便与代码的维护 所以对组件进行拆分 IU组件 进行页面渲染 容器组件  进行逻辑操作 UI组件的拆分 新建一个 ...

  9. Jenkins-在CentOS7 上安装配置

    Jenkins-在CentOS7 上安装配置 1.安装JDK yum install -y java 2.安装jenkins 方法1:添加Jenkins库到yum库,Jenkins将从这里下载安装. ...

  10. Android尺寸单位

    px:pixels(像素),1px的长度对应屏幕一个像素点的大小. dp/dip:(density-independent pixels,设备无关像素) sp:scaled pixels(可缩放像素) ...