zoukankan      html  css  js  c++  java
  • Java 理解类加载过程 -- 自定义加载器

    类加载器可以看下我的收藏:

      https://www.cnblogs.com/dongguacai/p/5879931.html

    现在准备一个字节码文件:

    自定义加载器:

     1 package com.xzlf.test;
     2 
     3 import java.io.ByteArrayOutputStream;
     4 import java.io.FileInputStream;
     5 import java.io.IOException;
     6 import java.io.InputStream;
     7 
     8 /**
     9  * 自定义类加载器
    10  * 
    11  * @author xzlf
    12  *
    13  */
    14 public class MyClassLoader extends ClassLoader {
    15     // 类加载器查找的根目录
    16     private String rootDir;
    17 
    18     public MyClassLoader(String rootDir) {
    19         super();
    20         this.rootDir = rootDir;
    21     }
    22 
    23     @Override
    24     protected Class<?> findClass(String name) throws ClassNotFoundException {
    25         // 查看 c 是否已经被加载
    26         Class<?> c = findLoadedClass(name);
    27         if(c != null) {
    28             // 已经加载直接返回
    29             return c;
    30         }else {
    31             // 没有被加载,先委派给父类加载器, 最终会委派到引导类加载器
    32             ClassLoader parent = this.getParent();
    33             try {
    34                 c = parent.loadClass(name);
    35             } catch (ClassNotFoundException e) {
    36                 //e.printStackTrace();
    37             }
    38             // 如果父类加载器已加载则直接返回,如果没有加载则使用自定加载器加载类的字节码文件
    39             if(c != null) {
    40                 return c;
    41             }else {
    42                 // 获取字节码文件
    43                 byte[] classDatas = getClassData(name);
    44                 if(classDatas == null) {
    45                     throw new ClassNotFoundException();
    46                 }else {
    47                     //Converts an array of bytes into an instance of class
    48                     c = defineClass(name, classDatas, 0, classDatas.length);
    49                 }
    50             }
    51         }
    52         return c;
    53     }
    54 
    55     // 获取字节码文件
    56     private byte[] getClassData(String name) {
    57         //com.test.A --> f:/mycode/  com/test/A.class
    58         String path = rootDir + "/" + name.replace('.', '/') + ".class";
    59         
    60         // IO 操作 返回字节码
    61         InputStream is = null;
    62         ByteArrayOutputStream bos = new ByteArrayOutputStream();
    63         try {
    64             is = new FileInputStream(path);
    65             byte[] flush = new byte[1024];
    66             int len;
    67             while((len = is.read(flush)) != -1) {
    68                 bos.write(flush, 0, len);
    69             }
    70             return bos.toByteArray();
    71         } catch (Exception e) {
    72             e.printStackTrace();
    73         }finally {
    74             if(bos != null) {
    75                 try {
    76                     bos.close();
    77                 } catch (IOException e) {
    78                     e.printStackTrace();
    79                 }
    80             }
    81             if(is != null) {
    82                 try {
    83                     is.close();
    84                 } catch (IOException e) {
    85                     e.printStackTrace();
    86                 }
    87             }
    88         }
    89         return null;
    90     }
    91 }

    测试代码:

     1 package com.xzlf.test;
     2 
     3 public class TestClassLoader {
     4     public static void main(String[] args) throws Exception {
     5         MyClassLoader loader1 = new MyClassLoader("f:/mycode");
     6         MyClassLoader loader2 = new MyClassLoader("f:/mycode");
     7         
     8         Class<?> c1 = loader1.loadClass("com.test.Welcome");
     9         Class<?> c2 = loader1.loadClass("com.test.Welcome");
    10         Class<?> c3 = loader2.loadClass("com.test.Welcome");
    11         
    12         Class<?> c4 = loader2.loadClass("java.lang.String");
    13         Class<?> c5 = loader2.loadClass("com.xzlf.test.MyClassLoader");
    14         
    15         // 自定义加载器
    16         System.out.println("c1-->" + c1.hashCode() + "-->" + c1.getClassLoader());
    17         System.out.println("c2-->" + c2.hashCode() + "-->" + c2.getClassLoader());
    18         
    19         // 同一个类,被不同的加载器加载,JVM认为也是不相同的类
    20         System.out.println("c3-->" + c3.hashCode() + "-->" + c3.getClassLoader());
    21         
    22         // 引导加载器
    23         System.out.println("c4-->" + c4.hashCode() + "-->" + c4.getClassLoader());
    24         
    25         // 应用加载器
    26         System.out.println("c5-->" + c5.hashCode() + "-->" + c5.getClassLoader());
    27     }
    28 }
    
    

    运行测试:

     

    重视基础,才能走的更远。
  • 相关阅读:
    spring websocket 记录
    mysql-enum
    再问jvm内存管理
    video相关参数、操作和事件
    监听页面关闭和刷新的总结
    VUE路由新页面打开的方法总结
    VUE的一个数据绑定与页面刷新相关的bug
    element-ui笔记
    Vue笔记(props和 mounted)
    Python总结(二)
  • 原文地址:https://www.cnblogs.com/xzlf/p/12687062.html
Copyright © 2011-2022 走看看