---------- android培训java培训、期待与您交流! ----------

一、概述

  (一)类加载器(class loader

  用来动态加载Java类的工具,它本身也是Java类。

  (二)类加载器作用

  负责加载 Java 类的字节代码到 Java 虚拟机中。

  (三)Java类加载器

  1、Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类加载器负责加载特定位置的类:

  (1)BootStrap(bootstrap class loader):它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自 java.lang.ClassLoader。

  (2)ExtClassLoader(extensions class loader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。

  (3)AppClassLoader(system class loader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader()来获取它。

  2、BootStrap

  类加载器也是Java类,因为其他java类的类加载器本身也要被类加载器加载,显然必须有第一个类加载器不是不是java类,这正是BootStrap。

  3、类加载器演示,代码示例:

 public class ClassLoaderDemo {
public static void main(String[] args) {
System.out.println(
ClassLoaderDemo.class.getClassLoader().getClass().getName()
);//sun.misc.Launcher$AppClassLoader,表示由AppClassLoader加载
System.out.println(System.class.getClassLoader());//null,表示System这个类时由RootStrap加载的
}
}

  (四)类加载器的树状组织结构及管辖范围

  演示类加载器的树状组织结构,代码示例如下:

 public class ClassLoaderTree {
public static void main(String[] args) {
ClassLoader loader = ClassLoaderTree.class.getClassLoader();
while (loader != null) {
System.out.println(loader.toString());
loader = loader.getParent();
}
}
}

二、类加载器的委托机制

  (一)加载类的过程

  当Java虚拟机要加载一个类时,到底要用哪个类加载器加载呢?

  (1)首先,当前线程的类加载器去加载线程中的第一个类。

  (2)若A引用类B(继承或者使用了B),Java虚拟机将使用加载类的类加载器来加载类B。

  (3)还可直接调用ClassLoader的LoaderClass()方法,来指定某个类加载器去加载某个类。

  (二)类加载器的委托

  1、每个类加载器加载类时,又先委托给上级类加载器。

  (1)首先,类加载器发起者一级级向上委托,直至BootStrap;

  (2)从BootStrap加载器开始查找,找到了直接返回,没找到再一级级向下返回让其子级加载器查找;

  (3)一直返回到发起者,发起者再没找到,则抛出ClassNotFoundException,而不再找发起者类加载器的子类来找。

  2、面试题:可不可以自己写一个java.lang.System类呢?

  (1)通常是不可以的,由于类加载器的委托机制,会先将System这个类一级级委托给最顶级的BootStrap,由于BootStrap在其指定的目录中加载的是rt.jar中的类,rt.jar中有System类,那么就会直接加载,而不会去加载自定义的System类。

  (2)但是还是有办法加载自定义的System类的,此时就不能交给上级加载了,需要用自定义的类加载器加载,这就需要有特殊的写法才能去加载这个自定义的System类的。

三、自定义类加载器

  (一)概述

  1、自定义的类加载器必须继承ClassLoader,要覆盖其中的findClass(String name)方法,不用覆盖loadClass()方法。

  2、类加载器的原理

  (1)loadClass()内部会先委托给父级,当父级找不到后返回,再调用findClass(String name)方法,即自定义的类加载器去找。所以只需要覆写findClass方法,就能实现用自定义的类加载器加载类的目的。

  (2)一般自定义类加载器,会把需要加载的类放在自己指定的目录中,而java中已有的类加载器是不知道你这个目录的,所以会找不到。这样才会调用你复写的findClass()方法,用你自定义的类加载器去指定的目录加载类。

  3、模板方法设计模式

  模板方法设计模式,保留了loadClass()方法中的流程(此流程就是先找父级,找不到再调用自定义的类加载器),因此只需覆盖findClass()方法,实现局部细节就行了。

  4、当得到了class文件中的二进制数据,如何将class文件的内容转换成字节码?

  ClassLoader提供了一个protected Class<?> defineClass(String name , byte[] b , int off , int len)方法,只需要将类的class文件传入,就可以将其变为字节码。

  (二)编程步骤

  1、编写一个对文件内容进行简单加密的程序

  2、编写好了一个自己的类加载器,可实现对加密过来的类进行加载和解密。

  3、编写一个程序,调用类加载器加载类,在源程序中不能用该类名定义引用变量,因为编译器无法识别这个类,程序中除了可使用ClassLoader的loadClass方法外,还可以使用设置线程的上下文类加载器或系统类加载器,然后再使用Class.forName。

  (三)编码步骤

  1、对不带包名的class文件进行加密,加密结果存放到另外一个目录,例如: java MyClassLoader MyTest.class F:\itcast

  2、运行加载类的程序,结果能够被正常加载,但打印出来的类装载器名称为AppClassLoader:java MyClassLoader MyTest F:\itcast

  3、用加密后的类文件替换CLASSPATH环境下的类文件,再执行上一步操作就出问题了,错误说明是AppClassLoader类装载器装载失败。

  4、删除CLASSPATH环境下的类文件,再执行上一步操作就没问题了。

  (四)自定义类加载器,代码实现(张孝祥老师讲解)

  1、定义一个测试类:ClassLoaderAttachment

 // 定义一个测试类,继承Date,用于加载
import java.util.Date;
public class ClassLoaderAttachment extends Date{
public String toString(){
return " hello,itcast";
}
}

  2、自定义类加载器:MyClassLoader,继承ClassLoader,覆盖findClass()方法。

 import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class MyClassLoader extends ClassLoader{
public static void main(String[] args) throws Exception {
String srcPath = args[0];
String destDir = args[1];
FileInputStream fis = new FileInputStream(srcPath);
String destFileName = srcPath.substring(srcPath.lastIndexOf("\\")+1);
String destFilePath = destDir+"\\"+destFileName;
FileOutputStream fos = new FileOutputStream(destFilePath);
cypher(fis,fos);//加密class字节码
fis.close();
fos.close();
}
//加密方法
private static void cypher(InputStream ips,OutputStream ops) throws Exception{
int b = -1;
while((b = ips.read())!=-1){
ops.write(b^0xff);
}
} private String classDir; @Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String classFileName = classDir + "\\" + name.substring(name.lastIndexOf('.')+1) + ".class";
try {
FileInputStream fis = new FileInputStream(classFileName);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
cypher(fis,bos);//解密
fis.close();
System.out.println("aaa");
byte[] bytes = bos.toByteArray();
return defineClass(bytes, 0, bytes.length);
} catch (Exception e) {
e.printStackTrace();
}
return null;
} public MyClassLoader(){}
public MyClassLoader(String classDir){
this.classDir = classDir;
}
}

  3、定义类加载测试类:ClassLoaderTest,测试自定义的类加载器

 import java.util.Date;
public class ClassLoaderTest {
public static void main(String[] args) throws Exception {
Class clazz = new MyClassLoader (" itcastlib " ) . loadClass ( " cn.itcast . day2 . ClassLoaderAttachment " ) ;
Date d1 = (Date)clazz.newInstance();
System.out.println(d1);
}
}

---------- android培训java培训、期待与您交流! ----------

黑马程序员——【Java高新技术】——类加载器的更多相关文章

  1. 【黑马18期Java毕业生】黑马程序员Java全套资料+视频+工具

        Java学习路线图引言:        黑马程序员:深知广大爱好Java的人学习是多么困难,没视频没资源,上网花钱还老被骗. 为此我们历时一个月整理这套Java学习路线图,不管你是不懂电脑的小 ...

  2. 黑马程序员_高新技术之javaBean,注解,类加载器

    ----------- android培训.java培训.java学习型技术博客.期待与您交流! ---------- 第一部分 javaBean 一,由内省引出javaBean 1,内省: 内省对应 ...

  3. java高新技术-类加载器

    1.类加载器及委托机制的深入分析 > 类加载器的作用:一个java文件中的出现的类,首先要把这个类的字节码加载到内存中,这个类的信息放在硬盘的classPath下的class文件中,  把cla ...

  4. 黑马程序员——Java高级应用(一)

    ------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS ...

  5. 黑马程序员Java基础班+就业班课程笔记全发布(持续更新)

    正在黑马学习,整理了一些课程知识点和比较重要的内容分享给大家,也是给自己拓宽一些视野,仅供大家交流学习,大家有什么更好的内容可以发给我 ,现有黑马教程2000G  QQ 1481135711 这是我总 ...

  6. 黑马程序员----java基础笔记中(毕向东)

    <p>------<a href="http://www.itheima.com" target="blank">Java培训.Andr ...

  7. 黑马程序员——JAVA基础之泛型和通配符

    ------- android培训.java培训.期待与您交流! ---------- 泛型:            JDK1.5版本以后出现新特性.用于解决安全问题,是一个类型安全机制. 泛型好处: ...

  8. 黑马程序员——JAVA基础之简述面向对象,类,变量,匿名对象

    ------- android培训.java培训.期待与您交流! ---------- 面向对象: 面向对象是相对面向过程而言 面向对象和面向过程都是一种思想 面向过程 强调的是功能行为 面向对象 将 ...

  9. 黑马程序员——JAVA基础之语法、命名规则

    ------- android培训.java培训.期待与您交流! ---------- 1.java语言组成:关键字,标识符,注释,常量和变量,运算符,语句,函数,数组. 2.java关键字:被Jav ...

  10. 黑马程序员——JAVA基础之反射

      ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! -------     Java 反射是Java语言的一个很重要的特征,它使得Java具体了"动态 ...

随机推荐

  1. JavaWeb前端:CSS

    CSS 主要是要熟悉的掌握选择器 Div 的盒模型: 整个网页被切割成一个一个盒子,盒子可以套盒子,每个盒子通过以下几个主要属性来控制显示位置: 边框 Border-top, Border-botto ...

  2. BIEE 10g 二次开发整理

    近半年在公司做某个项目的时候,主要使用到了Oracle BIEE 10g这套工具.刚开始的时候,对OBIEE是七窍通了六窍,还是一窍不通. 现在已经摸索出些许门道,特整理出来:一来,备忘:二来,供大家 ...

  3. JAVA OO 第二章知识点

    一.JAVA的基础语法 1.关键字 ①关键字:关键字用于定义该门语言,且这些单词对编译器用特殊的含义,而且不能作为标识符. 2.标识符 标识符:在JAVA中我们备选的单词,包括:类名.方法名.字段.变 ...

  4. 斐讯k1路由器刷Breed BootLoader(不死UBoot)教程

    刷入Breed BootLoader: 因为这个K1路由器可以开启telnet服务,所以此处刷Breed可以不使用编程器刷Flash芯片的方法进行. 1.打开K1路由器的Telnet服务. 电脑通过有 ...

  5. C指针的大小

    应该说这是一个非常基础的问题,教科书上说指针大小和机器字长相同,即32位机指针长度为4字节!但是对不对呢?为什么是这样? 搜了一下相关资料...居然发现回答不统一,很多人也同样是糊里糊涂. 下面对这个 ...

  6. Balanced Binary Tree [LeetCode]

    Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced binary ...

  7. jquery1:

    在jquery中:1.window.onload: --->$();所以一般jquery用如下开头: $(function(){ })2.获取元素:$('#div'):获取id为div的元素$( ...

  8. 关于rem的学习

    网页常见单位px.em.rem:其中rem是css3新出的单位,官网是这样定义的:“font size of the root element”,意思是:相对长度单位,相对于根元素(即html元素)f ...

  9. linux 下 PHP Notice: session_start(): ps_files_cleanup_dir 报错 问题剖析

    如果在ubuntu/Debian下, 采用apt安装的PHP, 那么在使用Session的时候, 就可能会有小概率遇到这个提示. 代码如下: PHP Notice: session_start(): ...

  10. MySQL 5.6查询优化器新特性的“BUG” eq_range_index_dive_limit

    本文转自 http://www.imysql.cn 最近碰到一个慢SQL问题,解决过程有点小曲折,和大家分享下. SQL本身不复杂,表结构.索引也比较简单,不过个别字段存在于多个索引中. CREATE ...