因为在深刻jvm虚拟机中看到了有部分说道class能够经过网络的方式加载,因而就想到了是否是能够经过在网络上发布jar包,而后程序动态加载网络上的jar包(可拓展为热更新)java
调用模块 https://coding.net/u/mich/p/easytry/git/tree/master/src/com/netclassloadergit
实现模块 https://coding.net/u/mich/p/easytry/git/tree/master/netlogicImpl数组
接口模块 https://coding.net/u/mich/p/easytry/git/tree/master/netlogicInterface网络
该内容主要由三部分组成jvm
接口模块相对来讲比较简单,两个接口ide
package com.netresource.logic; /** * Created by Mich on 2017/7/22. */ public interface ISayHello { Object sayHello(); }
package com.netresource.logic; /** * Created by Mich on 2017/7/22. */ public interface ISayWorld { Object sayWorld(); }
实现模块须要先导入刚才接口模块,而后写两个接口的实现类函数
package com.netlogic; import com.netresource.logic.ISayHello; /** * Created by Mich on 2017/7/22. */ public class SayHelloImpl implements ISayHello { @Override public Object sayHello() { return "Hello"; } }
package com.netlogic; import com.netresource.logic.ISayWorld; /** * Created by Mich on 2017/7/22. */ public class SayWorldImpl implements ISayWorld { @Override public Object sayWorld() { return "World"; } }
你会发现还有两个util,fileutil主要是我一直使用的对文件的一些处理比较方便,就直接引用了,PropertiesUtil主要是协议文件的生成工具,经过传入实现类的包名,而后扫描该包下的全部类把接口和实现作对应关系存放在output.properties文件中,须要注意的是,若是一个接口并不支持有多个实现类,可是一个实现类实现多个接口是能够的工具
最后将实现类打jar包,以及将协议文件上传至网络,我这里图方便直接放到了coding上https://coding.net/u/mich/p/easytry/git/raw/master/src/com/netclassloader/output/netlogicImpl.jar测试
https://coding.net/u/mich/p/easytry/git/raw/master/src/com/netclassloader/output/output.propertiesthis
一样调用模块须要引用接口模块的jar包,而后介绍一下调用模块的具体目录结构(这里无视output文件夹,这主要是我刚才上传的两个文件,jar包和协议文件,为了在一个模块里才放这里,实际不须要这个文件夹)
NetClassManager,因为代码有点多就不在这里显示了,具体能够再coding上去看,这里主要介绍一下结构
NetClassLoader类加载器
package com.netclassloader; /** * Created by Mich on 17/7/17. */ public class NetClassLoader extends ClassLoader { private NetClassManager netClassManager; public NetClassLoader(NetClassManager netClassManager) { this.netClassManager = netClassManager; } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { byte[] bytes = netClassManager.getClassMap().get(name); return defineClass(name, bytes, 0, bytes.length); } }
这个就比较简单了,继承了ClassLoader,构造函数传入刚刚说明的管理类NetClassManager,而后重写了findClass的方法,经过管理类的map来获取字节数组
Main做为测试的入口函数
public static void main(String[] args) {
String jarUrl = "https://coding.net/u/mich/p/easytry/git/raw/master/src/com/netclassloader/output/netlogicImpl.jar"; String propertiesUrl = "https://coding.net/u/mich/p/easytry/git/raw/master/src/com/netclassloader/output/output.properties"; NetClassManager netClassManager = new NetClassManager(propertiesUrl, jarUrl); NetClassLoader classLoader = new NetClassLoader(netClassManager); ISayHello hello = netClassManager.getService(classLoader, ISayHello.class); ISayWorld world = netClassManager.getService(classLoader, ISayWorld.class); System.out.println(hello.sayHello()); System.out.println(world.sayWorld()); }
最后就是比较简单的调用了,运行结果
其实这里也只是抛砖,若是具体使用,应该还须要版本控制,能够有一个专门的类,或者手动调用,去获取最新的jar包,和最新的协议接口文件,固然更好一点能够再添加一个实现类的版本控制,这样就须要修改的粒度更小了。对了若是要添加动态更新还须要修改NetClassLoader类,如今目前只是第一次加载处理,若是有更新,就须要重写loadClass方法了。最后想一想其实协议文件,和版本控制能够直接放在jar包中。。。等下次再继续改进吧。。。