Java ClassLoader学习三:自定义ClassLoader

一.自定义ClassLoader关键

  1. 是继承ClassLoader还是继承URLClassLoader。
      1. 如果你的class文件存放于一个JAR文件里,同时你需要一些自己的load策略,可以考虑继承URLClassLoader。
      2. 如果你的class文件位于其它地方,继承ClassLoader。比喻位于普通文件夹里,可以自定义一个JyzClassLoader;如果位于网络上,可以定义一个NetworkClassLoaer,等等。
             class NetworkClassLoader extends ClassLoader {
                 String host;
                 int port;
        
                 public Class findClass(String name) {
                     byte[] b = loadClassData(name);
                     return defineClass(name, b, 0, b.length);
                 }
        
                 private byte[] loadClassData(String name) {
                     // load the class data from the connection
                      . . .
                 }
             }
  2. 重写findClass方法。

二.JyzClassLoader

 

package com.jyz.study.jdk.classLoader;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;
import java.util.Arrays;

/**
 * 自定义ClassLoader
 * @author [email protected]
 * 
 */
public class JyzClassLoader extends ClassLoader {

	private String classPath;

	public JyzClassLoader(String classPath) {
		this.classPath = classPath;
	}

	@Override
	protected Class<?> findClass(String className)
			throws ClassNotFoundException {
		byte[] bytes = loadClassData(className);
		Class<?> clazz = defineClass(className, bytes, 0, bytes.length);
		fillSigners(clazz);
		return clazz;
	}
	
	//测试ClassLoader setSigners的用法
	private void fillSigners(Class<?> clazz){
		Object[] singers = new Object[1];
		singers[0] = "[email protected]";
		this.setSigners(clazz, singers);
	}

	private byte[] loadClassData(String className)
			throws ClassNotFoundException {
		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();
			return baos.toByteArray();
		} catch (IOException fnfe) {
			throw new ClassNotFoundException(className);
		}
	}

	private String getClassFile(String name) {
		StringBuffer sb = new StringBuffer(classPath);
		sb.append(File.separator).append(name.replace('.', File.separatorChar)).append(".class");
		return sb.toString();
	}

	public static void main(String[] args) {
		try {
			JyzClassLoader classLoader = new JyzClassLoader("D:\\GoogleCode\\platform-components\\trunk\\SourceCode\\component-core\\target\\classes");
			Class<?> clazz = classLoader.loadClass("com.jyz.component.core.collection.Tuple");
			
			JyzClassLoader classLoader2 = new JyzClassLoader("D:\\GoogleCode\\platform-components\\trunk\\SourceCode\\component-core\\target\\classes");
			Class<?> clazz2 = classLoader2.loadClass("com.jyz.component.core.collection.Tuple");
			
			System.out.println(clazz == clazz2);//return false
			System.out.println(clazz.equals(clazz2));//return false
			
			System.out.println("c1.getSigners is " + Arrays.toString(clazz.getSigners()));
			System.out.println(clazz.newInstance());
			System.out.println(Arrays.toString(classLoader.getPackages()));
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		}

	}

}



console output:
false
false
c1.getSigners is [[email protected]]
Tuple[t1:null, t2:null]
[package java.util.jar, Java Platform API Specification, version 1.6, package java.nio.channels, Java Platform API Specification, version 1.6, package java.util, Java Platform API Specification, version 1.6, package sun.util, Java Platform API Specification, version 1.6, package java.net, Java Platform API Specification, version 1.6, package sun.reflect.misc, Java Platform API Specification, version 1.6, package sun.security.provider, Java Platform API Specification, version 1.6, package sun.net.www.protocol.jar, Java Platform API Specification, version 1.6, package sun.security.action, Java Platform API Specification, version 1.6, package java.nio.charset, Java Platform API Specification, version 1.6, package sun.io, Java Platform API Specification, version 1.6, package java.io, Java Platform API Specification, version 1.6, package sun.nio, Java Platform API Specification, version 1.6, package sun.net.www, Java Platform API Specification, version 1.6, package java.util.zip, Java Platform API Specification, version 1.6, package java.lang.ref, Java Platform API Specification, version 1.6, package java.lang, Java Platform API Specification, version 1.6, package sun.misc, Java Platform API Specification, version 1.6, package sun.net.www.protocol.file, Java Platform API Specification, version 1.6, package java.util.concurrent, Java Platform API Specification, version 1.6, package java.util.concurrent.atomic, Java Platform API Specification, version 1.6, package java.nio.charset.spi, Java Platform API Specification, version 1.6, package java.nio.channels.spi, Java Platform API Specification, version 1.6, package java.nio, Java Platform API Specification, version 1.6, package java.util.concurrent.locks, Java Platform API Specification, version 1.6, package java.security, Java Platform API Specification, version 1.6, package sun.reflect, Java Platform API Specification, version 1.6, package java.lang.reflect, Java Platform API Specification, version 1.6, package sun.nio.cs, Java Platform API Specification, version 1.6, package sun.security.util, Java Platform API Specification, version 1.6, package sun.nio.cs.ext, package com.jyz.study.jdk.classLoader, package java.security.cert, Java Platform API Specification, version 1.6, package sun.nio.ch, Java Platform API Specification, version 1.6, package sun.net.util, Java Platform API Specification, version 1.6, package sun.jkernel, Java Platform API Specification, version 1.6]

 

三.再来说说laodClass

      http://zy19982004.iteye.com/blog/1983240里文字解释了一下loadClass的过程。下面debug一下。

      进入点Class<?> clazz = classLoader.loadClass("com.jyz.component.core.collection.Tuple");

  1. JyzClassLoader委派给AppClassLoader,AppClassLoader委派给ExtClassLoader,ExtClassLoader委派给BootstrapLoader,BootstrapLoader找不到,ExtClassLoader自己去找。想想为什么JyzClassLoader会委派给AppClassLoader?参考http://zy19982004.iteye.com/blog/1983240。Java ClassLoader学习三:自定义ClassLoader_第1张图片
  2. ExtClassLoader找不到,AppClassLoader自己去找。Java ClassLoader学习三:自定义ClassLoader_第2张图片
  3. AppClassLoader找不到J,yzClassLoader自己去找。Java ClassLoader学习三:自定义ClassLoader_第3张图片

你可能感兴趣的:(ClassLoader)