由于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)。
- package org.apache.jmeter.loader;
-
- import java.io.ByteArrayOutputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.IOException;
- import java.nio.ByteBuffer;
- import java.nio.channels.Channels;
- import java.nio.channels.FileChannel;
- import java.nio.channels.WritableByteChannel;
-
-
-
-
-
-
- public class JmeterClassLoader extends ClassLoader {
- private static final String SUFFIX = ".class";
- private String baseDir = System.getProperty("user.dir");
-
- public JmeterClassLoader() {
- super();
- }
-
- public JmeterClassLoader(String baseDir) {
- this.baseDir = baseDir;
- }
-
- public JmeterClassLoader(ClassLoader parent, String baseDir) {
- super(parent);
- this.baseDir = baseDir;
- }
-
- public Class<?> findClass(String className) throws ClassNotFoundException {
- Class<?> clazz = this.findLoadedClass(className);
- if (null == clazz) {
- try {
- String classFile = getClassFile(className);
- FileInputStream fis = new FileInputStream(classFile);
- FileChannel fileC = fis.getChannel();
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- WritableByteChannel outC = Channels.newChannel(baos);
- ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
- while (true) {
- int i = fileC.read(buffer);
- if (i == 0 || i == -1) {
- break;
- }
- buffer.flip();
- outC.write(buffer);
- buffer.clear();
- }
- fis.close();
- byte[] bytes = baos.toByteArray();
-
- clazz = defineClass(className, bytes, 0, bytes.length);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- return clazz;
- }
-
- private String getClassFile(String name) {
- StringBuffer sb = new StringBuffer(baseDir);
- name = name.replace('.', File.separatorChar) + SUFFIX;
- sb.append(File.separator + name);
- return sb.toString();
- }
-
-
-
-
-
- @Override
- public String toString() {
- return this.getClass().getName();
- }
- }
其中的findClass()将被classloader类中loadclass方法所调用,所以使用时可以直接调用loadclass方法即可,此为模板方法模式的典型使用。
2、卸载问题
loader1 = null;
clazz = null;
object = null;
本文转自 tianya23 51CTO博客,原文链接:http://blog.51cto.com/tianya23/640743,如需转载请自行联系原作者