基本原理
						
								
								
								
						
				
		
		
				所有类都由类装载器载入,载入内存中的类对应一个
				java.lang.Class
				实例。
		
		
				已被加载的类由该类的类加载器实例与该类的全路径名的组合标识。设有
				packagename.A Class
				,分别被类加载器
				CL1
				和
				CL2
				加载,则系统中有两个不同的
				java.lang.Class
				实例:
				<CL1, packagename.A>
				和
				<CL2, packagename.A>
				。
		
		
				存在一个
				Bootstrap Loader
				(以下简称为
				BL
				),由
				C++
				写成,负责在虚拟机启动后一次
		
		
				性加载
				Java
				基础类库中的所有类。其他的类装载器由
				Java
				写成,都是
				java.lang.ClassLoader
				的子类。
		
		
				除
				BL
				之外的所有类装载器都有一个
				parent
				属性,指向其父装载器。查阅
				java.lang.ClassLoader
				的源码,不难发现类装载器的委托装载方式。
		
		
		
		
				
						
								| 
												
														 
												
												
														   
												
												
														protected
												
												
												
												
														synchronized
												
												Class<?> loadClass(String name, 
												
														boolean
												
												resolve)
												
														
																throws
														
														ClassNotFoundException
														
														
												
										 
												
														    {
												
														
														
												
										 
												
														     
														     
												
												// First, check if the class has already been loaded
												
														
														
												
										 
												
														     
														     Class c = findLoadedClass(name);
												
														
														
												
										 
												
														     
														     
												
												
														if
												
												(c == 
												
														null
												
												) {
												
														
														
												
										 
												
														     
														    
														
														
														     
												
												
														try
												
												{
												
														
														
												
										 
												
														         
														     
														     
												
												
														if
												
												(
												parent
												!= 
												
														null
												
												) {
												
														
														
												
										 
												
														         
														    
														
														
														     
														     c = 
												parent
												.loadClass(name, 
												
														false
												
												);
												
														
														
												
										 
												
														         
														     
														     } 
												
														else
												
												{
												
														
														
												
										 
												
														         
														    
														
														
														     
														     c = findBootstrapClass0(name);
												
														
														
												
										 
												
														         
														     
														     }
												
														
														
												
										 
												
														     
														    
														
														
														     } 
												
														catch
												
												(ClassNotFoundException e) {
												
														
														
												
										 
												
														     
														        
														
														
														     
												
												// If still not found, then invoke findClass in order
												
														
														
												
										 
												
														     
														        
														
														
														     
												
												// to find the class.
												
														
														
												
										 
												
														     
														        
														
														
														     c = findClass(name);
												
														
														
												
										 
												
														     
														    
														
														
														     }
												
														
														
												
										 
												
														     
														     }
												
														
														
												
										 
												
														     
														     
												
												
														if
												
												(resolve) {
												
														
														
												
										 
												
														     
														    
														
														
														     resolveClass(c);
												
														
														
												
										 
												
														     
														     }
												
														
														
												
										 
												
														     
														     
												
												
														return
												
												c;
												
														
														
												
										 
												
														    }
										 | 
				
		
		
				
						       
				
				对于给定的类名,首先检查自己是否已加载过该类。如果没有,则首先通过父装载器加载(如果
				parent==null
				,则直接通过
				BL
				来加载,相当于
				BL
				是其父装载器)。如果父装载器也无法装载,才真正调用自己的
				findClass()
				方法来装载。
		
		
				
						       Java
				基础类在
				Java
				虚拟机启动后由
				BL
				一次性载入。构成
				Java
				应用程序的其它类在程序运行过程中由不同类装载器按需通过
				loadClass()
				方法装载。
		
		
				
						Java
						程序启动过程中的类装载器
				
		
		
				当执行“
				java XXX.class
				”时,
				java.exe
				首先找到
				JRE
				(
				Java Runtime Environment
				),接着找到位于
				JRE
				之中的
				jvm.dll
				,最后载入
				jvm.dll
				并启动虚拟机。
		
		
				虚拟机一启动,先做一些初始化动作,如获取系统参数等,然后产生
				BL
				。
				BL
				加载
				Java
				基础类,这些类都存放在
				JRE
				中的
				lib
				目录下,可由
				System.getProperty(“sun.boot.class.path”)
				列出,如:
		
		
		
		
				
						
								| 
												C:\Program Files\Java\jre1.5.0_09\lib\rt.jar;
										 
												C:\Program Files\Java\jre1.5.0_09\lib\i18n.jar;
										 
												C:\Program Files\Java\jre1.5.0_09\lib\sunrsasign.jar;
										 
												C:\Program Files\Java\jre1.5.0_09\lib\jsse.jar;
										 
												C:\Program Files\Java\jre1.5.0_09\lib\jce.jar;
										 
												C:\Program Files\Java\jre1.5.0_09\lib\charsets.jar;
										 
												C:\Program Files\Java\jre1.5.0_09\classes
										 | 
				
		
		
				
						       BL
				然后创建
				sun.misc.Launcher$ExtClassLoader
				(
				ExtClassLoader
				是定义于
				sun.misc.Launcher
				之内的内部类,继承自
				java.lang.URLClassLoader
				)的实例(以下简称
				EL
				)和
				sun.misc.Launcher$AppClassLoader
				(
				AppClassLoader
				是定义于
				sun.misc.Launcher
				之内的内部类,继承自
				URLClassLoader
				)的实例(以下简称
				AL
				),并将
				EL
				的
				parent
				属性设置为
				null
				,
				AL
				的
				parent
				属性设置为
				EL
				。
		
		
				
						       EL
				在程序运行过程中按需加载保存在
				JRE
				的“
				\lib\ext
				”目录下的类。该目录可由
				System.getProperty(“java.ext.dirs”)
				读出,如
		
		
		
		
				
						
								| 
												C:\Program Files\Java\jre1.5.0_09\lib\ext
										 | 
				
		
		
				
						       AL
				在程序运行过程中按需加载的类搜索路径则是从系统参数
				java.class.path
				取出的字符串。
				java.class.path
				是由我们在执行
				java.exe
				时,利用
				-cp
				或
				-classpath
				或
				CLASSPATH
				环境变量所决定。我们应用程序用到的非
				JRE
				提供类的搜索路径一般都配置在
				java.class.path
				中。
		
		
				
						什么时候装载类,由什么类装载器装载
				
		
		
				
						1.  
				
				Java
				基础类由
				BL
				在虚拟机启动时一次性载入。
		
		
				
						2.  
				
				包含
				main()
				的入口类由
				AL
				的
				loadClass()
				方法载入。
		
		
				
						3.  
				
				由
				new 
				关键字创建一个类的实例。该类由运行时刻包含该
				new
				语句的类实例的类装载器(
				ClassLoader.getCallerClassLoader()
				)的
				loadClass()
				方法载入。
		
		
				
						4.  
				
				调用
				Class.forName()
				方法。完整的
				forName()
				函数版本有一个
				ClassLoader
				参数,用于指定用什么类装载器来装载指定类。
		
		
		
		
				
						
								| 
												
														    
												
												
														public
												
												
												
												
														static
												
												Class<?> forName(String name, 
												
														boolean
												
												initialize,
												
														
														
												
										 
												
														              
														   ClassLoader loader)
												
														throws
												
												ClassNotFoundException
												
														
														
												
										 | 
				
		
		
				
						       
				
				对于
				public static Class<?> forName(String className)
				版本,是由运行时刻包含该语句的类实例的类装载器(
				ClassLoader.getCallerClassLoader()
				)的
				loadClass()
				方法载入。
		
		
				
						5.  
				
				调用某个
				ClassLoader
				实例的
				loadClass()
				方法。通过该
				ClassLoader
				实例的
				loadClass()
				方法载入。应用程序可以通过继承
				ClassLoader
				实现自己的类装载器。
				
						
						
				
		
		
				6
				.装载一个类时,首先要装载该类的基类及其接口。