前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何打破双亲委派机制?

如何打破双亲委派机制?

作者头像
逍遥壮士
发布2022-06-15 12:36:22
2880
发布2022-06-15 12:36:22
举报
文章被收录于专栏:技术趋势技术趋势技术趋势

上文:jdk-Launcher源码学习


背景

上文说过,jdk是通过双亲委派机制实现类的加载,但是这个加载效率及场景存在弊端,所以本文借鉴tomcat的实现方式去打破双亲委派机制实现自定义类加载器来模似tomcat的类加载方式。

实现方式

实现思想:首先继承ClassLoader,然后通过classLoader进行重写findClass实现。

package com.classloader.simulate;

import com.encryption.demo.EncryptionUtils;
import org.apache.commons.lang.StringUtils;

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author hong
 * @version 1.0
 * @description: 模似打破双亲委派机制
 * @date 2022/4/16 18:50
 */
public class SimulateTomcatClassLoader  {

    static class MySelfClassLoader extends ClassLoader{
        /**
         * 类路劲
         **/
        private String classPath;

        public MySelfClassLoader(String classPath) {
            this.classPath = classPath;
        }

        private byte[] loadByClassName(String className) throws Exception {
            if (StringUtils.isEmpty(className)) {
                throw new Exception("类名不能为空!");
            }
            //替换路劲格式
            className = className.replaceAll("\\.", "/");
            //获取文件信息
            FileInputStream fis = new FileInputStream(classPath + "/" + className + ".class");
            //获取长度
            int len = fis.available();
            //文件信息
            byte[] data = new byte[len];
            //读写文件信息
            fis.read(data);
            fis.close();
            return data;

        }

        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            try {
                byte[] data = loadByClassName(name);
                return defineClass(name, data, 0, data.length);
            } catch (Exception e) {
                e.printStackTrace();
                throw new ClassNotFoundException();
            }
        }

        /**
         * 重写类加载方法,在这里打破双亲委派
         * @param name
         * @param resolve
         * @return
         * @throws ClassNotFoundException
         */
        @Override
        protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
            synchronized (getClassLoadingLock(name)) {
                // First, check if the class has already been loaded
                Class<?> c = findLoadedClass(name);

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    //这里重写逻辑 如果不是自定义类开头就用默认类加载器,如果是就有自定义类加载器加载
                    if(!name.startsWith("com.classloader")){
                        c = this.getParent().loadClass(name);
                    }else{
                        c = findClass(name);
                    }

                    // this is the defining class loader; record the stats
// sun.misc.PerfCounter.getParentDelegationTime().addTime(t1);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
// }
                if (resolve) {
                    resolveClass(c);
                }
                return c;
            }
        }
    }


    public void test(){
        System.out.println("测试类!");
    }

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        //获取项目路劲
        File file = new File(EncryptionUtils.class.getResource("/").getPath());
        MySelfClassLoader mySelfClaasLoader = new MySelfClassLoader(file.getPath());
        Class<?> loadClass = mySelfClaasLoader.loadClass("com.classloader.simulate.SimulateTomcatClassLoader");
        //获取实例对象
        Object obj = loadClass.newInstance();
        //获取方法列表
        Method[] declaredMethods = loadClass.getDeclaredMethods();
        System.out.println(declaredMethods);
        //获取方法
        Method method = loadClass.getMethod("test", null);
        method.invoke(obj,null);
        System.out.println(loadClass.getClassLoader().getClass().getName());;
    }
}

结果

测试类!
com.classloader.simulate.SimulateTomcatClassLoader$MySelfClassLoader

最后

很多容器都是打破Jvm的双亲委派机制来实现的,比如tomcat,如果不打破的话根据无法部署多个项目,所以打破双亲委派机制也是一种业务场景的需要。而通过了解和实现打破双亲委派机制来学习tomcat的实现,有效提升对jvm底层的实现了解。

参考文章:

https://www.jianshu.com/p/7706a42ba200

https://cwiki.apache.org/confluence/display/tomcat/FAQ

https://blog.csdn.net/lisheng5218/article/details/111475536

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-04-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 技术趋势 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档