深入理解Java类加载器原理

从Java虚拟机的角度来说,类加载器有两种,一种是启动类加载器, 即Bootstrap ClassLoader(启动类加载器),这个类加载器用C++ 语言实现,是虚拟机的一部分,另外一种类加载器是ExtClassLoader加载器(扩展类加载器),AppClassLoader(系统类加载器),这两个类加载器是用java 语言实现的独立于虚拟机的外部,并且全部继承自ClassLoader类。启动类加载器用来加载JAVA_HOME/lib目录下的类或者是-Xbootclasspath参数中指定的类,并且使虚拟机识别的类库加载到虚拟机内存的。扩展类加载器负责加载JAVA_HOME\jre\lib\ext 目录下或者被java.ext.dirs 系统变量所指定的路径下的所有类库。系统类加载器负责加载用户路径上所指定的类库,用户自定义的类基本都由这个类来加载。再来说一下这三个类加载器的关系,系统类加载器的父加载器是扩展类加载器,而扩展类加载器的父加载器是null ,并不是启动类加载器,注意系统类加载器和扩展类加载器并不是继承的关系。再来解释一个概念,双亲委派机制,这个意思是说在加载一个类的时候,会优先交给父加载器去加载,当父加载器是null的时候 ,则会让启动类加载器去加载 ,当父加载器加载或者启动类加载器都加载不了的话,才会由当前类加载器来加载,来看一下双亲委派机制的具体实现代码。

  protected Class<?> loadClass(String name, boolean resolve)
	        throws ClassNotFoundException
	     { 
	     	   synchronized (getClassLoadingLock(name)) {
	       	     // First, check if the class has already been loaded
	       	     
	       	     Class<?> c = findLoadedClass(name);
	        	    if (c == null) {
	        	        long t0 = System.nanoTime();
	         	       try {
	        	            if (parent != null) {
	            	            c = parent.loadClass(name, false);
	           	         } else {
	              	          c = findBootstrapClassOrNull(name);
	            	         }
	          		
	                   } catch (ClassNotFoundException e) {
	                }
	                if (c == null) {
	                    long t1 = System.nanoTime();
	                    c = findClass(name);
		          }
	            }
	            if (resolve) {
	                resolveClass(c);
	            }
	            return c;
	        }
 }
 这段代码是双亲委派机制实现的具体代码,首先是findLoadedClass方法,
 这个方法是用来查找该类是否有被加载,如果加载过则直接返回该类的Class 对象,
 若没有加载则会执行 parent.loadClass 方法,这个是表示让当前类的父类加载器去加载该类,
 当父类加载器为null ,则会执行findBootstrapClassOrNull方法,这个方法是意思是用启动类加载器去加载当前类,
 当父类加载器或者启动类加载器无法加载该类的时候,则会由当前类加载器去加载该类。
 用户自定义的类一般是由系统类加载器去加载,当加载一个类的类加载器显示为null 的时候,
 那么这个类便是由启动类加载器去加载的。

猜你喜欢

转载自blog.csdn.net/weixin_43352448/article/details/84671578
今日推荐