JVM自定义类加载器--读取与JAVA类名不同的文件名--并解析加载类
本文的目的,是通过解剖和修改JVM的类加载器,来详细分析JVM的类加载机制。
其实任何一个JVM的类加载器不过是做了如下的工作:
1. 确定JAVA类文件的位置。
2. 读取类文件内容,将类文件内容读取成二进制字节流。
3. 解析并加载类内容。
4. 最后,将类的“标识”返回给要使用这个类的代码中。
那下面我们就来做一个比较“另类”的试验:
在JAVA规范中,public类名必须与类所在的文件名相同。
但本文将尝试在一个名为“T1.bin”的文件中,加载一个名为“Test1”的类,以此来创造一种与JVM标准类加载器不同的类加载器。
先讲讲我的实现思路:
1. 先编写一个类,此类将被其它类来调用,这个类的类名和文件名在测试时将不会相同。这个类的类名为“Test1”,而文件名为“T1.bin”。
2. 编写自己的类加载器,此类加载器不是从寻常的".class"文件中来加载一个类,而是从代码中写死的“D:/Users/T1.bin”文件中来加载一个类。
3. 编写业务逻辑类,此类将利用反射原理,调用类加载器,读取T1.bin文件,构造第一步中建立的类的对象,并调用这个对象的方法。
首先在Eclipse中新建一个Java工程,名为“Test1”,在我的硬盘上,此工程的存储地址为“D:\Users\haojian.XINAO\workspace\Test1”。
在此工程的src目录下,新建一个Java类,名为“Test1”,内容如下:
?
protected Class<?> findClass(String name) throws ClassNotFoundException { throw new ClassNotFoundException(name); }
其实在ClassLoader类里,对findClass()是没有任何实现的,需要它的子类来实现。这样,执行权就顺利的交给了MyClassLoader1的findClass()方法,而通过findClass()->loadClassBytes()->getClassFile()就能顺利执行到getClassFile()方法了。
其实我这篇文章里面讲到的,都只是对类文件的读取,并没有涉及到最核心的“将二进制字节流解析成内存中的JAVA类结构”,将二进制解析成内存结构是由“defineClass()”方法来完成的,以后会慢慢讲到的。
其实按照我文章里的这种思路,大家可以尝试在数据库中、网站文件中、FTP中等地方来加载一个JAVA类。。。