首页 > 其他分享 >类加载

类加载

时间:2023-06-26 10:23:34浏览次数:27  
标签:String loadClass 加载 data class name

类加载到jvm中的过程

  • java.exe调用dll文件创建java虚拟机
  • 创建引导类加载器,sun.mis.Launcher创建其他类加载器
  • 获取运行类自己的加载器,加载class文件(从具体位置读取)
  • 调用main方法
  • jvm销毁

初始化launcher

public Launcher() {
	//初始化两个类加载器,ExtClassLoader为单例加载
    ...
    var1 = Launcher.ExtClassLoader.getExtClassLoader();
    ...
    this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);
    ...
}

加载class文件 loadClass

  • 加载:调用类方法或者new时,会生成一个class文件
  • 验证:校验字节码文件的正确性
  • 准备:给类的静态变量分配内存,并赋予默认值
  • 解析:将符号引用替换为直接引用
  • 初始化:对类的静态变量初始化为指定的值,执行静态代码块

静态方法为何不能调用非静态的数据

  • 普通方法初始化的顺序在静态方法之后,类加载时静态方法就已经分配耗内存了,非静态方法则要等到类加载之后
// loadClass方法
protected Class<?> loadClass(String name, boolean resolve){
    // 检查当前类加载器是否已经加载了该类
 	Class<?> c = findLoadedClass(name);
 	...
 	// 判断paraent属性,由下自上找加载器,找到顶级后由上自下,双亲委派
 	 if (parent != null) {
     	c = parent.loadClass(name, false);
     } else {
         //引导类
     	c = findBootstrapClassOrNull(name);
     }
    ...
}

类加载器

  • bootstrapClassLoader:加载核心类库,jre lib下

  • ExtClassLoader:加载ext下jar包

  • AppClassLoader:加载classpath下,也就是我们自己写的class

  • 自定义

继承关系

  • 这几个类之间并没有继承关系,只是类中有一个parent属性指向上一级
  • ExtClassLoader的上一级虽然是bootstrapClassLoader,但是它由c++调用,所以赋值的时候给了null
  • 他们都继承URLClassLoader->ClassLoader

双亲委派

  • 加载某个类时会先委托父加载器寻找目标类,找不到再委托上层父加载器加载,如果所有父加载器在自己的加载类路径下都找不到目标类,则在自己的类加载路径中查找并载入目标类

为什么要这么设计

  • 可能是由于我们在使用时,大多数调用的类都是由我们自己编写的class,他们都是appClassLoader加载,第一次加载该类时虽然需要由下往上和由上往下找一次之后在加载到内存,但是后面我们再使用这个类时就不需要再次找寻

优点

  • 沙箱安全机制:自己写的java.lang.String.class类不会被加载,这样便可以防止核心API库被随意篡改

  • 避免类的重复加载:当父亲已经加载了该类时,就没有必要子ClassLoader再加载一次,保证被加载类的唯一性

自定义类加载器

  • 继承classLoader抽象类重写findClass方法
  • 两个模块依赖同一个jar包的不同版本
  • 从其他源获取加载数据
class MyClassLoader  extends ClassLoader{

    private String classPath;
    public MyClassLoader(String classPath) {
        this.classPath = classPath;
    }
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        try {
            byte[] data = loadByte(name);
            return defineClass(name, data, 0, data.length);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private byte[] loadByte(String name) throws Exception {
        name = name.replaceAll("\\.", "/");
         FileInputStream fis = new FileInputStream(classPath + "/" + name + ".class");
         int len = fis.available();
         byte[] data = new byte[len];
         fis.read(data);
         fis.close();
         return data;
    }
}

打破双亲委派机制

  • 重写loadClass方法,判断加载路径是否是自己需要的,按需加载
if (!name.startsWith("xxx")){
 c = this.getParent().loadClass(name);
}else{
 c = findClass(name);
}

标签:String,loadClass,加载,data,class,name
From: https://www.cnblogs.com/wangpc/p/17504655.html

相关文章

  • ESP(EFI System Partition)分区是UEFI固件中的一个特殊分区,通常位于硬盘上的第一个分区,
    ESP(EFISystemPartition)分区是UEFI固件中的一个特殊分区,通常位于硬盘上的第一个分区,用于存储引导加载程序、UEFI应用程序和其他与系统启动相关的文件。ESP分区使用FAT32文件系统,并拥有特定的分区类型GUID(GUIDPartitionTable,GPT)。ESP分区的主要作用是提供一个可被UEFI固件直接......
  • GRUB(GNU GRand Unified Bootloader)是一个常用的引导加载程序,用于在计算机启动时加载操
    GRUB(GNUGRandUnifiedBootloader)是一个常用的引导加载程序,用于在计算机启动时加载操作系统。它是开源软件,由GNU项目开发并得到广泛应用。GRUB主要有两个版本:GRUBLegacy和GRUB2。GRUB2是较新的版本,也是目前更常用和推荐的版本。下面主要介绍GRUB2的特点和功能:多操作系统支......
  • EFI分区(也称为EFI系统分区或ESP)是一种特殊的分区,通常用于存储引导加载程序和其他与引
    EFI分区(也称为EFI系统分区或ESP)是一种特殊的分区,通常用于存储引导加载程序和其他与引导相关的文件。它是为了支持基于UEFI(统一固件接口)的系统而设计的。下面是一些理由说明为什么需要EFI分区:引导启动:EFI分区中存储着操作系统的引导加载程序(如GRUB、WindowsBootManager等)和相关......
  • Tensorflow整理[11]. 变量创建初始化保存加载
    变量:创建、初始化、保存和加载当训练模型时,用变量来存储和更新参数。变量包含张量(Tensor)存放于内存的缓存区。建模时它们需要被明确地初始化,模型训练后它们必须被存储到磁盘。这些变量的值可在之后模型训练和分析是被加载。描述以下两个TensorFlow类。点击以下链接可查看完整的......
  • 通过xml加载菜单Menus
    <MENUxmlns:android="http://schemas.android.com/apk/res/android"><GROUPandroid:id="@+id/myGroup"><ITEMandroid:id="@+id/New"android:title="New"android:orderInCategory="0"></ITE......
  • Android四种Activity的加载模式
    建议首先阅读下面两篇文章,这样才可以更好的理解Activity的加载模式:Android的进程,线程模型其中对“Android的单线程模型”的描述,明白Activity的一些注意事项。AndroidApplicationTaskActivities的关系尤其要明白Task是啥。 一个Activty的生命周期Activty的生命周期的也......
  • Android模仿微博的LazyFragment懒加载
    本文会从头开始一步一步带你去写一个LazyFragment,根据写的过程中一步一步记录,你也可以自己试一试,跟着一起写写。最后也根据遇到的问题去完善了,网上搜的都是不完善的,还是自己写一个吧!懒加载是在加载啥?这个问题显得很愚蠢。但是想一下,懒加载到底是加载数据和视图,还是数据呢??(一开始我也......
  • Android视图加载优化——Factory2设置方法
    前言Factory2是直接继承于Factory,继续跟踪下Factory的源码,比Factory的功能更加强大。当我们新建Activity的时候,大部分情况是继承AppCompatActivity。提供了向后兼容性。本文将深入探索AppCompatActivity的视图加载,探索将xml布局文件中的TextView替换成AppCompatTextVi......
  • 未能加载文件或程序集“****”或它的某一个依赖项的一种情况
    昨天碰到了一个异常:未能加载文件或程序集“*********”或它的某一个依赖项。拒绝访问但是这个需要加载的文件确实存在呀,它依赖的程序集也是存在,最后用FileMon去分析,发现是目录和文件权限的问题正常情况应该是下图:但是,我这里成了下面的情况,这就导致了未能加载文件或程序集“****......
  • ASPX页面如何加载GAC中的组件?
    注意这里是ASPX页面而不是ASPX.cs代码页面引用GAC的组件;要ASPX页面引用GAC中的组件,则需要做下面两步:一、在machine.config中增加你的assembly:在<assemblies>节(在<configuration>/<system.web>/<compilation>/<compilers>/<assemblies>可以找到这个节)中增加下面......