Java 热更新 加载class和jar

1、首先了解下java几个加载器的基本原理:

         Java 中的类加载器大致可以分成两类,一类是系统提供的,另外一类则是由 Java 应用开发人员编写的。系统提供的类加载器主要有下面三个: 
     引导类加载器(bootstrap class loader):它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自 java.lang.ClassLoader。 
     扩展类加载器(extensions class loader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。 
     系统类加载器(system class loader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader() 来获取它。

     除了系统提供的类加载器以外,开发人员可以通过继承 java.lang.ClassLoader 类的方式实现自己的类加载器,以满足一些特殊的需求。 

      我们平时程序执行的时候在类加载器中寻找类的结构的顺序是:引导类加载器-》 扩展类加载器-》系统类加载器-》我们自定义的一些类加载器,每个类加载器都有自己的空间,同一个加载器里面的类的二进制名字必须是唯一的,当然同一个类也可以存在不同的加载器内存区域里面,不过我们寻找类的时候是按顺序找的,一但找的也就不会继续往下找了,最终也没找到就会报类不存在异常。 
    我们如果想动态加载类的话就要仿照我们用的服务器如tomcat和weblogic之类的,他们的开发模式也就是把所有的类都加载到自身的类加载器中,当文件被替换的时候他们就重新加载新的class到内存里面去,从而实现了类的动态加载。

2、使用概要:

  File   file   =   new   File(jar文件全路径);   
  URL   url   =   file.toURI().toURL(); 
  URLClassLoader   loader   =   new   URLClassLoader(new   URL[]   {   url   });   
  Class   tidyClazz   =   loader.loadClass(所需class的含包名的全名);  

详细说明:

我们知道,Java利用ClassLoader将类载入内存,并且在同一应用中,可以有很多个ClassLoader,通过委派机制,把装载的任务传递给上级的装载器的,依次类推,直到启动类装载器(没有上级类装载器)。如果启动类装载器能够装载这个类,那么它会首先装载。如果不能,则往下传递。当父类为null时,JVM内置的类(称为:bootstrap class loader)就会充当父类。想想眼下的越来越多用XML文件做配置文件或者是描述符、部署符。其实这些通过XML文档描述的配置信息最终都要变成Java类,实都是通过ClassLoader来完成的。URLClassLoader是ClassLoader的子类,它用于从指向 JAR 文件和目录的 URL 的搜索路径加载类和资源。也就是说,通过URLClassLoader就可以加载指定jar中的class到内存中。

参考代码:

public class ReloadClassLoader extends ClassLoader{
/**

* @param classFile class文件
* @return
* @throws Exception
*/
public Class<?> loadClass(File classFile){
// 一般的class文件通常都小于100k,如果现实情况超出这个范围可以放大长度
byte bytes[] = new byte[(int) classFile.length()];
FileInputStream fis = null;
Class<?> clazz = null;
try
{
fis = new FileInputStream(classFile);
int j = 0;
while (true)
{
int i = fis.read(bytes);
if (i == -1)
break;
j += i;
}
clazz = super.defineClass(null, bytes, 0, j);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return clazz;
}
/**

* @param JarFile Jar包
* @param className 全类名
* @return 
* @throws Exception
*/
public Class<?> loadJAR(File JarFile,String className){
Class<?> cls = null;
         if (!JarFile.exists()) {
             return null;
         }
        
try {
URL url = JarFile.toURI().toURL();
URLClassLoader classLoader = new URLClassLoader(new URL[] { url }, Thread.currentThread().getContextClassLoader());
cls = classLoader.loadClass(className);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
         return cls;
}
}





  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的热加载jar包的Java代码示例: ```java public class HotClassLoader extends ClassLoader { private Map<String, Class> classMap = new HashMap<>(); private String jarPath; public HotClassLoader(String jarPath) { this.jarPath = jarPath; } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { Class clazz = classMap.get(name); if (clazz == null) { try { JarFile jarFile = new JarFile(jarPath); JarEntry entry = jarFile.getJarEntry(name.replace(".", "/") + ".class"); InputStream is = jarFile.getInputStream(entry); byte[] bytes = new byte[(int) entry.getSize()]; is.read(bytes); clazz = defineClass(name, bytes, 0, bytes.length); classMap.put(name, clazz); } catch (IOException e) { throw new ClassNotFoundException(name); } } return clazz; } } ``` 在此示例中,我们使用自定义的ClassLoader类 HotClassLoader 来加载新的jar包。在 HotClassLoader 中,我们使用 ClassLoader 的 defineClass 方法来定义新的类。在每次加载新的类时,我们会检查类是否已经被加载过,如果没有,则从指定的jar包中读取类的字节码,并使用 defineClass 方法来定义新的类。最后,我们将新的类保存在 classMap 中,以便下次使用。 使用热加载技术时,我们可以在任何需要更新的时候,重新加载新的jar包即可。例如,我们可以在一个定时任务中,每隔一段时间检查是否有新的jar包可用,如果有,则使用 HotClassLoader 来加载新的jar包。在加载新的类时,我们可以使用反射机制来调用其中的方法。例如: ```java HotClassLoader classLoader = new HotClassLoader("/path/to/new.jar"); Class clazz = classLoader.loadClass("com.example.MyClass"); Object obj = clazz.newInstance(); Method method = clazz.getDeclaredMethod("myMethod"); method.invoke(obj); ``` 在上述代码中,我们使用 HotClassLoader 来加载新的jar包,然后使用反射机制来调用其中的方法。这样,我们就可以在不重启应用程序的情况下,动态地更新程序的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值