虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到Java虚拟机外部去实现,以便应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块被称为类加载器。

1.类与类加载器

比较两个类是否“相等”,只有在这两个类是由同一个类加载器的前提下才有意义,否则,即使这两个类来源于同一个Class文件,只要加载它们的类加载器不同,这两个类就必定不相等。

package demos;

import java.io.IOException;
import java.io.InputStream;

public class ClassLoaderTest {
	public static void main(String[] args) throws Exception{
		ClassLoader myLoader = new ClassLoader(){
			@Override
			public Class<?> loadClass(String name) throws ClassNotFoundException{
				try{
					String fileName= name.substring(name.lastIndexOf(\".\")+1)+\".class\";
					InputStream is = getClass().getResourceAsStream(fileName);
					if(is == null){
						return super.loadClass(name);
					}
					byte[] b = new byte[is.available()];
					is.read(b);
					return defineClass(name, b, 0, b.length);
				}catch(IOException e){
					throw new ClassNotFoundException();
				}
			}
		};
		  obj = myLoader.loadClass(\"demos.ClassLoaderTest\").newInstance();
		System.out.println(obj.getClass());
		System.out.println(obj instanceof demos.ClassLoaderTest);
	}
}

结果:
\"在这里插入图片描述\"

2.双亲委派模型

Java虚拟机角度,两种类加载器:启动类加载器(Bootstrap ClassLoader);其他类加载器,由java语言实现,独立于虚拟机外部,全都继承自抽象类java.lang.ClassLoader。
Java开发人员角度,三种类加载器:
启动类加载器(Bootstrap ClassLoader):负责将虚拟机识别的类库加载到虚拟机内存中。无法被Java程序直接引用。
扩展类加载器(Extension ClassLoader):加载java.ext.dirs系统变量指定的路径中的所有类库,开发者可以直接使用。
应用程序类加载器(Application ClassLoader):也称系统类加载器,负责加载用户类路径(ClassPath)上所指定的类库,开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序的中的默认类加载器。该类加载器是ClassLoader中的getSystemClassLoader()的返回值。
双亲委派模型(Parents Delegation Model):
\"在这里插入图片描述\"
工作过程:一个类加载器收到类加载请求,首先不会自己去加载这个类,而是将这个请求委派给父类加载器完成,每一个层次的类加载都是如此,所有的加载请求都应该传送到顶层的启动类加载器中,只有当父加载器反馈无法完成这个加载请求时,子加载器才会尝试自己加载。
好处:Java类随着它的类加载器一起具备了带有优先级的层次关系;增强Java程序的稳定性。

OSGi((Open Service Gateway Initiative)——面向Java的动态模型系统。实现模块化热部署需要自定义类加载机制,不得不破坏双亲模型,从双亲委派模型中的树状结构,进一步发展成网状结构。

收藏 打印