• 类路径分析Java的类加载器与ClassLoader(二):classpath与查找类字节码的顺序,分析ExtClassLoader与AppClassLoader的源码


    每日一贴,今天的内容关键字为类路径

        

        先回想一下classpath

        classpath的作用:

            classpath的作用是指定找查类的路径:当应用java命令执行一个类(类中的main方法)时,会从classpath中停止找查这个类。

        

        指定classpath的方法一:

        

            置设环境变量CLASSPATH,多个路径之间应用英文的分号开隔,也可以指定为jar包路径。

            

        示例:CLASSPATH=c:/myclasses/;c/mylib/aa.jar;c:/mylib/bb.jar;.

            

        注意:在Windows中不区分大小写,所以指定的环境变量名为classpath或是ClassPath都一样。

        

        指定classpath的方法二:

        

            

        在执行java命令时通过-classpath数参指定。

            

        示例:java -classpath c:/myclasses/;c:/mylib/aa.jar cn.itcast.MainApp

            

        注意:这样就会只是用这个数参指定的classpath,找不到类就报错,不会应用CLASSPATH环境变量!

        

        指定classpath时各个路径的序顺:

        

            验试的论结是

        按classpath中指定的序顺,先从后面的路径中找查,如果找不到,在从下一个路径中找查,直到找到类字节码或是报NoClassDefFoundError。

        

        另外一种指定类路径方法:

        

            把类字节码文件打成jar包,并放到JRE的lib/ext/录目下,这样在执行时就能够直接找到这个类而不需要指定classpath了。

        类加载器与classpath

        从上一个文章中我们知道了类加载器认默应用三个:
    1,Bootstrap ClassLoader,启动类加载器,责负加载核心Class(即有所java.*扫尾的Class)。
    2,Extension ClassLoader,扩展类加载器,责负加载存放在JRE的lib/ext/录目下的jar包中的Class。
    3,Application ClassLoader,应用程序类加载器,责负加载应用程序自身的类(CLASSPATH录目中的Class)。

        析分ExtClassLoader

            Extension ClassLoader责负加载扩展类路径中的类(认默为JRE的lib/ext/录目),也就是说只要把jar包放到这个录目中,就能够直接应用面里的类字节码而不需要指定classpath !注意这要求必定要在这个录目中放jar包,直接把.class文件放到这个录目中行不。析分一下源码(sun.misc.Launcher$ExtClassLoader类):

        每日一道理
    因为自信,在呀呀学语时,我靠着纤嫩的双腿,迈出人生的第一步;因为自信,我一次次将第一名的奖状高高举起;因为自信,我毫不吝惜地剪掉飘逸的长发,在运动场上展现风采……感谢自信,它给了我一双翅膀,让我在电闪雷鸣中去飞翔,在风雨中去搏击人生!
    static class ExtClassLoader extends URLClassLoader {
    	private File[] dirs;
    
    
    	// 先看这个方法
    	public static ExtClassLoader getExtClassLoader() throws IOException {
    		// 用调getExtDirs()方法取获配置的扩展类路径
    		final File[] dirs = getExtDirs();
    		try {
    			// 应用getExtDirs()方法返回的路径生成一个新的ClassLoader实例
    			return (ExtClassLoader) AccessController.doPrivileged(new PrivilegedExceptionAction() {
    				public Object run() throws IOException {
    					int len = dirs.length;
    					for (int i = 0; i < len; i++) {
    						MetaIndex.registerDirectory(dirs[i]);
    					}
    					return new ExtClassLoader(dirs);
    				}
    			});
    		} catch (java.security.PrivilegedActionException e) {
    			throw (IOException) e.getException();
    		}
    	}
    
    
    	// 再看这个方法
    	private static File[] getExtDirs() {
    		// 取获配置的扩展类路径
    		String s = System.getProperty("java.ext.dirs");
    		File[] dirs;
    		if (s != null) {
    			StringTokenizer st = new StringTokenizer(s, File.pathSeparator);
    			int count = st.countTokens();
    			dirs = new File[count];
    			for (int i = 0; i < count; i++) {
    				dirs[i] = new File(st.nextToken());
    			}
    		} else {
    			dirs = new File[0];
    		}
    		return dirs;
    	}
    	
    	// 其他码代略
    	...
    }

        

            

        

        Application ClassLoader责负加载CLASSPATH录目中的Class

        

        ,也就是说classpath是给这个类加载器用的。析分一下源码(sun.misc.Launcher$AppClassLoader类):

    static class AppClassLoader extends URLClassLoader {
    
    
    	public static ClassLoader getAppClassLoader(final ClassLoader extcl) throws IOException {
    		// 取获配置的classpath路径
    		// 注1:可以通过置设classpath环境变量转变java.class.path的值。
    		// 注2:也可以在程序中应用System.setProperty("java.class.path", "newpath")转变java.class.path的值。
    		final String s = System.getProperty("java.class.path");
    		final File[] path = (s == null) ? new File[0] : getClassPath(s);
    
    
    		// 应用classpath中的路径生成一个新的ClassLoader实例并返回
    		return (AppClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
    			public Object run() {
    				URL[] urls = (s == null) ? new URL[0] : pathToURLs(path);
    				return new AppClassLoader(urls, extcl);
    			}
    		});
    	}
    
    
    	// 其他码代略
    	...
    }

        当AppClassLoader上遇ExtClassLoader

           

        

        如果JRE的lib/ext/录目下的jar包有某个类,我们指定的classpath中也有这个类,会怎么样呢?想一想类加载找查类字节码的策略!论结是会执行lib/ext/xx.jar中的类!

        

        因为类加载器应用托委式模停止类加载,并且ExtClassLoader是AppClassLoader的下级,所以AppClassLoader会先让ExtClassLoader加载。如果父的类加载器没有找到,自己才会加载。

        

        论结:

        

        1,把jar包放到扩展类路径中就能够直接应用其中的类(认默是JRE的lib/ext/录目)
    2,classpath是给AppClassLoader配置的。
    3,如果扩展类路径中有某个类,classpath中也有这个类,则会应用扩展类路径中的类。

    文章结束给大家分享下程序员的一些笑话语录: 开发时间
      项目经理: 如果我再给你一个人,那可以什么时候可以完工?程序员: 3个月吧!项目经理: 那给两个呢?程序员: 1个月吧!
    项目经理: 那100呢?程序员: 1年吧!
    项目经理: 那10000呢?程序员: 那我将永远无法完成任务.

  • 相关阅读:
    济南空中课堂视频下载辅助脚本
    npm 修改仓库源
    Java后端实现登陆的方式
    java 新词汇
    数据库系统,设计、实现与管理(基础篇)阅读笔记
    java 面试01
    js rem 适配多端
    了解Java
    linux 查看内存使用情况
    linux 日志查看
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3063579.html
Copyright © 2020-2023  润新知