欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

类加载器

程序员文章站 2022-05-12 11:43:08
...

什么是类加载器?

类加载器:类加载器是负责加载类的对象。将class文件(硬盘)加载到内存生成Class对象。所有的类加载器都是 java.lang.ClassLoader 的子类。

类加载器

解释上图:当我们要用一个类,这个类叫做Hello类,这个类假设不在内存中,我们现在需要用到它了,此时虚拟机就会在内存中说:内存中有没有Hello啊?内存说没有。虚拟机又说:类加载器加载一下这个Hello类,而实际中类加载器有很多;虚拟机会首先叫AppClassLoader(应用类加载器)加载一下Hello类,但是AppClassLoader在加载这个Hello类之前会去找它的父加载器ExtClassLoader(扩展类加载器)去问一下:你加载了这个Hello类吗?此时ExtClassLoader说等下,我去问一下父类BootstrapClassLoader(引导类加载器)有没有加载这个Hello类?ExtClassLoader说我没有加载这个Hello类,那么ExtClassLoader得到消息后就回复AppClassLoader类说我没有加载这个类。此时AppClassLoader类会自己去加载这个Hello类,我们就可以使用这个Hello类了。如果BootstrapClassLoader说我已经加载了Hello类了,那么就会对ExtClassLoader说:我已经加载了,拿去用,ExtClassLoader对AppClassLoader说我加载了,拿去用吧,AppClassLoader直接使用。

综上可得知:一个类在我们的虚拟机中,只允许被加载一次。

我们可以使用:类.class.getClassLoader()获得加载自己的类加载器。

那么我们现在就遇到一个问题:第一个类是从哪里来的?答:在JVM中有那么一个程序它不是java编写的,它是由c、c++编写的。我们称之为引导类加载器,这个是给它的名称而不是具体的类,所以它不是类,它是一个null,是一个空对象。

类加载器加载机制:全盘负责委托机制。

全盘负责:A类如果要使用B类(B类不在内存中),负责加载A类的加载器就需要负责把B类加载进来。谁用谁加载。

委托机制:A类加载器如果要加载资源B,必须询问父类加载是否加载。

                   如果加载,将直接使用。

                   如果没有机制,自己再加载。

采用 全盘负责委托机制 保证 一个class文件 只会被加载一次,形成一个Class对象

   注意:

         如果一个class文件,被两个类加载器加载,将是两个对象。(理解成JDK加载了一次,另一个程序也加载了一次)

          第一个加载器是A:h.getClass() -->A                第二个加载器是B: h.getClass()  -->B

          很有可能出现有提示 com.umanwu.Hello  不能强制成 com.umanwu.Hello

          会出现在自定义类加载出现可以将一个class文件加载多次。



类加载的演示:

  查看引导类加载器的内容:

package com.umanwu.classloader;

import org.junit.Test;

public class ClassLoaderDemo {

	@Test
	public void demo01() {
		// 查看引导类加载器加载的内容
		// * JDK固定配置信息,sun.boot.class.path 用于表示 引导类加载器所加载的内容
		String paths = System.getProperty("sun.boot.class.path");
		String[] allPath = paths.split(";");
		for (String p : allPath) {
			System.out.println(p);
		}
	}
}

输出的结果是:

类加载器


  查看引导类加载器加载的类型:

package com.umanwu.classloader;

import org.junit.Test;

public class ClassLoaderDemo {

	@Test
	public void demo02(){
		// 查看引导类加载器加载的类型
		ClassLoader cl = String.class.getClassLoader();
		System.out.println(cl);
	}
}

输出的结果是:null



   查看扩展类加载器的内容:

package com.umanwu.classloader;

import org.junit.Test;

import sun.net.spi.nameservice.dns.DNSNameService;

public class ClassLoaderDemo_02 {
	
	@Test
	public void demo01(){
		// 查看扩展类加载器加载的内容
		// * JDK固定配置信息,java.ext.dirs 用于表示 扩展类加载器所加载的内容
		String paths = System.getProperty("java.ext.dirs");
		String[] allPath = paths.split(";");
		for(String p : allPath){
			System.out.println(p);
		}
	}
}
输出:

类加载器

   查看扩展类加载器的类型:

package com.umanwu.classloader;

import org.junit.Test;

import sun.net.spi.nameservice.dns.DNSNameService;

public class ClassLoaderDemo_02 {
	
	@Test
	public void demo02(){
		// 查看扩展类加载器的类型:Launcher$ExtClassLoader($表示匿名内部类)
		ClassLoader cl = DNSNameService.class.getClassLoader();//JDK中随便找一个类的,需要添加允许访问规则
		System.out.println(cl);
	}

}
添加允许访问规则:

类加载器

输出:aaa@qq.com


   查看应用类加载器的内容:

package com.umanwu.classloader;

import org.junit.Test;

public class ClassLoaderDemo_03 {
	
	@Test
	public void demo01(){
		// 查看应用类加载器加载的内容: 项目/bin (编译后内容) ,自己编写类由应用类加载加载
		String paths = System.getProperty("java.class.path");
		String[] allPath = paths.split(";");
		for(String p : allPath){
			System.out.println(p);
		}
	}
}

输出:

类加载器


   查看应用类加载器加载的类型:

package com.umanwu.classloader;

import org.junit.Test;

public class ClassLoaderDemo_03 {
	
	@Test
	public void demo02(){
		ClassLoader cl = ClassLoaderDemo_03.class.getClassLoader();
		System.out.println(cl);
	}

}
输出:aaa@qq.com

三个加载器之间的关系:

package com.umanwu.classloader;

import org.junit.Test;

public class ClassLoaderDemo_04 {
	
	
	@Test
	public void demo01(){
		//3个类加载的关系
		
		ClassLoader c1 = ClassLoaderDemo_04.class.getClassLoader();
		System.out.println(c1);	//应用 (AppClassLoader)
		
		ClassLoader c2 = c1.getParent();
		System.out.println(c2);	//扩展(ExtClassLoader)
		
		ClassLoader c3 = c2.getParent();
		System.out.println(c3);	//引导(null)
	}

}
输出:

aaa@qq.com
aaa@qq.com
null


扩展:

//获得所有属性配置
Properties properties = System.getProperties();
for (String string : properties.stringPropertyNames()) {
	System.out.println(string);
}

//引导:sun.boot.class.path 用于表示引导类加载器所加载的内容
//扩展:java.ext.dirs 用于表示扩展类加载器所加载的内容
//应用:java.class.path 用于表示应用加载器所加载的内容


相关标签: 类加载器