package com.softmax.basic.jvm.sample; import java.io.*; import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.WritableByteChannel; /** * 自定义类加载器 * * @author Jarvis * @date 2018/8/20 */ public class MyClassLoader extends ClassLoader { private String fileName; public MyClassLoader(String fileName) { this.fileName = fileName; } public MyClassLoader(ClassLoader loader) { super(loader); } /** * Finds the class with the specified <a href="#name">binary name</a>. * This method should be overridden by class loader implementations that * follow the delegation model for loading classes, and will be invoked by * the {@link #loadClass loadClass} method after checking the * parent class loader for the requested class. * * @param name The <a href="#name">binary name</a> of the class * @return The resulting {@code Class} object * @throws ClassNotFoundException If the class could not be found * @implSpec The default implementation throws {@code ClassNotFoundException}. * @since 1.2 */ @Override protected Class<?> findClass(String name) throws ClassNotFoundException { File file = getClassFile(); try { byte[] bytes = getClassBytes(file); Class<?> cls = this.defineClass(name, bytes, 0, bytes.length); return cls; } catch (IOException e) { e.printStackTrace(); } return super.findClass(name); } private File getClassFile() { File file = new File(this.fileName); return file; } /** * 读入.class的字节,因此要使用字节流 * * 一个Buffer对象是固定数量的数据的容器。其作用是一个存储器,或者分段运输区,在这里数据可被存储并在之后用于检索。 * * 尽管缓冲区作用于它们存储的原始数据类型,但缓冲区十分倾向于处理字节。 * NIO里,一个通道(channel)可以表示任何可以读写的对象。它的作用是为文件和套接口提供抽象 * * @param file * @return * @throws IOException */ private byte[] getClassBytes(File file) throws IOException { FileInputStream inputStream = new FileInputStream(file); //通道(Channel)是一种途径,借助该途径,可以用最小的总开销来访问操作系统本身的 I/O 服务。 //缓冲区(Buffer)则是通道内部用来发送和接收数据的端点。通道channel充当连接I/O服务的导管 FileChannel channel = inputStream.getChannel(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); // WritableByteChannel 接口以提供 master( )方法 WritableByteChannel byteChannel = Channels.newChannel(outputStream); ByteBuffer buffer = ByteBuffer.allocate(1024); while (true) { int i = channel.read(buffer); if (i == 0 || i == -1) { break; } buffer.flip(); //写模式转换成读模式 byteChannel.write(buffer); buffer.clear(); } inputStream.close(); return outputStream.toByteArray(); } }