类加载

作者: 你值得拥有更好的12138 | 来源:发表于2019-01-04 22:17 被阅读0次

    图片与代码引用他人,侵权请告知。

    类加载的时机:

    1.new关键字
    2.get,set静态变量
    3.反射
    4.使用子类时,发现父类没有初始化时
    5.调用静态方法时。
    6.程序入口类。
    

    类的加载过程:

    加载,验证,准备,解析,初始化。
    

    双亲委派模式:

    image
    1.启动类加载器:
        JAVA_HOME/lib目录下的jar
    2.扩展类加载器:
        JAVA_HOME/lib/ext目录下的jar
    3.应用程序类加载器:
        加载构建工具指定的classpath目录
    4.自定义类加载器
    

    从下至上,在加载前都要询问父类加载器是否可以加载。这样就保证了,父类加载的都是子类需要的基础类。当父类表示超出加载范围,那么子类再去加载。这样就保证了同一类在系统就只会出现一次。
    以上的父子关系是通过组合复用父类代码实现的,不是继承实现的。
    如果输出类加载器是null是最顶上的加载器。
    如果构造同包名,同类名的类,编译器导包导不到自定义的包。

    列外的情况:(不使用双亲委派模式)

    热加载模式
    当前线程加载器应对Native代码调用用户代码的情况。
    

    列子:

    自定义加载器的使用场景:
        当你需要加密你的字节码的时候,或者你的字节码在网络上或者数据库中时。
    
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.nio.ByteBuffer;
    import java.nio.channels.Channels;
    import java.nio.channels.FileChannel;
    import java.nio.channels.WritableByteChannel;
    
    public class MyClassLoader extends ClassLoader
    {
        public MyClassLoader()
        {
            
        }
        
        public MyClassLoader(ClassLoader parent)
        {
            super(parent);
        }
        
        protected Class<?> findClass(String name) throws ClassNotFoundException
        {
            File file = new File("D:/People.class");
            try{
                byte[] bytes = getClassBytes(file);
                //defineClass方法可以把二进制流字节组成的文件转换为一个java.lang.Class
                Class<?> c = this.defineClass(name, bytes, 0, bytes.length);
                return c;
            } 
            catch (Exception e)
            {
                e.printStackTrace();
            }
            
            return super.findClass(name);
        }
        
        private byte[] getClassBytes(File file) throws Exception
        {
            // 这里要读入.class的字节,因此要使用字节流
            FileInputStream fis = new FileInputStream(file);
            FileChannel fc = fis.getChannel();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            WritableByteChannel wbc = Channels.newChannel(baos);
            ByteBuffer by = ByteBuffer.allocate(1024);
            
            while (true){
                int i = fc.read(by);
                if (i == 0 || i == -1)
                break;
                by.flip();
                wbc.write(by);
                by.clear();
            }
            fis.close();
            return baos.toByteArray();
        }
    }
    

    相关文章

      网友评论

          本文标题:类加载

          本文链接:https://www.haomeiwen.com/subject/bellrqtx.html