黑马程序员_类加载器

本文详细介绍了Java虚拟机中的类加载器工作原理,包括BootStrap、ExtClassLoader和AppClassLoader的作用,类加载器的委托机制及自定义类加载器的编写方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 -------  android培训java培训、期待与您交流! ----------
类加载器:    

        Java虚拟机中可以安装多个类加载器,系统默认有三个主要的类加载器,每个类加载器负责加载特定位置的类:

        BootStrap,ExtClassLoader,AppClassLoader。

        类加载器也是Java类,因此Java类的类加载器本身也要被其他的类加载器加载,显然必须有第一个类加载器不是Java类,它就

        是BootStrap类加载器。

        Java虚拟机中的所有类装载器采用具有父子关系的树形结构进行组织,在实例化每个类装载器对象时,需要为其指定一个父级
        类装载器对象或者默认采用系统类装载器为其父级类加载。

<span style="font-size:14px;">public class ClassLoaderTest {
	public static void main(String[] args) { 
		System.out.println(ClassLoaderTest.class.getClassLoader(). 
		getClass().getName()); 
		System.out.println(System.class.getClassLoader()); 
		} 
}
</span>
        由上面的示例可以看到ClassLoaderTest类是由AppClassLoader类加载器加载的。System类是由BootStrap类加载器加载的。   
        注意:
            JVM内核启动的时候,BootStrap就已经被加载了,它是内嵌在JVM内核中的,是用C++语言编写的二进制代码,因此不需
            要其他类加载器加载。 Java虚拟机中的所有类装载器采用了具有父子关系的树形结构进行组织。
<span style="font-size:14px;">public class ClassLoaderTest {
	public static void main(String[] args) { 
		ClassLoader loader = ClassLoaderTest.class.getClassLoader(); 
		while(loader !=null){ 
			System.out.println(loader.getClass().getName()); 
			loader = loader.getParent(); 
		} 
		System.out.println(loader); 
	} 
}            
</span>
        其结果为:
            sun.misc.Launcher$AppClassLoader
            sun.misc.Launcher$ExtClassLoader
            null
        由上面的示例可以看到AppClassLoader类加载器的父级别类加载器是ExtClassLoader类加载器,ExtClassLoader类加载器的父
        级别类加载器是BootStrap类加载器。 在实例化每个类加载器对象时,需要为其指定一个父级类加载器对象或者默认采用系统
        类加载器为其父级类加载。 

类加载器的委托机制:
        当Java虚拟机要加载一个类时,
首先当前线程的类加载器去加载线程中的第一个类。如果类A中引用了类B,Java虚拟机将使
        用加载类A的类加载器来加载类B。还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。每个类
        加载器加载类时,又先委托给其上级类加载器。 当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛
        ClassNotFoundException
。      
        注意:
           
每个ClassLoader本身只能分别加载特定位置和目录中的类,但它们可以委托其他的类装载器去加载类,这就是类加载器的

            委托模式。类加载器一级级委托到BootStrap类加载器,当BootStrap无法加载当前所要加载的类时,然后才一级级回退到子

            孙类装载器去进行真正的加载。当回退到最初的类装载器时,如果它自己也不能完成类的装加载,那就会告

            ClassNotFoundException异常。

        能不能自己写个类叫java.lang.System?
            答:不能,即使写了也不会被类加载器加载。为了不让我们写System类,类加载机制采用委托机制,这样可以保证父级类
            加载器优先,也就是总是使用父级类加载器能找到的类,结果就是总是使用Java系统自身提供的System类,而不会使用我
            们自己所写的System类。

自定义类加载器的编写原理分析:

        类加载器中的loadClass方法内部实现了父类委托机制,因此我们没有必要自己覆盖loadClass,否则需要自己去实现父类委托

        机制。我们只需要覆盖findClass方法。loadClass方法中调用了findClass方法,使用的是模板设计模式。我们得到了Class文件

        后,就可以通过defineClass方法将二进制数据转换成字节码。这就是自定义类加载器的编写原理。

        需求:
            编写一个对文件内容进行简单加密的程序。
        步骤:
           
1.对生成的字节码文件进行一个字节一个字节读取,然后对读取到的字节进行加密运算。
            2.把加密后的字节读取到另外一个字节码文件中。
public class ClassLoaderAttachment {
    public String toString(){ 
	return "黑马程序员"; 
    } 
}
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

public class MyClassLoader {
    public static void main(String[] args) throws Exception{ 
	String srcPath = args[0]; 
	String destPath = args[1]+"\\"+srcPath.substring(srcPath.lastIndexOf("\\")+1,srcPath.length()); 		
        InputStream ips =new FileInputStream(srcPath); 
	OutputStream ops =new FileOutputStream(destPath); 
	encrypt(ips,ops);
	ips.close(); 
	ops.close(); 
    } 
    //对输入流数据进行加密
    public static void encrypt(InputStream ips,OutputStream ops) throws Exception{ 
	int by = 0; 
	while((by=ips.read()) != -1){ 
	    ops.write(by ^ 0xff); 
	} 
    } 
} 
public class ClassLoaderTest {
    public static void main(String[] args) { 
	System.out.println(new ClassLoaderAttachment().toString()); 
    } 
}
 ------- android培训java培训、期待与您交流! ----------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值