在JVM里面可以根据类加载器而后进行指定路径中类的加载,也就是说找到了类的加载器就意味着找到了类的来源
系统类的加载器
如果说现在要想获得类的加载器,那么一定要同ClassLoader来获取,而要想获取Classloader类对象,则必须用Class类(反射的根源)实现,方法:public ClassLoader getClassLoader()
;
自定义加载器
自定义的类加载器其加载顺序是在所有系统类加载器的最后。系统类中的类加载器都是根据CLASSPATH路径进行加载的,而如果有了自定义加载器,就可以由开发者任意指派类的加载位置。
1、随意编写一个程序类,并且将这个类保存到磁盘上
package message;
public class Message {
public void send() {
System.out.println("www.asdads.asdasd");
}
}
2、将此类直接拷贝到D盘上进行编译处理,并且不打包:javac Message.java,此时并没有进行打包处理,所以此时无法进行CLASSPATH正常加载。
3、自定义一个类加载器,并且继承自ClassLoader类。在ClassLoader类里面为用户提供一个字节转换为类结构的方法:
- 定义类:
protected final Class<?> defineClass(String name, byte [] b, int off, int len) throws ClassFormatError
package demo.util;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
public class MLDNClassLoader extends ClassLoader {
private static final String MESSAGE_CLASS_PATH = "D:" + File.separator +"Message.class";
/**
* 进行指定类加载
* @param className 类的完整名称“包.类”
* @return 返回一个指定类的Class对象
* @throws Exception 如果类文件不存在则无法加载
*/
public Class<?> loadData(String className) throws Exception{
byte [] data = this.loadClassData();//读取二进制数据文件
if(data !=null) {//读取到了
return super.defineClass(className, data, 0, data.length);
}
return null ;
}
private byte [] loadClassData() throws Exception{//通过文件进行类的加载
InputStream input = null ;
ByteArrayOutputStream bos = null ;//将数据加载到内存之中
byte data[] = null;
try {
bos = new ByteArrayOutputStream();//实例化内存流
input = new FileInputStream(new File(MESSAGE_CLASS_PATH));//文件流加载
input.transferTo(bos);//读取数据
data = bos.toByteArray();//将所有读取到的字节数据取出
} catch (Exception e) {
e.printStackTrace();
}finally {
if(input != null) {
input.close();
}
if(bos != null) {
bos.close();
}
}
}
}
4、编写测试类实现实现类加载控制。
package demo;
import java.lang.reflect.Method;
import demo.util.MLDNClassLoader;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
MLDNClassLoader classloader = new MLDNClassLoader();//实例化自定义类加载器
Class<?> cls = classloader.loadData("demo.util.Message");//进行类加载
Object obj = cls.getDeclaredConstructor().newInstance();
Method method = cls.getDeclaredMethod("send");
method.invoke(obj);
}
}
如果以后结合到网络程序开发的话,就可以通过一个远程的服务器获取内容。
参考资料:https://edu.aliyun.com/lesson_1012_9061?spm=5176.10731542.0.0.4369d29052jBVf