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内存后就立刻初始化。

          

  • 相关阅读:
    numpy 基础 —— np.linalg
    图像旋转后显示不完全
    opencv ---getRotationMatrix2D函数
    PS1--cannot be loaded because the execution of scripts is disabled on this system
    打开jnlp Faild to validate certificate, the application will not be executed.
    BATCH(BAT批处理命令语法)
    oracle vm virtualbox 如何让虚拟机可以上网
    merge 实现
    Windows batch,echo到文件不成功,只打印出ECHO is on.
    python2.7.6 , setuptools pip install, 报错:UnicodeDecodeError:'ascii' codec can't decode byte
  • 原文地址:https://www.cnblogs.com/timssd/p/4790477.html
Copyright © 2011-2022 走看看