前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ClassLoad

ClassLoad

作者头像
名字是乱打的
发布2022-05-13 11:00:17
3100
发布2022-05-13 11:00:17
举报
文章被收录于专栏:软件工程
类从编译到执行经历的的过程

➢编译器将Robot.java源文件编译为Robot.class字节码文件 ➢ClassLoader将字节码转换为JVM中的Class <Robot>对象 ➢JVM利用Class <Robot>对象实例化为Robot对象

ClassLoader

Classloader在Java中有着非常重要的作用 它主要工作在Class装载的加载阶段,所有的Class都是由ClassLoader进行加载的,ClassLoader负责通过将Class文件里的二进制数据流或者是从系统外部获得Class二进制数据流装载进系统,然后交给Java虚拟机进行连接、初始化等操作。

ClassLoader的种类
  • BootStrapClassLoader:C++编写,java的核心自带类库的java.* (用户不可见除非看JVM代码)
  • ExtClassLoader:Java编写,扩展库javax.*
  • AppClassLoader:Java编写,加载程序所在目录主要加载我们的src程序代码
  • 自定义ClassLoader:Java编写,定制化加载
ClassLoader的源码和解析过程分析:

ClassLoader里面包含了许多方法制定了加载流程和方式

其中loadClass是比较重要的,可以根据类名查找当前ClassLoader是否加载了该class,如果有的话就返回类的class实例,找不到就会返回null

手写classloader关键

代码语言:javascript
复制
手写ClassLoader
package jvm;

import java.io.*;

public class MyClassLoader extends ClassLoader{
    private String path;
    private String MyClassLoaderName;//定义自己的ClassLoader名字 实际上没啥用

    public MyClassLoader(String path, String MyClassLoaderName) {
        this.path = path;
        this.MyClassLoaderName = MyClassLoaderName;
    }
    @Override
    //用于寻找类文件
    public Class findClass(String name){
        byte[] b=loadClassData(name);
        return  defineClass(name,b,0,b.length);
    }

    //用于加载class文件为字节码
    private byte[] loadClassData(String name) {
        String url=path+name+".class";
        InputStream inp=null;
        ByteArrayOutputStream out=null;
        try {
            inp=new FileInputStream(new File(url));
            out=new ByteArrayOutputStream();
            int i=0;
            while ((i=inp.read())!=-1){
                out.write(i);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
           try{
               out.close();
               inp.close();
           }catch (Exception e)
           {
               e.printStackTrace();
           }
        }
        return out.toByteArray();
    }

}
代码语言:javascript
复制
package jvm;

public class ClassLoaderCheck {
    public static void main(String[] args) throws Exception {
        MyClassLoader myl=new MyClassLoader("C:\\Users\\Zyh\\Desktop\\","ZyhClassLoader");//我的桌面C:\\Users\\Zyh\\Desktop\\上有个ClassTest.class文件,ZyhClassLoader没有啥左右就是给我的classloader起个名字而已
        Class c = myl.loadClass("ClassTest");
        System.out.println(c.getClassLoader());
        c.newInstance();
    }
}
为什么我们要手写ClassLoader,有什么好处呢?

可以加载任意字节流,比如访问远程网络加载二进制流并生成我们需要的类 我们也可以对某些敏感的class进行加密,自定义findClass()进行解密处理

ClassLoader的双亲委派机制
双亲委派模型的工作过程是:
  • 如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成。
  • 每一个层次的类加载器都是如此。因此,所有的加载请求最终都应该传送到顶层的启
  • 只有当父加载器反馈自己无法完成这个加载请求时(搜索范围中没有找到所需的类),子加载器才会尝试自己去加载。
为什么要使用双亲委派机制去加载类
  • 避免一个class被多次装载
  • 父类加载器已经加载过的类,不用再次加载,而且对于一些系统类,用户自定义的不起作用了,有一定安全保证。
类加载方式

隐式加载:new 显式加载:loadClass,forName等

类加载过程
loadClass和forName的区别
  • Class.forName得到的class是已经初始化完成的
  • Classloder.loadClass得到的class是还没有链接的

举例子:

forName是执行了初始化的有时候我们需要得到已经初始化的class比如注册mysql驱动

有时候我们为了加快初始化速度会使用lazy-load(比如springIOC读取bean的配置文件),而使用ClassLoader不用进行链接和初始化省去执行static方法等的时间花费,加快加载速度,等需要时候再进行使用

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-05-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 类从编译到执行经历的的过程
  • ClassLoader
  • 手写classloader关键
    • 为什么我们要手写ClassLoader,有什么好处呢?
      • ClassLoader的双亲委派机制
        • 双亲委派模型的工作过程是:
      • 为什么要使用双亲委派机制去加载类
        • 类加载方式
          • 类加载过程
            • loadClass和forName的区别
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档