首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Class文件的加载过程

Class文件的加载过程

作者头像
@派大星
发布2023-06-28 11:06:26
发布2023-06-28 11:06:26
8420
举报
文章被收录于专栏:码上遇见你码上遇见你

一个class文件是如何从硬盘到内存,并且开始准备执行。

一共分为三大步:loading->linking->initializing

细化分为:

loading:将class load到内存里面(双亲委派)

verification:校验

preparation:面试可能问-(把class文件赋默认值)

resolution:class文件常量池里面的符号引用转换成直接的内存地址 直接能访问到的内容

initializing:静态变量赋值为初始值

类加载器:classLoader

Bootstrap类加载器在获取时会显示null 因为它是C++实现的 Java没有与其对应的class。

一个class文件load到内存中实际有两块内容:

· 把二进制的文件扔到内存中(这块内容在metaSpace(1.8之后)需要看JVM实现)

· 与此同时生成了class类的对象,这个class对象指向了上面那一块内容

Tips:加载器的加载器是不是就是它的parent 不是 不是 不是

parent是加载类的过程中需要查找的一个层次关系,至于parent是被谁加载的是两回事

父加载器不是类加载器的加载器 也不是类加载器的父类加载器

类加载过程:

说到class加载过程就要提到双亲委派机制:

双亲委派是一个孩子向父亲方向,然后父亲向孩子方向的双亲委派过程

为什么要有双亲委派:其实是主要为了安全问题 次要是避免再次加载

所有的类加载器都是Launcher的内部类

我们加载类的时候需要先调用loadclass方法,loadclass方法调用了重载的loadClass方法 需不需要解析 把符号引用直接转换为直接访问的地址 并且加载的时候加锁了(sychronized) 这里会检查是不是已经load进来了(findLoadedClass 再往下就是hospot源码了) 如果load进来了直接返回 如果没有load进来 会调用parentload (这就是双亲委派的过程_其实parent也是先findloadedclass 如果找不到也是调用parent 类似于递归调用,这里的parent 是final修饰的 修改不了);

如果都没有找到,父加载器也没有加载成功,只能由我自己去加载,这里面调用了findClass(proctected修饰 只实现了一句话throw ClassNotFoundException ) 只可以在子类去自己去实现。所以自定义classloader只需要重写findClass 即可 这个模式是模板模式方法

这个模式是模板模式方法

什么时候我们需要加载一个类呢?

spring的某个class spring会给你生成动态代理 这个动态代理是一个新的class 当你要用的时候 spring会给你偷偷的load到内存里面

Jrebel热部署 需要一个classloader 将类load内存里面

自定义类加载器:

代码语言:javascript
复制
public class customizeClassLoaderextends ClassLoader {

    @Override
    protectedClass<?> findClass(String name) throws ClassNotFoundException {
        File f = new File("c:/test/", name.replace(".", "/").concat(".class"));
        try {
            FileInputStream fis = new FileInputStream(f);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            int b = 0;

            while ((b=fis.read()) !=0) {
                baos.write(b);
            }

            byte[] bytes = baos.toByteArray();
            baos.close();
            fis.close();//可以写的更加严谨

            return defineClass(name, bytes, 0, bytes.length);
        } catch (Exception e) {
            e.printStackTrace();
        }
        returnsuper.findClass(name); //throws ClassNotFoundException
    }

    publicstatic void main(String[] args) throws Exception {
        ClassLoaderl = new customizeClassLoader();
        Class clazz = l.loadClass("com.test.jvm.Hello");
        Class clazz1 = l.loadClass("com.test.jvm.Hello");

        System.out.println(clazz == clazz1);

        Hello h = (Hello)clazz.newInstance();
        h.m();

        System.out.println(l.getClass().getClassLoader());
        System.out.println(l.getParent());

        System.out.println(getSystemClassLoader());
    }
}

lazyLoading JVM并没有规定什么时候加载,但是严格规定了什么时候必须初始化

newgetstatic putstatic invokestatic 访问final变量除外

Java.lang.reflect对雷进行反射调用时

初始化子类的时候 父类首先初始化

虚拟机启动的时候 被执行的主类必须初始化

动态语言支持java.lang.invoke.methodHandle解析的结果为REF_getstatic REF_putstatic REF_invokestatic的方法句柄时 该类必须初始化

代码语言:javascript
复制
代码语言:javascript
复制
package com.example.demo.test;



/**

 * @ClassName testLazyLoading

 * @Description TODO

 * @Author zbw

 * @Date 4/13/20214:00 PM

 **/





public class testLazyLoading { //严格讲应该叫lazy initialzing,因为java虚拟机规范并没有严格规定什么时候必须loading,但严格规定了什么时候initialzing

    public static void main(String[] args) throws Exception {

        //P p;

        //X x = new X();

        //System.out.println(P.i);

        //System.out.println(P.j);

        Class.forName("com.mashibing.jvm.c2_classloader.T008_LazyLoading$P");



    }



    public static class P {

        final static int i = 8;

        static int j = 9;

        static {

            System.out.println("P");

        }

    }



    public static class X extends P {

        static {

            System.out.println("X");

        }

    }

}

Class.forName("com.mashibing.jvm.c2_classloader.T008_LazyLoading$P");

这里面的 :由于P是当前类的内部类所以访问他需要外部类++内部类的名字

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-04-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码上遇见你 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 类加载器:classLoader
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档