黑马程序员--类加载器小结,黑马程序员--小结
黑马程序员--类加载器小结,黑马程序员--小结
---------------------- android培训、java培训、期待与您交流! ----------------------
类加载器基本概念
顾名思义,类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成java.lang.Class
类的一个实例。每个这样的实例用来表示一个 Java 类。通过此实例的newInstance()
方法就可以创建出该类的一个对象。实际的情况可能更加复杂,比如
Java 字节代码可能是通过工具动态生成的,也可能是通过网络下载的。
基本上所有的类加载器都是 java.lang.ClassLoader
类的一个实例。
Java 中的类加载器大致可以分成两类,一类是系统提供的,另外一类则是由 Java 应用开发人员编写的。系统提供的类加载器主要有下面三个:
- 引导类加载器(bootstrap class loader):它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自
java.lang.ClassLoader
。 - 扩展类加载器(extensions class loader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。
- 系统类加载器(system class loader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过
ClassLoader.getSystemClassLoader()
来获取它。
除了系统提供的类加载器以外,开发人员可以通过继承 java.lang.ClassLoader
类的方式实现自己的类加载器,以满足一些特殊的需求。
加载类的过程
完成类的加载工作是通过调用 defineClass
来实现的;而启动类的加载过程是通过调用 loadClass
来实现的。前者称为一个类的定义加载器(defining loader),后者称为初始加载器(initiating loader)。在 Java 虚拟机判断两个类是否相同的时候,使用的是类的定义加载器。也就是说,哪个类加载器启动类的加载过程并不重要,重要的是最终定义这个类的加载器。两种类加载器的关联之处在于:一个类的定义加载器是它引用的其它类的初始加载器。如类com.example.Outer
引用了类 com.example.Inner
,则由类 com.example.Outer
的定义加载器负责启动类com.example.Inner
的加载过程。
方法 loadClass()
抛出的是 java.lang.ClassNotFoundException
异常;方法defineClass()
抛出的是java.lang.NoClassDefFoundError
异常。
类加载器在成功加载某个类之后,会把得到的 java.lang.Class
类的实例缓存起来。下次再请求加载该类的时候,类加载器会直接使用缓存的类的实例,而不会尝试再次加载。也就是说,对于一个类加载器实例来说,相同全名的类只加载一次,即loadClass
方法不会被重复调用。
如何自定义一个类加载器
基本原则 定一个类,继承ClassLoader, 复写该类的findClass()方法。
package cn.itcast.day1;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class MyClassLoader extends ClassLoader {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
//ClassLoaderDemo cld = new ClassLoaderDemo();
//System.out.println(cld);
String srcPath = args[0];
String destDir = args[1];
FileInputStream fis = new FileInputStream(srcPath);
String destFileName = srcPath.substring(srcPath.lastIndexOf("\\")+1);
String destPath = destDir+"\\"+destFileName;
//String destFileName =
FileOutputStream fos = new FileOutputStream(destPath);
encrypt(fis,fos);
//fis.close();
//fos.close();
}
public static void encrypt(InputStream is, OutputStream os) throws Exception
{
int b = -1;
while((b=is.read())!= -1)
{
os.write((byte)b ^ 0xff);
}
}
private String classDir;
public MyClassLoader() {
}
public MyClassLoader(String classDir) {
this.classDir = classDir;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
// TODO Auto-generated method stub
String classFileName = classDir +"\\"+name+".class";
try {
FileInputStream fis = new FileInputStream(classFileName);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
encrypt(fis,baos);
byte[] bytes = baos.toByteArray();
return defineClass(bytes, 0, bytes.length);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
//encrypt(is,os);
return super.findClass(name);
}
---------------------- android培训、java培训、期待与您交流! ----------------------
详细请查看:http://edu.csdn.net/heima
相关文章
- 暂无相关文章
用户点评