zoukankan      html  css  js  c++  java
  • Java自定义类加载和ClassPath类加载器

    1 自定义类加载器:

    实现规则: 自定义类加载器,需要重写findClass,然后通过调用loadClass进行类加载(loadClass通过递归实现类的双亲委派加载)

    package com.daxin;
    
    import java.io.*;
    
    /**
     * 自定义类加载器,需要重写findClass,然后通过调用loadClass进行类加载(loadClass通过递归实现类的双亲委派加载)
     */
    public class MyClassLoader extends ClassLoader {
    
        /**
         * 设置类的路径
         */
        private String root;
    
    
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            byte[] classData = loadClassData(name);
            if (classData == null) {
                throw new ClassNotFoundException();
            } else {
                return defineClass(name, classData, 0, classData.length);
            }
        }
    
        private byte[] loadClassData(String className) {
            String fileName = root + File.separatorChar
                    + className.replace('.', File.separatorChar) + ".class";
            InputStream ins = null;
            try {
                ins = new FileInputStream(fileName);
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                int bufferSize = 1024;
                byte[] buffer = new byte[bufferSize];
                int length = 0;
                while ((length = ins.read(buffer)) != -1) {
                    baos.write(buffer, 0, length);
                }
                return baos.toByteArray();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    ins.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    
            return null;
        }
    
    
        public void setRoot(String root) {
            this.root = root;
        }
    
        public static void main(String[] args) {
    
            MyClassLoader classLoader = new MyClassLoader();
            classLoader.setRoot("C:\temp");
    
            Class<?> testClass = null;
            try {
                testClass = classLoader.loadClass("com.daxin.classloader.StaticClassDemo");
                Object object = testClass.newInstance();
                System.out.println(object.getClass().getClassLoader());
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

    2 自定义ClassPath类加载器:

    类加载器的继承关系图:

    ClassPath类加载器实现源码:

    package org.apache.loadjar;
    
    import java.io.BufferedReader;
    /** 
     * 
     * 
     */
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.lang.reflect.Method;
    import java.net.URL;
    import java.net.URLClassLoader;
    import java.util.ArrayList;
    import java.util.List;
    
    public final class ExtClassPathLoader {
    
        private static Method addURL = initAddMethod();
    
        public static URLClassLoader classloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
    
        /**
         * 初始化addUrl 方法.
         * 
         * @return 可访问addUrl方法的Method对象
         */
        private static Method initAddMethod() {
            try {
                // 反射获取addURL方法
                Method add = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class });
                // 设置访问权限
                add.setAccessible(true);
                return add;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        /**
         * 加载jar classpath。
         */
        public static void loadClasspath() {
            List<String> files = getJarFiles();
            if (files == null)
                return;
            for (String f : files) {
                loadClasspath(f);
            }
    
            List<String> resFiles = getResFiles();
            if (resFiles == null)
                return;
            for (String r : resFiles) {
                loadResourceDir(r);
            }
        }
    
        private static void loadClasspath(String filepath) {
            File file = new File(filepath);
            loopFiles(file);
        }
    
        private static void loadResourceDir(String filepath) {
            File file = new File(filepath);
            loopDirs(file);
        }
    
        /** */
        /**
         * 循环遍历目录,找出所有的资源路径。
         * 
         * @param file
         *            当前遍历文件
         */
        private static void loopDirs(File file) {
            // 资源文件只加载路径
            if (file.isDirectory()) {
                addURL(file);
                File[] tmps = file.listFiles();
                for (File tmp : tmps) {
                    loopDirs(tmp);
                }
            }
        }
    
        /**
         * 循环遍历目录,找出所有的jar包。
         * 
         * @param file
         *            当前遍历文件
         */
        private static void loopFiles(File file) {
            if (file.isDirectory()) {
                File[] tmps = file.listFiles();
                for (File tmp : tmps) {
                    loopFiles(tmp);
                }
            } else {
                if (file.getAbsolutePath().endsWith(".jar") || file.getAbsolutePath().endsWith(".zip")) {
    
                    addURL(file);
                }
            }
        }
    
        /**
         * 通过filepath加载文件到classpath。
         * 
         * @param filePath
         *            文件路径
         * @return URL
         * @throws Exception
         *             异常
         */
        private static void addURL(File file) {
            try {
                addURL.invoke(classloader, new Object[] { file.toURI().toURL() });
            } catch (Exception e) {
            }
        }
    
        /**
         * 
         * 将当前classpath下jar.txt的清单jar明见加载到classpath中
         * 
         * @return
         * @throws Exception
         */
        private static List<String> getJarFiles() {
            // TODO 从properties文件中读取配置信息 如果不想配置 可以自己new 一个List<String> 然后把 jar的路径加进去
            // 然后返回
            InputStream in = ClassLoader.getSystemResourceAsStream("jar.txt");
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String line = null;
            List<String> list = new ArrayList<String>();
            try {
                line = br.readLine();
                while (line != null) {
                    list.add(line);
                    line = br.readLine();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (br != null)
                        br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    
            return list;
        }
    
        /**
         * 从配置文件中得到配置的需要加载classpath里的资源路径集合
         * 
         * @return
         */
        private static List<String> getResFiles() {
            // TODO 从properties文件中读取配置信息略 如果不想配置 可以自己new 一个List<String> 然后把
            // jar的路径加进去 然后返回 额 如果没有资源路径为空就可以了
            return null;
        }
    
    
    }

    使用示例:

    package org.apache.action;
    
    import java.io.BufferedReader;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.URLClassLoader;
    
    import org.apache.loadjar.ExtClassPathLoader;
    
    
    
    /**
     * 
     * 
     * @date 2017年8月14日 下午9:13:40
     * 
     */
    public class MainClassLoaderTest {
        public static void main(String[] args)
                throws InstantiationException, IllegalAccessException, ClassNotFoundException, Exception {
    
    
            
            ExtClassPathLoader.loadClasspath();
            
            System.out.println((URLClassLoader)ExtClassPathLoader.classloader);
            
    //        StringUtils su =new StringUtils();
    //        su.sayHello();
    ////         
    //        System.out.println(su.getClass().getClassLoader());
             
            
            
        }
    
    }
    
    // ExtClasspathLoader.loadClasspath();
    //
    //ExtClasspathLoader.loadClasspath("C:\Users\Daxin\Desktop\myjar.jar");
    //
    //StringUtils su = new StringUtils();
    //
    //su.sayHello();
    //
    //su.saySomeThing("I am daxin!");
    
    
    
    //只会读取第一行
    //ClassLoader.getSystemResource("jar.txt");
    //InputStream in = ClassLoader.getSystemResourceAsStream("jar.txt");
    //BufferedReader br =new BufferedReader(new InputStreamReader(in));
    //System.out.println(br.readLine());
  • 相关阅读:
    POJ 1320 Street Numbers 解佩尔方程
    数学分支(转)
    深入理解Java类加载器(1):Java类加载原理解析
    Java类加载器的工作原理
    深入理解Java:类加载机制及反射
    类加载机制:全盘负责和双亲委托
    java底层学习
    代码面试最常用的10大算法
    程序员面试金典算法题
    了解ASCII、gb系列、Unicode、UTF-8的区别
  • 原文地址:https://www.cnblogs.com/leodaxin/p/7707766.html
Copyright © 2011-2022 走看看