• JVM热加载class文件(findLoadedClass)


    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虚拟机中,加载器和类的全限定名结合起来才能唯一确定一个类。

  • 相关阅读:
    XML Schema
    String.Format格式说明(转)
    Init,Load,PreRender事件执行顺序
    ASP.NET Web Form 的“连续”和“有状态”假象 (转)
    Windows Phone的网络连接策略(转)
    JAVA获取图片大小和尺寸【转】
    Head First Servlet and JSP 笔记 JSP 部分 (未完待续)
    修复Xcode升级错误 — PCH File Error【转】
    java_时间戳与Date_相互转化相关函数【转】
    Head First Servlet and JSP 笔记 Servlet 部分
  • 原文地址:https://www.cnblogs.com/chwy/p/16037335.html
Copyright © 2020-2023  润新知