zoukankan      html  css  js  c++  java
  • java之jvm学习笔记五(实践写自己的类装载器)

     java之jvm学习笔记五(实践写自己的类装载器)

                          课程源码:http://download.csdn.net/detail/yfqnihao/4866501

                          前面第三和第四节我们一直在强调一句话,类装载器和安全管理器是可以被动态扩展的,或者说,他们是可以由用户自己定制的,今天我们就是动手试试,怎么做这部分的实践,当然,在阅读本篇之前,至少要阅读过笔记三。

                         下面我们先来动态扩展一个类装载器,当然这只是一个比较小的demo,旨在让大家有个比较形象的概念。

                          第一步,首先定义自己的类装载器,从ClassLoader继承,重写它的findClass方法,至于为什么要这么做,大家如果看过笔记三就知道,双亲 委托模式下,如果parent没办法loadClass,bootStrap也没把办法loadClass的时候,jvm是会调用ClassLoader 对象或者它子类对象的findClass来装载。

    1. package com.yfq.test;  
    2.   
    3. import java.io.File;  
    4. import java.io.FileInputStream;  
    5. import java.io.FileNotFoundException;  
    6. import java.io.IOException;  
    7.   
    8.   
    9. public class MyClassLoader extends ClassLoader {  
    10.   
    11.     @Override  
    12.     protected Class<?> findClass(String name) throws ClassNotFoundException {  
    13.         byte[] data = getByteArray(name);    
    14.         if (data == null) {    
    15.             throw new ClassNotFoundException();    
    16.         }    
    17.         return defineClass(name, data, 0, data.length);   
    18.     }  
    19.       
    20.       
    21.     private byte[] getByteArray(String name){  
    22.         String filePath =   name.replace(".", File.separator);  
    23.         byte[] buf = null;  
    24.         try {  
    25.             FileInputStream in = new FileInputStream(filePath);  
    26.             buf = new byte[in.available()];  
    27.             in.read(buf);  
    28.         } catch (FileNotFoundException e) {  
    29.             e.printStackTrace();  
    30.         } catch (IOException e) {  
    31.             e.printStackTrace();  
    32.         }  
    33.         return buf;  
    34.     }  
    35.   
    36. }  

    第二步,定义一个类,专门用于被装载,这里我们定义了一个静态代码块,待会用到它

    1. package com.yfq.test;  
    2.   
    3. public class TestBeLoader {  
    4.     static{  
    5.         System.out.println("TestBeLoader init");  
    6.     }  
    7.     public void sayHello(){  
    8.         System.out.println("hello");  
    9.     }  
    10. }  

    第三步,定义一个有main函数入口的public类来做验证

    1. package com.yfq.test;  
    2.   
    3. public class TestClassLoaderDemo {  
    4.     public static void main(String[] args) throws InstantiationException, IllegalAccessException {  
    5.         Class thisCls = TestClassLoaderDemo.class;  
    6.         MyClassLoader myClassLoader = new MyClassLoader();  
    7.         System.out.println(thisCls.getClassLoader());  
    8.         System.out.println(myClassLoader.getParent());  
    9.         try {  
    10.             //用自定义的类装载器来装载类,这是动态扩展的一种途径  
    11.             Class cls2 = myClassLoader.loadClass("com.yfq.test.TestBeLoader");  
    12.             System.out.println(cls2.getClassLoader());  
    13.             TestBeLoader test=(TestBeLoader)cls2.newInstance();  
    14.         } catch (ClassNotFoundException e) {  
    15.             e.printStackTrace();  
    16.         }  
    17.     }  
    18. }  


    第四步,查看运行结果

    sun.misc.Launcher$AppClassLoader@19821f
    sun.misc.Launcher$AppClassLoader@19821f
    sun.misc.Launcher$AppClassLoader@19821f
    TestBeLoader init
    说明:

            第一个输出:装载TestClassLoaderDemo的类是AppClassLoder

           第二个输出:装载myClassLoader的装载器也是AppClassLoader,这里也验证了我们笔记三讲的,在同个线程中,动态连接模式会运用当前线程的类加载器来加载所需的class文件,因为第一个和第二个输出是同一个对象的对象名

           第三个输出:是TestBeLoader的类加载器,这个输出验证了,双亲委托模式下的动态连接模式,由于 myClassLoader是由AppClassLoader装载的,所以它会委托自己的parent来装载 com.yfq.test.TestBeLoader这个类,加载成功所以就不再调用自己的findClass方法,这个我们在笔记三有做过简要的讨论。

           第四个输出:如果我们将TestBeLoader test=(TestBeLoader)cls2.newInstance();这句话注掉,则不会有第四个输出,为什么?

                                 类的装载大致分为三步,装载,连接,初始化。而初始化这一步,是在我们第一次创建对象的时候才进行初始化分配内存,这一点需要注意,并不是class被load内存后就立刻初始化。

          

  • 相关阅读:
    ESLint 规则详解(一)
    我为什么不看好微信小程序
    两分钟实现安全完备的登录模块
    基于大数据的用户行为预测在前端性能优化上的应用
    《深入浅出NodeJS》mindmap
    如何设计一个异步Web服务——任务调度
    如何设计一个异步Web服务——接口部分
    【技能】眼镜清洗,如何不用眼镜布让眼镜一尘不染?
    【技能】小白耳机维修入门--各种耳机插头接线图--耳机维修汇总贴
    【电脑skill】怎么关闭wps热点?永久关闭wps右下角弹窗的方法!
  • 原文地址:https://www.cnblogs.com/timssd/p/4790477.html
Copyright © 2011-2022 走看看