由于ClassLoader的单亲委托结构,保证了JVM中加载的类的安全性。BootstrapClassloader会加载java核心库(例如:java.lang.*等);ExtClassloader会加载jdk安装目录下的ext目录下的jar包(即jdk1.6.0_18\jre\lib\ext),包括dnsns.jar、sunjce_provider.jar...等;AppClassloader会加载当前目录(即'.')和classpath中内容。在加载的过程中,会尽量尝试用父亲去加载,父亲如果不加载,才尝试子Classloader加载。

   自定义Classloader具有相当的实际意义,例如在同一环境下需要多个同一字节码的多个Class模型(Jboss容器中多个应用使用同一类,但彼此隔离,完全没有关系)。

   查看java的源代码,java中的调用关系如下:ClassLoader类的loadClass(String name) -》loadClass(String name, boolean resolve) [会先尝试父亲加载,父亲不加载才ClassLoader加载]-》findClass(String name),而此方法的实现为空,因此自定义的Classloader需要复写findClass(String name)

  1. package org.apache.jmeter.loader; 
  2.  
  3. import java.io.ByteArrayOutputStream; 
  4. import java.io.File; 
  5. import java.io.FileInputStream; 
  6. import java.io.FileNotFoundException; 
  7. import java.io.IOException; 
  8. import java.nio.ByteBuffer; 
  9. import java.nio.channels.Channels; 
  10. import java.nio.channels.FileChannel; 
  11. import java.nio.channels.WritableByteChannel; 
  12.  
  13. /** 
  14.  * TODO Comment of JmeterClassLoader 
  15.  *  
  16.  * @author keju.wangkj 
  17.  */ 
  18. public class JmeterClassLoader extends ClassLoader { 
  19.     private static final String SUFFIX  = ".class"
  20.     private String              baseDir = System.getProperty("user.dir"); 
  21.  
  22.     public JmeterClassLoader() { 
  23.         super(); 
  24.     } 
  25.  
  26.     public JmeterClassLoader(String baseDir) { 
  27.         this.baseDir = baseDir; 
  28.     } 
  29.  
  30.     public JmeterClassLoader(ClassLoader parent, String baseDir) { 
  31.         super(parent); 
  32.         this.baseDir = baseDir; 
  33.     } 
  34.  
  35.     public Class<?> findClass(String className) throws ClassNotFoundException { 
  36.         Class<?> clazz = this.findLoadedClass(className); 
  37.         if (null == clazz) { 
  38.             try { 
  39.                 String classFile = getClassFile(className); 
  40.                 FileInputStream fis = new FileInputStream(classFile); 
  41.                 FileChannel fileC = fis.getChannel(); 
  42.                 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
  43.                 WritableByteChannel outC = Channels.newChannel(baos); 
  44.                 ByteBuffer buffer = ByteBuffer.allocateDirect(1024); 
  45.                 while (true) { 
  46.                     int i = fileC.read(buffer); 
  47.                     if (i == 0 || i == -1) { 
  48.                         break
  49.                     } 
  50.                     buffer.flip(); 
  51.                     outC.write(buffer); 
  52.                     buffer.clear(); 
  53.                 } 
  54.                 fis.close(); 
  55.                 byte[] bytes = baos.toByteArray(); 
  56.  
  57.                 clazz = defineClass(className, bytes, 0, bytes.length); 
  58.             } catch (FileNotFoundException e) { 
  59.                 e.printStackTrace(); 
  60.             } catch (IOException e) { 
  61.                 e.printStackTrace(); 
  62.             } 
  63.         } 
  64.         return clazz; 
  65.     } 
  66.  
  67.     private String getClassFile(String name) { 
  68.         StringBuffer sb = new StringBuffer(baseDir); 
  69.         name = name.replace('.', File.separatorChar) + SUFFIX; 
  70.         sb.append(File.separator + name); 
  71.         return sb.toString(); 
  72.     } 
  73.  
  74.     /* 
  75.      * (non-Javadoc) 
  76.      * @see java.lang.Object#toString() 
  77.      */ 
  78.     @Override 
  79.     public String toString() { 
  80.         return this.getClass().getName(); 
  81.     } 

 其中的findClass()将被classloader类中loadclass方法所调用,所以使用时可以直接调用loadclass方法即可,此为模板方法模式的典型使用。

 2、卸载问题

loader1 = null;

clazz = null;

object = null;