• Java动态加载


    今天初步接触了一下Java的动态加载概念,发现很多情景下我们都会遇到这种用法,自己当初并没有意思到,只是把它当做那种奇奇怪怪的感觉...

    首先,程序是如何跑起来的

    第一步,编译检查、通过编译
    第二步,构建加载器对象、构建字节码对象,完成静态加载
    第三步,在一切准备完成后,对已经加载的目标上跑线程
    第四步,在跑线程过程中,获取当前加载器对象、构建字节码对象,完成动态加载

    加载只是一个读文件的过程,除了文件路径并不会进行其他检查
    静态加载可以说是动态加载的一种特殊情况
    动态加载跳出了固定的编译-加载-运行模式

    典型的静态加载

    如果直接对一个Java源码进行编译,此时缺少Word.java,则无法通过编译检查,无法成功编译

    public class Office{
    	public static void main(String[] args) {
    		System.out.println("编译完成,静态加载完成,开始运行");
    		if ("Word".equals(args[0])) {
    			Word w = new Word();
    			w.start();
    		}
    	}
    }
    

    添加Word.java,成功编译并进行静态加载

    class Word{
    	public static void start(){
    		System.out.println("word...start...");
    	}
    }
    

    运行结果

    ➜  Desktop java Office Word
    编译完成,静态加载完成,开始运行
    word...start...
    

    运行时动态加载

    将以上Office.java稍作改变,成功编译并完成静态加载

    import java.lang.reflect.Method;
    
    class OfficeBetter{
    	public static void main(String[] args){
    		System.out.println("编译完成,静态加载完成,开始运行");
    		if ("OfficeBetter".equals(args[0])) {
    			try{
    				Class c = Class.forName(args[1]); //动态加载类 
    				System.out.println("完成动态加载,继续运行");
    				System.out.println(c.getName());
    				Method[] methods = c.getMethods();
    	            for (Method method: methods) {
    	                System.out.print(method.getReturnType().getName() + "(");
    	                Class[] params = method.getParameterTypes();
    	                for (Class param: params) {
    	                    System.out.print(param.getName() + " ");
    	                }
    	                System.out.println(")");
    	            }
    			}catch(Exception e){
    				e.printStackTrace();		
    			}	
    		}
    		
    	}
    }
    

    程序在运行过程中会再次进行运行时检查,运行结果

    ➜  Desktop java OfficeBetter isNotOfficeBetter
    编译完成,静态加载完成,开始运行
    ➜  Desktop java OfficeBetter OfficeBetter
    编译完成,静态加载完成,开始运行
    java.lang.ArrayIndexOutOfBoundsException: 1
    	at OfficeBetter.main(OfficeBetter.java:8)
    ➜  Desktop java OfficeBetter OfficeBetter Word
    编译完成,静态加载完成,开始运行
    java.lang.ClassNotFoundException: Word
    	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
    	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    	at java.lang.Class.forName0(Native Method)
    	at java.lang.Class.forName(Class.java:264)
    	at OfficeBetter.main(OfficeBetter.java:8)
    

    路径添加Word.class,运行结果

    ➜  Desktop java OfficeBetter OfficeBetter Word
    编译完成,静态加载完成,开始运行
    完成动态加载,继续运行
    Word
    void()
    void(long int )
    void(long )
    void()
    boolean(java.lang.Object )
    java.lang.String()
    int()
    java.lang.Class()
    void()
    void()
    

    Java动态加载非常灵活,运用反射可以一定程度上绕过编译器的检查,JSP其实就是一种动态加载的应用场景呢

  • 相关阅读:
    boost编译中的细节问题
    geos编译问题
    安装pytorch的细节记录
    Qt学习-模仿Qt实现一个colorbutton
    BOOST内存管理-intrusive_ptr
    GEOS使用记录
    matlab添加永久路径
    关于浮点数的取值范围以及精度的问题
    vs2010中使用命令行参数
    sprintf fprintf EOF scanf 的返回值 深拷贝与浅拷贝
  • 原文地址:https://www.cnblogs.com/zzzz76/p/8076536.html
Copyright © 2020-2023  润新知