黑马程序员--类加载器小结

---------------------- 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 

你可能感兴趣的:(heima,java,classloader,string,exception,虚拟机,class)