Java自定义类加载器实战

本文介绍了在项目Q和D中遇到的Mesos与Hadoop Protobuf版本冲突,以及不同Hadoop组件版本冲突问题。为解决这些问题,作者深入探讨了Java类加载的原理,包括Bootstrap、Extension和Application类加载器,并详细阐述了双亲委派模型。通过自定义类加载器,实现了从特定目录加载jar包以避免冲突。文中提供了两种使用自定义加载类的方法:面向接口编程和反射调用。
摘要由CSDN通过智能技术生成

在项目Q中,使用Mesos进行资源隔离和任务调度。调度的任务类型包括一些Hadoop相关任务,在某次升级Hadoop集群之后,这些任务出错,跟踪日志发现是Mesos和Hadoop依赖的Protobuf版本出现了冲突,升级或降级Protobuf都不能解决问题。同时,在另外一个负责数据传输的项目D中,随着数据传输场景的多样化,项目D开始要和不同类型的输入输入打交道,包括不同版本的Hdfs、HBase和Hive集群等,同样出现了各种jar包冲突问题。按照经验,此类问题适合使用自定义类加载器来解决,但一路下来,磕磕碰碰踩了不少坑,记录下来。

原理学习

所谓类加载,就是虚拟机通过类名称获取类的二进制字节流,然后在方法区中生成代表这个类的Class对象的过程,而开发人员自定义类加载器能控制的就是如何获取字节流方式进行加载这一步。当然一个类能够被使用,还必须经过链接(验证+准备+解析)和初始化(clinit静态变量初始化和运行静态语句块)。

类加载过程

java提供了三种类加载器:
1. Bootstrap启动类加载器,负责加载jdk_home/lib目录下的核心api类。
2. Extension扩展类加载器,负责加载jdk_home/lib/ext目录下的jar包或-Djava.ext.dirs指定目录下jar包。
3. Application应用类加载器,负责加载用户类路径ClassPath下jar包。

其中,用户自定义类加载器的父类加载起是3,3的父是2,2的父是1。。。类加载过程使用双亲委派模型,即先交给父类加载器去加载,只有父类加载器无法加载再交给子类去完成,最后才会由用户自定义类加载器来加载。

源码分析

首先注意的是父类加载器是父“类加载器”而不是“父类”加载器,即双亲委派不是通过继承关系实现的,扩展类加载器和应用类加载器都是URLClassLoader的子类。

这里写图片描述
这里写图片描述

双亲关系通过parent成员变量在构造函数中初始化:

public abstract class ClassLoader {
   
    // The parent class loader for delegation
    // Note: VM hardcoded the offset of this field, thus all new fields
    // must be added *after* it.
    private final ClassLoader parent;
    ……
}

委派加载流程在loadClass方法中实现:

protected Class<?> loadClass(String name,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值