ClassLoader机制分析与自制加解、密类加载器

参考

张孝详系列

深入理解JVM机制 - 周志明

场景

ClassLoader机制 ? 由下及上委托,上面没有再往下,直到自身(自身没有目标类,就抛ClassNotFoundException,不用子类类加载器)

 1、AppClassLoader:加载ClassPath目录下的.class文件
 2、ExtClassLoader:加载~/jre/lib/ext.jar中的.class文件
 3、Bootstrap:加载 ~/jre/lib/rt.jar中的.class文件(eg、System,String,Object等类)

实验

package cool.pengych.java.classloader;
import java.util.Date;
/**
 * ClassLoader 分析
 * @author pengyucheng
 * 
 * 一、认识类加载器
 * JDK自带内加载器
 * AppClassLoader => ExtClassLoader => Bootstrap用(C++写的二进制代码,同JVM启动时被加入内存)
 * 1、AppClassLoader:加载ClassPath目录下的.class文件
 * 2、ExtClassLoader:加载~/jre/lib/ext.jar中的.class文件
 * 3、Bootstrap:加载 ~/jre/lib/rt.jar中的.class文件(eg、System,String,Object等类)
 *二、类加载器工作机制
 *由下及上委托,上面没有再往下,直到自身(自身没有目标类,就抛ClassNotFoundException,不用子类类加载器)
 *三、自定义类加载器
 *  className extends java.lang.ClassLoader
 *  应用
 */
public class ClassLoader
{
	public static void main(String[] args) throws Exception
	{
		System.out.println(ClassLoader.class.getClassLoader().getClass().getName());// sun.misc.Launcher$AppClassLoader
		System.out.println(System.class.getClassLoader());// null :BootStrap 类加载器不是java类,这里返回null是合理的
		
		java.lang.ClassLoader loader = ClassLoader.class.getClassLoader();
		while(null != loader)
		{
			System.out.println(loader.getClass().getName());
			loader = loader.getParent();
		}
		System.out.println(loader);
		/*
		 *  执行结果
		 *  sun.misc.Launcher$AppClassLoader
		 * sun.misc.Launcher$ExtClassLoader
		 * null
		 */
		System.out.println(new ClassLoaderAttachment());
		Class clazz = new MyClassLoader("//home//pengyucheng//eclipse//java//bin/cool//pengych//java//classloader").loadClass("ClassLoaderAttachment");
		Date d1 = (Date) clazz.newInstance();
		System.out.println(d1);
	}
}
package cool.pengych.java.classloader;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
 * 自定义类加载器
 * @author pengyucheng
 */
public class MyClassLoader extends java.lang.ClassLoader // 继承 ClassLoader
{
	public static void main(String[] args)  
	{
		String srcPath = args[0];
		String desDir = args[1];
		String desFileName = srcPath.substring(srcPath.lastIndexOf("//") + 1);
		InputStream ips;
		OutputStream ops;
		try
		{
			ips = new FileInputStream(srcPath);
			ops = new FileOutputStream(desDir+desFileName);
			encryt(ips,ops);
			 ips.close();
			ops.close();
		} 
		catch (FileNotFoundException e)
		{
			e.printStackTrace();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}
	/**
	 *  对输入流中的字节数据取反
	 */
	public static void encryt(InputStream ips, OutputStream ops) throws IOException
	{
		int b = -1;
		while ((b = ips.read()) != -1) 
		{
			ops.write(b ^ 0xff);
		}
	}
	private String classDir;
	public  MyClassLoader()
	{
		// TODO Auto-generated constructor stub
	}
	public  MyClassLoader(String classDir)
	{
		this.classDir = classDir;
	}
	
	
	@Override
	protected Class<?> findClass(String name) 
	{
		String classFileName = classDir + "//" + name + ".class";
		try
		{
			InputStream is = new FileInputStream(classFileName);
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			encryt(is,bos);
			is.close();
			byte[] bytes = bos.toByteArray();
			bos.close();
			return defineClass(bytes,0,bytes.length);
		}
		catch ( IOException e) 
		{
			e.printStackTrace();
		}
		return null;
	}
}
package cool.pengych.java.classloader;
import java.util.Date;
/**
 * @author pengyucheng
 * 自定义类加载器测试用实例
 */
public class ClassLoaderAttachment extends Date
{
	private static final long serialVersionUID = 1L;

	public ClassLoaderAttachment() {
		// TODO Auto-generated constructor stub
	}
	@Override
	public  String toString()
	{
		return "just for fun";
	}
}

总结

一、JDK自带三种类加载器:AppClassLoader、ExtClassLoader及Bootstrap。

二、自制类加载器需继承java.lang.ClassLoader , 重写 findClass方法。可自定义加载类的行为。eg、加载前后可以对类的字节码进行加解密。

你可能感兴趣的:(ClassLoader机制分析与自制加解、密类加载器)