ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

JVM热加载class文件(findLoadedClass)

2022-03-21 23:33:07  阅读:142  来源: 互联网

标签:java buffer findLoadedClass JVM import new class 加载


package geym.zbase.ch10.clshot;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;

public class MyClassLoader extends ClassLoader {  
    private String fileName;  
  
    public MyClassLoader(String fileName) {  
        this.fileName = fileName;  
    }  
  
    protected Class<?> findClass(String className) throws ClassNotFoundException {  
        Class clazz = this.findLoadedClass(className);  
        if (null == clazz) {  
            try {  
                String classFile = getClassFile(className);  
                FileInputStream fis = new FileInputStream(classFile);  
                FileChannel fileC = fis.getChannel();  
                ByteArrayOutputStream baos = new  
                        ByteArrayOutputStream();  
                WritableByteChannel outC = Channels.newChannel(baos);  
                ByteBuffer buffer = ByteBuffer.allocateDirect(1024);  
                while (true) {  
                    int i = fileC.read(buffer);  
                    if (i == 0 || i == -1) {  
                        break;  
                    }  
                    buffer.flip();  
                    outC.write(buffer);  
                    buffer.clear();  
                }  
                fis.close();  
                byte[] bytes = baos.toByteArray();  
  
                clazz = defineClass(className, bytes, 0, bytes.length);  
            } catch (FileNotFoundException e) {  
                e.printStackTrace();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
        return clazz;  
    }  
    private byte[] loadClassBytes(String className) throws  
            ClassNotFoundException {  
        try {  
            String classFile = getClassFile(className);  
            FileInputStream fis = new FileInputStream(classFile);  
            FileChannel fileC = fis.getChannel();  
            ByteArrayOutputStream baos = new  
                    ByteArrayOutputStream();  
            WritableByteChannel outC = Channels.newChannel(baos);  
            ByteBuffer buffer = ByteBuffer.allocateDirect(1024);  
            while (true) {  
                int i = fileC.read(buffer);  
                if (i == 0 || i == -1) {  
                    break;  
                }  
                buffer.flip();  
                outC.write(buffer);  
                buffer.clear();  
            }  
            fis.close();  
            return baos.toByteArray();  
        } catch (IOException fnfe) {  
            throw new ClassNotFoundException(className);  
        }  
    }  
    private String getClassFile(String name) {  
        StringBuffer sb = new StringBuffer(fileName);  
        name = name.replace('.', File.separatorChar) + ".class";  
        sb.append(File.separator + name);  
        return sb.toString();  
    }  
}  
package geym.zbase.ch10.clshot;

import java.lang.reflect.Method;

public class DoopRun {
    public static void main(String args[]) {
        while(true){
            try{
                MyClassLoader loader = new MyClassLoader("D:/tmp/clz");
                Class cls = loader.loadClass("geym.zbase.ch10.clshot.DemoA");
                Object demo = cls.newInstance();
        
                Method m = demo.getClass().getMethod("hot", new Class[] {});
                m.invoke(demo, new Object[] {});
                Thread.sleep(10000);
            }catch(Exception e){
                System.out.println("not find");
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e1) {
                }
            }
        }
    }
}
package geym.zbase.ch10.clshot;

public class DemoA {
    public void hot(){
        System.out.println("NewDemoA");
    }
}

以上程序复制于(《实战JAVA虚拟机》)

MyClassLoader是自定义加载器。
DoopRun用于执行热加载文件中的hot方法。
DemoA用于提供hot方法,不同DemoA中的hot方法可以打印不同的内容。

将DemoA.class文件放到D:/tmp/clz下面,需保持DemoA的全限定名的目录结构。另外Java程序的启动参数需要设置为-Xbootclasspath/a:/tmp/clz 。这样替换DemoA.java 中的hot方法,可以打印不同的内容,不需要重启Java程序。

MyClassLoader loader = new MyClassLoader("D:/tmp/clz"); 另外这一句非常重要,这一句要放到while中,放到while外的话,即使替换Demo.java也不会打印新的内容。原因是findClass方法中的Class clazz = this.findLoadedClass(className); 会判断class文件是否已经加载。如果已经加载,则使用之前加载过的class文件,而不会重新加载。而放到while中,相当于每次重新new一个MyClassLoader,生成了不同的加载器,不同的加载器对应的是不同的class文件,此时this.findLoadedClass(className)每次返回的都是null,都会去重新读取DemoA.class文件,重新加载,从而实现了热加载。在JVM虚拟机中,加载器和类的全限定名结合起来才能唯一确定一个类。

标签:java,buffer,findLoadedClass,JVM,import,new,class,加载
来源: https://www.cnblogs.com/chwy/p/16037335.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有