Copy备用

之前客户要求在不重启应用的前提下实现动态增加服务及交易,在网上查了很长时间也没发现类似的技术,最后研究了一下ClassLoader。因为项目是与Spring,一开始我和同事尝试替换源码的class文件,然后调用Spring的refresh()函数刷新上下文,但是发现原来的类没有被新的类替换。于是我看了一下ClassLoader相关的内容,发现默认的系统类加载器加载类后就不会再次加载。然后我想到要定义自己的类加载器,最后可以实现动态替换原来的类了。虽然最后没能应用在项目中,但是初步了解了一下ClassLoader原理让我感觉挺兴奋的,打算以后再做一下深入的研究,先把源码拷贝下来。

class NetClassLoader extends ClassLoader{
 private byte[] bb = null;
 //private String className = null;
 public NetClassLoader(){
  //super();
  super(ClassLoader.getSystemClassLoader().getParent());//让定义的类加载器与默认的系统类加载器平级
 }
 
 public Class<?> loadClass(String name) throws ClassNotFoundException {
  return loadClass(name, false);
 }
// public Class<?> getLoadedClass(String className)throws ClassNotFoundException{
//  Class c = null;
//  
//  FileInputStream fis;
//  try {
//   
//   fis = new FileInputStream("bin\\"+className+".class");
//   int length = 0;
//   length = fis.available();
//   bb = new byte[length];
//   fis.read(bb);
//   fis.close();
//  } catch (FileNotFoundException e) {
//   throw new ClassNotFoundException("所要加载的类的字节码文件不存在");
//  } catch (IOException e) {
//   throw new RuntimeException("加载字节码文件时出错");
//  }
//
//      c = findClass(className);
//      return c;
// }
 protected synchronized Class<?> loadClass(String className, boolean resolve)
 throws ClassNotFoundException
    {
 Class c = findLoadedClass(className);
 FileInputStream fis = null;
 if(c == null){
  try{
   c = super.loadClass(className, resolve);
  }catch(ClassNotFoundException e){
   
   try {
  
    fis = new FileInputStream("bin\\"+className+".class");
    int length = 0;
    length = fis.available();
    bb = new byte[length];
    fis.read(bb);
    fis.close();
   } catch (FileNotFoundException fe) {
    throw new ClassNotFoundException("所要加载的类的字节码文件不存在");
   } catch (IOException ie) {
    throw new RuntimeException("加载字节码文件时出错");
   }
     c = defineClass(className,bb,0,bb.length);//createClass(className);
  }
 }
 if (resolve) {
     resolveClass(c);
 }
     return c;
    }
 
// public NetClassLoader(byte[] b){
//  bb = b;
// }
 public Class createClass(String className){
  Class klass = defineClass(className,bb,0,bb.length);
  if(klass == null)
   System.out.println("是空的");
  return klass;
 }
}

使用java的自定义classloader机制实现类的动态加载。

//自定义classloader
public class StrategyClassLoader extends ClassLoader { //通过该方法实现类的加载
public Class<BaseStrategy> loadStrategyClass(String name) throws FileNotFoundException, IOException {
String classname = name.replace('.', File.separatorChar) + ".class";
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(classname);
Class<BaseStrategy> cls = instantiateClass(name, is, is.available());
return cls;
} @SuppressWarnings("unchecked")
private Class<BaseStrategy> instantiateClass(String name, InputStream fin, long len) throws IOException {
byte[] raw = new byte[(int) len];
try {
fin.read(raw);
} finally {
fin.close();
}
return (Class<BaseStrategy>) defineClass(name, raw, 0, raw.length);
} } //类加载器classloader的使用
new StrategyClassLoader().loadStrategyClass("com.xxx.xxxx.DummyStrategy");

注意:

  • 该classloader每次都重新读取class文件,实际使用时需要根据自己的需求决定是不是需要缓存。比如可以先检测class文件的时间戳是否变化再确定要不要通过new StrategyClassLoader来重新加载类,否则的话可以使用老的classloader并将之前加载过的class缓存起来以提高性能。

  • 你可以重写loadClass方法来实现目标,但这里我觉得没什么必要。

  • 是不是没更新一次类都要新建立一个classloader?是的,同个classloader中对于相同的类只能加载一次,如果想实现类的不断更新,必须建立新的classloader。

  • 建立这么多的classloader会不会导致内存或者其他资源问题?不会,classloader也只是一个普通的java对象,他一样会被GC垃圾回收掉。所以不用担心太多classloader导致资源不足问题,当然,我们尽可能的减少classloader的创建,毕竟类的加载也是挺耗时的操作。

为了实现动态加载而编写的自己的ClassLoader的更多相关文章

  1. Android 动态加载(防止逆向编译) jar混淆加密

    最近工作中接到了一个研究防止逆向编译的任务.研究了几天资料,最后基本实现了防破解技术,在这个工程中,也略有一些心得体会,现整理下来分享,供大家探讨参考研究.文中如有纰漏.失实之处,请大家及时给与指正. ...

  2. 编写软件动态加载NT式驱动

    NT式设备驱动程序的动态加载主要是由服务控制管理程序(Service Control Manager,即SCM)系统组件来完成的. Windwos服务可以在系统启动时加载,用户也可以按需在服务控制平台 ...

  3. CS.动态加载DLL.动态生成.运行代码.BS.AutoFac管理实现类

    以英雄联盟为例.界面上经常有Load....xxxx.dll.一般都是加载子系统.比如装备系统.英雄系统等.在实际开发中很多项目非常庞大.都会分割成独立子解决方案开发.后期就需要加载回来.一般都是利用 ...

  4. Dex动态加载

    Dex动态加载是为了解决什么问题? 在Android系统中,一个App的所有代码都在一个Dex文件里面. Dex是一个类似Jar的存储了多个Java编译字节码的归档文件. 因为Android系统使用D ...

  5. ligerui_ligerTree_007_ligerTree动态加载节点

    ligerui:ligerTree:动态加载节点: 源码地址:http://download.csdn.net/detail/poiuy1991719/8571255 效果图: 代码:json.txt ...

  6. Android中插件开发篇之----动态加载Activity(免安装运行程序)

    一.前言 又到周末了,时间过的很快,今天我们来看一下Android中插件开发篇的最后一篇文章的内容:动态加载Activity(免安装运行程序),在上一篇文章中说道了,如何动态加载资源(应用换肤原理解析 ...

  7. Android中的动态加载机制

    在目前的软硬件环境下,Native App与Web App在用户体验上有着明显的优势,但在实际项目中有些会因为业务的频繁变更而频繁的升级客户端,造成较差的用户体验,而这也恰恰是Web App的优势.本 ...

  8. Android 动态加载 (一) 态加载机制 案例一

    在目前的软硬件环境下,Native App与Web App在用户体验上有着明显的优势,但在实际项目中有些会因为业务的频繁变更而频繁的升级客户端,造成较差的用户体验,而这也恰恰是Web App的优势.本 ...

  9. Linux中mod相关的命令 内核模块化 mod相关命令都是用来动态加载内核模块/驱动程序模块

    Linux中mod相关的命令 内核模块化   mod相关命令都是用来动态加载内核模块/驱动程序模块 http://baike.baidu.com/link?url=lxiKxFvYm-UfJIxMjz ...

随机推荐

  1. AES加密算法在Linux下出现随机加密结果

    特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过.如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/ ...

  2. python3笔记三:运算符与表达式

    一:学习内容 算术运算符:+(加).-(减).*(乘)./(除).%(取模).**(求幂).//(取整) 赋值运算符:= 复合运算符:+=.-=.*=./=.%=.**=.//= 位运算符:& ...

  3. 关于varchar的总结

    摘自:https://www.jianshu.com/p/c3e188440c67 大家都知道用 varchar 比用 char 类型更省空间(不过性能略有下降,char查询更快),相对于定长的 ch ...

  4. How does ASP.NET Forms Authentication really work?

    I've always wondered how exactly ASP.NET forms authentication works. Yes, I know how to configure Fo ...

  5. 浅谈Manacher算法

    Manacher manacher是一种\(O(n)\)求最长回文子串的算法,俗称马拉车(滑稽) 直接步入正题 首先可以知道的是:每一个回文串都有自己的对称中心,相应的也有自己的最大延伸长度(可以称之 ...

  6. DeepFaceLab参数详解之Batch-Size的使用和取值!

    Batch-Size简称BS. 这是一个非常常见的参数,所有模型都具备的一个参数. 这其实是深度学习中的一个基础概念.要说理论可以说出一大堆,大家可以先简单的理解为一次处理的图片张数.为了防止吓跑小白 ...

  7. 【10】css设置文字不换行,超过的部分用“...”代替

    设置文字不换行,超过的部分用“...”代替  overflow: hidden;  text-overflow: ellipsis;  white-space: nowrap;  width: 210 ...

  8. git 如何把master分支代码合并到自己的分支

    master分支的代码领先自己的分支,git 如何把master分支代码合并到自己的分支 1.首先切换到主分支 git checkout master 2.使用git pull 把领先的主分支代码pu ...

  9. Centos下使用subversion

    Centos下使用subversion 1.安装 yum install subversion 2.创建版本库 a.mkdir -p /var/svn/repositories(创建版本库目录) b. ...

  10. 微信小程序的生命周期和APP对象的使用

    1.生命周期和APP对象的使用: //app.js App({ onLaunch: function () { //调用API从本地缓存中获取数据 var logs = wx.getStorageSy ...