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. centos文件实时同步inotify+rsync

    我的应用场景是重要文件备份 端口:873,备份端打开即可 下载地址:https://rsync.samba.org/ftp/rsync/src/ 服务端和客户端要保持版本一致 网盘链接:https:/ ...

  2. servlet3.0以后可以不用web.xml配置了

    AbstractDispatcherServletInitializer 注意:删除了web.xml会报错,web.xml is missing and <failOnMissingWebXml ...

  3. springboot学习问题一:启动springboot报错端口被占用解决办法

    一:问题 二:分析原因 springboot启动默认端口为8080,现在提示被占用,那我们可以修改springboot的启动端口,换一个未被占用的端口即可 三:解决方法 打开application.p ...

  4. 【6】font-size 字体属性

    font-style                         --  字体风格 font-variant                      -- 小型大写字母文本 font-weigh ...

  5. Unity3D中的SendMessage使用(消息传递的三种方法)

    概述 Unity提供的消息推送机制可以非常方便我们的脚本开发,它实现的是一种伪监听者模式,利用的是反射机制. 常用函数 关于消息推送,常用的函数有三个:”SendMessage“.”SendMessa ...

  6. Docker 容器操作

    1. 创建并运行 一个容器 docker run -it --rm   centos:latest  bash run  运行容器 -it  以交互方式运行容器 --rm  退出容器后删除容器 cen ...

  7. 【Ruby on Rails 学习六】Ruby 类 的入门

    1.什么是类 2.类与实例的区别 3.自定义简单的类 生活中的垃圾分类,是集合上的概念 比如数学上的   1  a  2  b  c  4  5分类为数字1 2 4 5 ,字母  a  b  c ir ...

  8. python基础--面向对象初始

    # 类与对象,类是类别.种类,是面向对象设计中最重要的概念, # 对象是特征与技能的结合体, # 类是一系列对象相似特征与技能的结合体 # 例如:人是一个类,而我本人是一个对象,手,脚,是我的特征, ...

  9. Linux (1)

    @https://blog.csdn.net/mayi_xiaochaun这人博客里有一系列linux教程 @linux中,文件名最前加/  比如 cd /usr/local是绝对路径 若#前显示当前 ...

  10. v-if 和v-show的区别

    在切换 v-if 块时,Vue.js 有一个局部编译/卸载过程,因为 v-if 之中的模板也可能包括数据绑定或子组件.v-if 是真实的条件渲染,因为它会确保条件块在切换当中合适地销毁与重建条件块内的 ...