除了自定义的类加载之外,jvm存在三种类加载器,并以一种父委托的加载机制进行加载。

--启动类加载器,又称根加载器,是一个native的方法,使用c++实现。在java中我们用null标识,用于加载jdk自带的类。

--扩展类加载器,用于加载jdk扩展类

--系统类加载器,用于加载classpath目录下的类


上面提到的三种类加载器,是存在父子关系,即系统类加载器会委托extension加载器,如果extension加载器不能加载该类的话,再由系统类加载器进行加载。注意这里所说的父子关系不是指继承关系,而是一种组合关系。至于为什么要使用这种父委托加载机制呢?

一个显而易见的好处就是Java类伴随着它的类加载器一起具备了一种带有优先级带层次关系,列如类java.lang.Object,它存放在rt.jar之中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的启动类加载器进行加载的,因此Object类在程序的各种类加载器环境中是同一个类。相反,如果没有使用双亲委派模型,由各个类加载器自行去加载的话,如果用户自己编写了一个成为java.lang.Object的类,并放在程序的classpath下面,那系统将出现多个Object类,java类型体系中最基础的行为也就无法保证类,应用程序也将会变得一片混乱。


实现一个自定义类加载器只需继承ClassLoader,重写findClass()方法

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream; /**
* @desc
* @author chenqm
* @date 2016年2月17日
*/
public class MyClassLoader extends ClassLoader { private String name; //类加载器的名字
private String path = "d:\\"; //加载类的路径
private String fileType = ".class";//Class文件的扩展名
public MyClassLoader(String name){
super();
this.name = name;
} public MyClassLoader(ClassLoader parent,String name){
super(parent);//显式制定该类加载器的父加载器
} public String getPath() {
return path;
} public void setPath(String path) {
this.path = path;
} @Override
public Class<?> findClass(String name) throws ClassNotFoundException{
byte[] data = this.loadClassData(name);
return this.defineClass(name, data, 0, data.length);
} private byte[] loadClassData(String name){
InputStream is = null; byte[] data = null; ByteArrayOutputStream baos = null; try{
name = name.replace(".", "\\");
is = new FileInputStream(path + name +fileType);
baos = new ByteArrayOutputStream();
int ch =0 ;
while(-1 !=(ch = is.read())){
baos.write(ch);
}
data = baos.toByteArray();
}catch(Exception e){
e.printStackTrace();
}finally{
try{
is.close();
baos.close();
}catch(Exception e){
e.printStackTrace();
}
} return data;
} @Override
public String toString() {
// TODO Auto-generated method stub
return name;
} public static void main(String[] args) throws Exception{
MyClassLoader loader1 = new MyClassLoader("loader1");
loader1.setPath("d:\\myapp\\serverlib\\");
MyClassLoader loader2 = new MyClassLoader(loader1,"loader2");
loader2.setPath("d:\\myapp\\clientlib\\");
MyClassLoader loader3 = new MyClassLoader(null,"loader3");
loader3.setPath("d:\\myapp\\otherlib\\");
test(loader1);
test(loader2);
test(loader3);
} public static void test(ClassLoader loader) throws Exception{
Class clazz = loader.loadClass("Simple");
Object o = clazz.newInstance();
}
}

这里我自定了一个类加载器,用于加载simple类

/**
* @desc
* @author chenqm
* @date 2016年2月17日
*/
public class Simple {
public Simple(){
System.out.println("Sample is loaded by:"+this.getClass().getClassLoader());
Dog dog = new Dog();
System.out.println("Dog is loaded by:"+dog.getClass().getClassLoader());
}
}

给出dog类:

/**
* @desc
* @author chenqm
* @date 2016年2月17日
*/
public class Dog { }

然后把Dog.class与Simple.class文件放到d:\myapp\serverlib 和d:\myapp\clientlib(两个路径下均有两个class),将MyClassLoader文件放到d:\myapp\otherlib下面。

进入d:\myapp\otherlib 执行java MyClassLoader

得到结果:

Sample is loaded by:loader1
Dog is loaded by:loader1
Sample is loaded by:loader1
Dog is loaded by:loader1
java.io.FileNotFoundException: d:\myapp\otherlib\Simple.class (No such file or directory)

简单分析一下,请注意MyClassLoader的main方法,有三个自定类加载器loader1(父加载器是系统类加载器),loader2(父加载器是loader1),loader3(父加载器是根加载器)。

test方法:用指定的类加载器去加载simple类。

--用loader1去加载simple类的时候,loader1的父加载器是系统类加载器,系统类加载器肯定无法加载simple类,为什么呢?前面说了,系统类加载器用于加载classpath下的类,而classpath默认是什么?  "."就是当前路径,而当前路径不存在simple类,所以进而由loader1加载。

--loader2的父加载器是loader1,所以根据父委托加载机制,理应由loader1去加载simple类。

--loader3的父加载器是根加载器,根加载器是不会加载我们自定义的类文件的,所以加载的重任就交给了loader3,但是loader3的目录下,不存在simple.class文件,没办法了,父亲干不了,自己也干不了,那只能抛异常咯。

												

JVM之类加载器下篇的更多相关文章

  1. JVM自定义类加载器加载指定classPath下的所有class及jar

    一.JVM中的类加载器类型 从Java虚拟机的角度讲,只有两种不同的类加载器:启动类加载器和其他类加载器. 1.启动类加载器(Boostrap ClassLoader):这个是由c++实现的,主要负责 ...

  2. 【深入理解JVM】类加载器与双亲委派模型 (转)

    出处: [深入理解JVM]类加载器与双亲委派模型 加载类的开放性 类加载器(ClassLoader)是Java语言的一项创新,也是Java流行的一个重要原因.在类加载的第一阶段“加载”过程中,需要通过 ...

  3. 1.1 jvm核心类加载器--jdk源码剖析

    目录 前提: 运行环境 1. 类加载的过程 1.1 类加载器初始化的过程 1.2 类加载的过程 1.3 类的懒加载 2. jvm核心类加载器 3. 双亲委派机制 4. 自定义类加载器 5. tomca ...

  4. 【JVM】JVM之类加载器

    一.前言 首先,小小测试,看是否已经掌握了JVM类加载的过程 1.1.测试一 class Singleton { private static Singleton sin = new Singleto ...

  5. 【深入理解JVM】类加载器与双亲委派模型

    原文链接:http://blog.csdn.net/u011080472/article/details/51332866,http://www.cnblogs.com/lanxuezaipiao/p ...

  6. JVM学习一:JVM之类加载器概况

    18年转眼就3月份都快结束了,也就是说一个季度就结束了:而我也因为年前笔记本坏了,今天刚修好了,那么也应该继续学习和博客之旅了.今年的博客之旅,从JVM开始学起,下面我们就言归正传,进入正题. 一.J ...

  7. (转)JVM——自定义类加载器

    背景:为什么要自定义,如何自定义,实现过程 转载:http://blog.csdn.net/SEU_Calvin/article/details/52315125 0. 为什么需要自定义类加载器 网上 ...

  8. JVM虚拟机-类加载器子系统

    转自博客:http://www.cnblogs.com/muffe/p/3541189.html   还有一些自己补充的知识点 一.类加载器基本概念 顾名思义,类加载器(class loader)用来 ...

  9. 深入理解JVM一类加载器原理

    我们知道我们编写的java代码,会经过编译器编译成字节码文件(class文件),再把字节码文件装载到JVM中,映射到各个内存区域中,我们的程序就可以在内存中运行了.那么字节码文件是怎样装载到JVM中的 ...

随机推荐

  1. MongoDB与内存

    来自  http://www.ttlsa.com/mongodb/mongodb-and-memory/# 但凡初次接触MongoDB的人,无不惊讶于它对内存的贪得无厌,至于个中缘由,我先讲讲Linu ...

  2. 位运算(&)实现分享弹窗上的图标动态显示/隐藏

    一  需求     要求自定义弹窗,上面动态显示多种分享平台,根据后台api接口传递过来的type控制显示哪些平台icon     1 定义平台变量,用2的几次方来定value     2 若要显示那 ...

  3. 如何参与一个 GitHub 开源项目?

    最近一年开源项目特别的热,很多技术大会或论坛都以开源项目作为主题进行探讨,可见这是一种趋势.而Github作为开源项目的著名托管地,可谓无 人不知,越来越多的个人和公司纷纷加入到Github的大家族里 ...

  4. 一个简单的、面向对象的javascript基础框架

    如果以后公司再能让我独立做一套新的完整系统,那么我肯定会为这个系统再写一个前端框架,那么我到底该如何写这个框架呢? 在我以前的博客里我给大家展示了一个我自己写的框架,由于当时时间很紧张,做之前几乎没有 ...

  5. 用1、2、2、3、4、5这六个数字,用java写一个main函数,打印出所有不同的排列,如:512234、412345等,要求:"4"不能在第三位,"3"与"5"不能相连。

    最近在看算法,看到这个题,觉得挺经典的,收起. 分析: 1 .把问题归结为图结构的遍历问题.实际上6个数字就是六个结点,把六个结点连接成无向连通图,对于每一个结点求这个图形的遍历路径,所有结点的遍历路 ...

  6. 分享一个U3D在Runtime显示碰撞盒的插件

    有些时候,我们需要在Game视图显示碰撞盒,比如格斗游戏我要开发碰撞配置的工具,我经常需要看到碰撞盒,今天找了一下,没有发现合适的插件,我还花5美金买了一个插件,结果也只是在scene视图显示,这里我 ...

  7. Canny算子边缘检测(cvCanny)

    Canny是常用的边缘检测方法,其特点是试图将独立边的候选像素拼装成轮廓. John Canny于1986年提出Canny算子,它与Marr(LoG)边缘检测方法类似,也属于是先平滑后求导数的方法. ...

  8. VUE 意淫笔记

    caihg Vue.js 递归组件实现树形菜单 最近看了 Vue.js 的递归组件,实现了一个最基本的树形菜单. 项目结构: main.js 作为入口,很简单: 1 2 3 4 5 6 7 8 9 i ...

  9. 爱上MVC3~为下拉列表框添加一个自定义验证规则

    回到目录 开发它的原因: 之前的同事,也是我的哥们,问我下拉列表框是否可以支持验证,这个问题看似简单,但确实MVC里有为我们提供,所以,只能自己写个扩展了,即自己写一个attribute特性,让它继承 ...

  10. JS基础知识总结

      js基础知识点总结 如何在一个网站或者一个页面,去书写你的js代码:1.js的分层(功能):jquery(tool) 组件(ui) 应用(app),mvc(backboneJs)2.js的规划() ...