黑马程序员——java的类加载器

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

类加载器的作用
当我们编写出java文件时就有,经过java编译器的编写之后转回成class文件,当我们用到某一class类时,就要把该类的字节码加载进内存才可以用,而这一加载的过程就要通过类加载器完成,也就是说java类通过类加载器加载进内存。

类加载器的结构
Java 中的类加载器大致可以分成两类,一类是系统提供的,另外一类则是由 Java 应用开发人员自定义编写的。系统提供的类加载器主要有下面三个:

BootStrap:在java虚拟机启动的时候会利用这个类加载器来加载 JDK安装目录下的 /JRE/LIB/rt.jar 也就是系统默认导入的一些类例如System类,这个类加载器不是类 。只是作为一个java中类的起源工具,没有父类加载器。

ExpClassLoader:这个类加载器加载JDK安装目录的/JRE/LIB/ext目录中的类 我们只要把我们的类打包成JAR包放在这里即可。

AppClassLoader:我们在java程序中classpath对应的类都有这个AppClassLoader导入进来。

类加载器间的关系:
类加载器与java类有着类似的关系,每一个java类都有父类,而Object是所有java类的父类,自身没有父类。同Object是所有类的父类一样,BootStrap是所用加载器的父类,自身是根加载器,没有父类加载器,除了BootStrap不是java类以外,其他的类加载器都是java类,ExpClassLoader的父类加载器是BootStrap,AppClassLoader的父类加载器是ExpClassLoader,每一个加载器都有指定加载目录,自定义的加载器在编写时要指定父加载器或者用默认的父加载器。这样我们就可以知道类加载器是一个树状组织结构。
这里写图片描述

练习代码:

/*
 * 打印GenericTest的加载器以及父类的以上的加载器
 */
public class GenericTest {

    public static void main(String[] args) {
        //获得本类的加载器
        ClassLoader loader=GenericTest.class.getClassLoader();
        //打印父类类以上的加载器
        while(loader !=null)
        {
            System.out.println(loader);
            loader = loader.getParent();
        }
        //打印根类加载器
// 因为根类加载器不是java类,所以为null
        System.out.println(loader);

    }
}

运行效果:
这里写图片描述

委托机制
某一个类一般会用当前线程的类加载器加载该类,也可以指定类加载器加载一个类,类加载器通过委托机制加载类,如A类指定B加载器加载,B不会马上加载该类,会把加载的任务交给父类加载器加载,同样父类加载器会把加载任务交给下一个父类加载器,直到根加载器,因为根加载器么有父类加载器,所用他会尝试加载A类,因为每一个加载器都会指定加载类的目录,当在根目录不存在A类时,根加载器加载失败,根加载器会把加载任务给他的子加载器,子加载器会尝试加载,如果能够加载,此次加载完成,如果还是加载失败,会把加载任务继续给下一个子加载器,直到加载成功,当所用的父加载器都无法加载时,B加载器会尝试加载,如果B加载器加载失败,那么此次的类加载失败,程序报错。这就是类加载器的委托机制。

那为什么要用委托机制,用委托机制的好处?
方便管理,如果A加载器与B加载器是C加载器的子加载器,当一个L类同时能够被三个加载器加载时,A加载器加载了L,因为B加载器不知道L已经加载,可能会再次对L进行加载,这样就类被多次加载,用委托机制,只能有C加载器能够加载L类,避免了类的多次多次加载,有效地管理了类的加载。

自定义类加载器
定义加载器要求继承ClassLoader 并重写findClass方法。

ClassLoader类部分方法:
defineClass(byte[] b, int off, int len)
将一个 byte 数组转换为 Class 类的实例。
findClass(String name):
使用指定的二进制名称查找类。
findLoadedClass(String name):
如果 Java 虚拟机已将此加载器记录为具有给定二进制名称的某个类的启动加载器,则返回该二进制名称的类。
自定义加载器利用了模板设计模式,findLoadedClass方法会找父类的加载器加载类,当加载不成功,会调用findClass方法加载class文件,把得到的二进制代码返回到defineClass方法中,该方法会把二进制代码转换成class的字节码加载进内存,所以我们只有重写findClass方法,通过自定义的方法读入class文件的二进制代码。

class NetworkClassLoader extends ClassLoader {
         String host;
         int port;

         public Class findClass(String name) {
             byte[] b = loadClassData(name);
             return defineClass(name, b, 0, b.length);
         }

         private byte[] loadClassData(String name) {
             // load the class data from the connection
              . . .
         }
     }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值