java 自定义类的加载器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 自定义类的加载器相关的知识,希望对你有一定的参考价值。


首先介绍自定义类的应用场景:

(1)加密:Java代码可以轻易的被反编译,如果你需要把自己的代码进行加密以防止反编译,可以先将编译后的代码用某种加密算法加密,类加密后就不能再用Java的ClassLoader去加载类了,这时就需要自定义ClassLoader在加载类的时候先解密类,然后再加载。

(2)从非标准的来源加载代码:如果你的字节码是放在数据库、甚至是在云端,就可以自定义类加载器,从指定的来源加载类。

(3)以上两种情况在实际中的综合运用:比如你的应用需要通过网络来传输 Java 类的字节码,为了安全性,这些字节码经过了加密处理。这个时候你就需要自定义类加载器来从某个网络地址上读取加密后的字节代码,接着进行解密和验证,最后定义出在Java虚拟机中运行的类。

package com.test6;

public class DataInfo {

	private Long id;

	private String userName;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	@Override
	public String toString() {
		return "DataInfo [id=" + 1 + ", userName=" + "测试" + "]";
	}

}
package com.test6;

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

/**
 * 自定义加载器
 * 
 * @author sdc
 *
 */
public class MySelfClassLoader extends ClassLoader {

	public MySelfClassLoader() {

	}

	public MySelfClassLoader(ClassLoader parent) {
		super(parent);
	}

	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		File file = new File("D:/DataInfo.class");

		try {
			byte[] bytes = getClassBytes(file);
			// defineClass方法可以把二进制流字节组成的文件转换为一个java.lang.Class
			Class<?> cla = this.defineClass(name, bytes, 0, bytes.length);
			return cla;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return super.findClass(name);
	}

	private byte[] getClassBytes(File file) throws Exception {
		// 这里要读入.class的字节,因此要使用字节流
		FileInputStream fis = new FileInputStream(file);
		FileChannel fc = fis.getChannel();
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		WritableByteChannel wbc = Channels.newChannel(baos);
		ByteBuffer by = ByteBuffer.allocate(1024);

		while (true) {
			int i = fc.read(by);
			if (i == 0 || i == -1)
				break;
			by.flip();
			wbc.write(by);
			by.clear();
		}
		fis.close();
		return baos.toByteArray();
	}

	public static void main(String[] args) {

		MySelfClassLoader mcl = new MySelfClassLoader();
		Class<?> clazz;
		try {
			clazz = Class.forName("DataInfo", true, mcl);
			Object obj = clazz.newInstance();

			System.out.println(obj);
			System.out.println(obj.getClass().getClassLoader());// 打印出我们的自定义类加载器
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}


本文出自 “10093778” 博客,请务必保留此出处http://10103778.blog.51cto.com/10093778/1923781

以上是关于java 自定义类的加载器的主要内容,如果未能解决你的问题,请参考以下文章

28 Java类的加载机制什么是类的加载类的生命周期加载:查找并加载类的二进制数据连接初始化类加载器双亲委派模型自定义类加载器

Java自定义类加载和ClassPath类加载器

深入理解Java虚拟机——类加载器

深入理解Java虚拟机——类加载器

用户自定义类加载器及具体实现

用户自定义类加载器及具体实现