构建网络类加载器 继承ClassLoader 实现自定义类加载器
package com.net.utils; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.net.URL; public class NetClassLoder extends ClassLoader { private String url; public NetClassLoder(String url){ this.url=url; } @Override protected void finalize() throws Throwable { System.out.println("类加载器回收了"); } @Override public Class> findClass(String className) throws ClassNotFoundException { System.out.println(className); Class> aClass; byte[] classByNet = findClassByNet(className); System.out.println(classByNet); if(classByNet==null){ System.out.println("没找到"); // aClass = super.findClass(className); // System.out.println("找到这个"+aClass); return null; } aClass = defineClass(className,classByNet,0,classByNet.length); return aClass; } protected byte[] findClassByNet(String className){ // 从网络上读取的类的字节 String path = pares2Url(className); try { URL url = new URL(path); InputStream ins = url.openStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); int bufferSize = 4096; byte[] buffer = new byte[bufferSize]; int bytesNumRead = 0; // 读取类文件的字节 while ((bytesNumRead = ins.read(buffer)) != -1) { baos.write(buffer, 0, bytesNumRead); } return baos.toByteArray(); } catch (Exception e) { return null; } } private String pares2Url(String className) { String replace = className.replace(".", "/"); return url+"/"+replace+".class"; } } //使用方式 String domain="http://172.0.10.173"; NetClassLoder classLoader = new NetClassLoder(domain); Class> aClass = classLoader.findClass("com.load.plugin.impl.Command"); Cmd cmd = (Cmd) aClass.newInstance(); NetClass netClass = new NetClass(); cmd.test();以上存在的问题发现
当netclassloder类加载器 被构建的时候
每次类加载的时候都会调用finalclass 去寻找
由于是网络中只有我们的目的class文件,导致其他字节码找不到
重写在netclassLoader中重写 loadclass 方法
@Override public Class> loadClass(String name) throws ClassNotFoundException { //优先从网络找字节码 Class> loadClass =findClass(name); //第一情况 这个类 不需要由我们加载 //第二种情况 这个类需要由我们加载 但是 确实加载不到 if ( loadClass ==null){ //查看是否已经加载过 加载过就返回之前存在的 loadClass = findLoadedClass(name); } if(loadClass == null){ //如果网络和之前都没加载过 就调用系统的类加载器去加载这个类 loadClass= getSystemClassLoader().loadClass(name); System.out.println(loadClass); } return loadClass; } //使用方式中修改为 String domain="http://172.0.10.173"; NetClassLoder classLoader = new NetClassLoder(domain); Class> aClass = classLoader.loadClass("com.load.plugin.impl.Command"); Cmd cmd = (Cmd) aClass.newInstance(); NetClass netClass = new NetClass(); cmd.test();以上idea 调试 和整合springboot 直接使用都没问题 但是打包部署却有问题
spring boot 类加载的时候是通过 启动类加载器 加载springboot/lib 下的包
所以使用系统的类加载器是无法识别到maven 依赖的,尽管已经打包到里面了
完整代码
package com.net.utils; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.net.URL; public class NetClassLoder extends ClassLoader { private String url; public NetClassLoder(String url){ this.url=url; } @Override protected void finalize() throws Throwable { System.out.println("类加载器回收了"); } @Override public Class> findClass(String className) throws ClassNotFoundException { System.out.println(className); Class> aClass; byte[] classByNet = findClassByNet(className); System.out.println(classByNet); if(classByNet==null){ System.out.println("没找到"); // aClass = super.findClass(className); // System.out.println("找到这个"+aClass); return null; } aClass = defineClass(className,classByNet,0,classByNet.length); return aClass; } protected byte[] findClassByNet(String className){ // 从网络上读取的类的字节 String path = pares2Url(className); try { URL url = new URL(path); InputStream ins = url.openStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); int bufferSize = 4096; byte[] buffer = new byte[bufferSize]; int bytesNumRead = 0; // 读取类文件的字节 while ((bytesNumRead = ins.read(buffer)) != -1) { baos.write(buffer, 0, bytesNumRead); } return baos.toByteArray(); } catch (Exception e) { return null; } } @Override public Class> loadClass(String name) throws ClassNotFoundException { Class> loadClass = findClass(name); if ( loadClass ==null){ loadClass = findLoadedClass(name); } if(loadClass==null){ loadClass = Thread.currentThread().getContextClassLoader().loadClass(name); System.out.println(loadClass); } return loadClass; } private String pares2Url(String className) { String replace = className.replace(".", "/"); return url+"/"+replace+".class"; } } // 使用 String domain="http://172.0.10.173"; NetClassLoder classLoader = new NetClassLoder(domain); Class> aClass = classLoader.loadClass("com.load.plugin.impl.Command"); Cmd cmd = (Cmd) aClass.newInstance(); NetClass netClass = new NetClass(); cmd.test();
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)