java 类加载器的委托机制
l 当Java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢?
1.首先当前线程的类加载器去加载线程中的第一个类。
2.如果类A中引用了类B,Java虚拟机将使用加载类A的类装载器来加载类B。
3.还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。
l 每个类加载器加载类时,又先委托给其上级类加载器。
1.当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛ClassNotFoundException,不是再去找发起者类加载器的儿子,因为没有getChild方法,即使有,那有多个儿子,找哪一个呢?
2.对着类加载器的层次结构图和委托加载原理,解释先前将ClassLoaderTest输出成jre/lib/ext目录下的itcast.jar包中后,运行结果为ExtClassLoader的原因。
每个ClassLoader本身只能分别加载特定位置和目录中的类,但它们可以委托其他的类装载器去加载类,这就是类加载器的委托模式。类装载器一级级委托到BootStrap类加载器,当BootStrap无法加载当前所要加载的类时,然后才一级级回退到子孙类装载器去进行真正的加载。当回退到最初的类装载器时,如果它自己也不能完成类的装载,那就应报告ClassNotFoundException异常。
有一道面试,能不能自己写个类叫java.lang.System,为了不让我们写System类,类加载采用委托机制,这样可以保证爸爸们优先,也就是总是使用爸爸们能找到的类,这样总是使用java系统提供的System。
把先前编写的类加入到jdk的rt.jar中,会有怎样的效果呢?不行!!!看来是不能随意将自己的class文件加入进rt.jar文件中的。
编写自己的类加载器(需要再仔细看一遍,不是太懂)
知识讲解:
自定义的类加载器的必须继承ClassLoader
loadClass方法(直接继承,省去委托机制的编写)与findClass方法(覆盖这个就行了)
defineClass方法
编程步骤:
编写一个对文件内容进行简单加密的程序。
编写了一个自己的类装载器,可实现对加密过的类进行装载和解密。
编写一个程序调用类加载器加载类,在源程序中不能用该类名定义引用变量,因为编译器无法识别这个类。程序中可以除了使用ClassLoader.load方法之外,还可以使用设置线程的上下文类加载器或者系统类加载器,然后再使用Class.forName。
实验步骤:
对不带包名的class文件进行加密,加密结果存放到另外一个目录,例如: java MyClassLoader MyTest.class F:\itcast
运行加载类的程序,结果能够被正常加载,但打印出来的类装载器名称为AppClassLoader:java MyClassLoader MyTest F:\itcast
用加密后的类文件替换CLASSPATH环境下的类文件,再执行上一步操作就出问题了,错误说明是AppClassLoader类装载器装载失败。
删除CLASSPATH环境下的类文件,再执行上一步操作就没问题了。
import java.io.*;
import java.lang.reflect.*;
public class MyClassLoader extends ClassLoader
{
private String path = null;
public MyClassLoader(String path) throws Exception//检查文件是否存在
{
File f = new File(path);
if(!f.isDirectory())
{
throw new RuntimeException(path + " is not a directory");
}
this.path = path;
}
public Class findClass(String name) //throws Exception //为什么不能抛出
{
try
{
File f = new File(path,name.substring(name.lastIndexOf('.')+1) + ".class");
FileInputStream fis = new FileInputStream(f);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
cypher(fis,bos);
byte [] buf = bos.toByteArray();
fis.close();
bos.close();
return defineClass(name,buf,0,buf.length);
}catch(Exception e)
{
throw new ClassNotFoundException(name + " is not found!");
}
return null;
}
public static void cypher(InputStream istream,OutputStream ostream) throws Exception
{
//下面这段代码可能遇到255的字节,当成byte就成了-1
/*byte b = 0;
while((b = (byte)istream.read()) != -1)
{
ostream.write(b ^ 0xff);
}*/
int b = 0;
while((b = istream.read()) != -1)
{
ostream.write(((byte)b) ^ 0xff);
}
}
public static void main(String [] args) throws Exception
{
//下面省略了错误检查
if(!args[0].endsWith("class"))
{
ClassLoader loader = new MyClassLoader(args[1]);
Class cls = loader.loadClass(args[0]);
/*
让自定义类继承Date类
System.out.println(cls.getClassLoader().getClass().getName());
java.util.Date d = (java.util.Date)cls.newInstance();
System.out.println(d.toString());
*/
//Method m = cls.getMethod("test",null);//在jdk1.5中报警告,为什么?
Method m = cls.getMethod("test");
//m.invoke(cls.newInstance(),null);
m.invoke(cls.newInstance());
//((Test)cls.newInstance()).test();
return;
}
else
{
FileInputStream fis = new FileInputStream(args[0]);
File f = new File(args[1], new File(args[0]).getName());//不用检查目录最后是否有目录分割符
FileOutputStream fos = new FileOutputStream(f);
cypher(fis,fos);
fis.close();
fos.close();
}
}
}
//类加载器不能加载这种非public的类
/*
Exception in thread "main" java.lang.IllegalAccessException: Class MyClassLoader
can not access a member of class MyTest with modifiers ""
*/
/*
class MyTest
{
public void test()
{
System.out.println("hello,www.it315.org");
}
}
*/
java 类加载器的委托机制的更多相关文章
- java类加载器及其委托机制
1.什么是类加载器,类加载器父子结构.BootStrap-->ExtClassLoader-->AppClassLoader,级别依次降低 2.类加载器之间的父子关系和管辖范围 3.类加载 ...
- java类加载器-系统类加载器
系统类加载器 系统类加载器可能都耳详能熟,但是为了完整点,还是先简单的说说系统的类加载器吧. public class Test { public static void main(String[] ...
- Java 类加载器(转)
java虚拟机中可以安装多个类加载,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap(内嵌在java虚拟机中由C++编写),ExtClassLoader,AppClassLoa ...
- Java基础-类加载机制与自定义类Java类加载器(ClassLoader)
Java基础-类加载机制与自定义类Java类加载器(ClassLoader) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 关于类加载器的概念和分类我就不再废话了,因为我在之前的笔 ...
- java笔记--理解java类加载器以及ClassLoader类
类加载器概述: java类的加载是由虚拟机来完成的,虚拟机把描述类的Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成能被java虚拟机直接使用的java类型,这就是虚拟机的类加载机制 ...
- java类加载器深入研究
看了下面几篇关于类的加载器的文章,豁然开朗.猛击下面的地址开始看吧. Java类加载原理解析 深入探讨 Java 类加载器 分析BootstrapClassLoader/ExtClassLo ...
- 深入探讨 Java 类加载器
转自:http://www.ibm.com/developerworks/cn/java/j-lo-classloader/ 类加载器(class loader)是 Java™中的一个很重要的概念.类 ...
- JAVA 类加载器 第14节
JAVA 类加载器 第14节 今天我们将类加载机制5个阶段中的第一个阶段,加载,又叫做装载.为了阅读好区分,以下都叫做装载. 装载的第一步就是要获得二进制的字节流,它可以从读.class文件获得,也可 ...
- 深入探讨 Java 类加载器[转]
原文地址:http://www.ibm.com/developerworks/cn/java/j-lo-classloader/index.html 类加载器(class loader)是 Java™ ...
随机推荐
- 【风马一族_Android】无线连接|调试Android手机
原文来自:http://www.cnblogs.com/sows/p/6269396.html (博客园的)风马一族 侵犯版本,后果自负 2017-01-10 15:03:31 准备阶段 1. 软 ...
- Python PEP8标准
1.编码 如无特殊情况,文件一律使用utf-8编码 如无特殊情况,文件头部必须添加# -*- coding:utf-8 -*- 标志 2.代码 统一使用四个空格缩进 每行代码不超过80个字符 自然语言 ...
- Docker数据管理-数据卷 data volumes和数据卷容器data volumes containers的使用详解
此文来源于:https://yq.aliyun.com/ziliao/43471 参考原文件之外,做了些修改. Volume数据卷是Docker的一个重要概念.数据卷是可供一个或多个容器使用的特殊目录 ...
- day3-转自金角大王
本节内容 1. 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数 温故知新 1. 集合 主要作用: 去重 关系测 ...
- 【风马一族_php】PHP运算
运算 算术运算符 <?php //加法 $num1 = 10; $num2 = 43; echo $num1 + $num2; echo " "; var_dump($num ...
- js赋值符号“=”的小例子
var obj1={x:5}; var obj2=obj1; obj1.a=obj1={x:6}; console.log(obj1.a); console.log(obj2.a); 为什么obj1. ...
- VIM中空格和TAB的替换
在.vimrc中添加以下代码后,重启vim即可实现按TAB产生4个空格:set ts=4 (注:ts是tabstop的缩写,设TAB宽4个空格)set expandtab 对于已保存的文件,可以使用 ...
- 微信小程序云数据库——where查询和doc查询区别
用法 条件查询where 我们也可以一次性获取多条记录.通过调用集合上的 where 方法可以指定查询条件,再调用 get 方法即可只返回满足指定查询条件的记录,比如获取用户的所有未完成的待办事项,用 ...
- Git同步Python代码
之前我们都是将代码保存到本地目录, 然后再上传到Git中,但如果针对在pycharm中的代码,就要换另一种方式了,下面简单介绍一下. 1.打开pycharm主界面,选择菜单栏VCS---checkou ...
- UDP传输对象--JavaSE考试题
Server.java package com.sxt.udp.object; import java.io.ByteArrayInputStream; import java.io.ObjectIn ...