IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> JVM类加载机制 -> 正文阅读

[JavaScript知识库]JVM类加载机制

JVM类加载机制

概述

虚拟机把描述类的数据从 Class 文件加载到内存,并对数据进行校验、装换解析和初始化,最终形成可以被虚拟机直接使用的 Java 类型。

类加载过程

在这里插入图片描述

类加载过程:

  1. 加载:通过路径找到字节码文件,然后导入加载。
  2. 验证:检查字节码文件的正确性。
  3. 准备:为类中的静态变量分配内存空间。
  4. 解析:虚拟机将常量池中的符号引用替换为直接引用的过程。
  5. 初始化:为静态变量赋初始值,静态代码快执行初始化工作。

说明:一个Class文件被加载到内存中,会在内存中生成两块内容,一块是保存被加载的二进制文件;另一块是生成一个Class类对象,指向内存中的二进制文件。

类加载器

在这里插入图片描述

类加载器分类:

  • 启动类加载器(Bootstrap ClassLoader):是虚拟机的一部分,默认加载jdk\lib下的核心类,C++实现,这个路径可以使用 -Xbootclasspath参数指定。
  • 扩展类加载器(Ext ClassLoader):默认加载jdk\lib\ext\目录下扩展类,这个路径可以使用 java.ext.dirs系统变量来更改。
  • 应用类加载器(App ClassLoader):负责加载开发人员编写的类,可以classpath指定内容。
  • 自定义类加载器(Custom ClassLoader):自定义ClassLoader。

双亲委派机制

在这里插入图片描述

双亲委派过程:

  1. 当一个类收到类加载的请求时,虚拟机将这个请求交给Custom ClassLoader处理,先从ClassLoader缓存中查找,如果缓存中存在,则直接返回结果;如果缓存中不存在,则委派给它的父ClassLoader(即App ClassLoader)处理。
  2. App ClassLoader会先从缓存中查找,如果缓存中存在,则直接返回结果;如果缓存中不存在,则委派给他的父ClassLoader(即Ext ClassLoader)处理。
  3. Ext ClassLoader也会先从缓存中查找,如果缓存中存在,则直接返回结果;如果缓存中不存在,则委派给他的父ClassLoader(即Bootstrap ClassLoader)处理。
  4. Bootstrap ClassLoader已经是顶层了,没有父ClassLoader,如果这时缓存中仍然没有,则会先从核心库中查找,如果核心库中没有找到,则会给子ClassLoader(即Ext ClassLoader)反馈。
  5. Ext ClassLoader收到反馈,会查找扩展库,如果扩展库中不存在,则给子ClassLoader(即App ClassLoader)反馈。
  6. App ClassLoader收到反馈,会从应用代码中查找,如果没有找到,会给子ClassLoader(即Custom ClassLoader)反馈。
  7. Custom ClassLoader收到反馈,会交给自定义的ClassLoader处理,如果没有找到,则会抛ClassNotFoundException异常。

工作过程:类被加载时,首先自己不会先加载,而是交给父ClassLoader处理,父ClassLoader无法处理时,再交给子ClassLoader处理。

双亲委派机制优点

双亲委派机制的优势:采用双亲委派模式的是好处是Java类随着它的类加载器一起具备了一种带有优先级的层次关系,通过这种层级关可以避免类的重复加载,当父亲已经加载了该类时,就没有必要子ClassLoader再加载一次。其次是考虑到安全因素,Java核心API中定义类型不会被随意替换。假设通过网络传递一个名为java.lang.Integer的类,通过双亲委托模式传递到启动类加载器,而启动类加载器在核心Java API发现这个名字的类,发现该类已被加载,并不会重新加载网络传递的过来的java.lang.Integer,而直接返回已加载过的Integer.class,这样便可以防止核心API库被随意篡改。

案例分析

public class Demo {
    public static void main(String[] args) {

        System.out.println(String.class.getClassLoader());
        //null

        System.out.println(sun.awt.HKSCS.class.getClassLoader());
        //null

        System.out.println(sun.net.spi.nameservice.dns.DNSNameService.class.getClassLoader());
        //sun.misc.Launcher$ExtClassLoader@677327b6

        System.out.println(Person.class.getClassLoader());
        //sun.misc.Launcher$AppClassLoader@18b4aac2

        System.out.println(Class.class.getClassLoader());
        //null

        System.out.println(sun.net.spi.nameservice.dns.DNSNameService.class.getClassLoader().getClass().getClassLoader());
        //null

        System.out.println(Person.class.getClassLoader().getClass().getClassLoader());
        //null

        System.out.println(Person.class.getClassLoader().getParent());
        //sun.misc.Launcher$ExtClassLoader@677327b6
    }
}
  1. String.class.getClassLoader()sun.awt.HKSCS.class.getClassLoader()返回null,这是因为Bootstrap ClassLoader是C++实现的核心库,在Java中没有对应类,只能返回null。
  2. sun.net.spi.nameservice.dns.DNSNameService.class.getClassLoader()表示这个类位于扩展库中。
  3. Person.class.getClassLoader()表示这个类是开发人员编写的。
  4. Class.class.getClassLoader()sun.net.spi.nameservice.dns.DNSNameService.class.getClassLoader().getClass().getClassLoader()以及Person.class.getClassLoader().getClass().getClassLoader()返回null,这是因为Class类位于rt包下,由是Bootstrap ClassLoader加载。
  5. Person.class.getClassLoader().getParent()返回Ext ClassLoader,通过getParent()获取它的父ClassLoader。

自定义ClassLoader

package com.example.lib_java;

public class Hello {
    public void say() {
        System.out.println("hello");
    }
}
//自定义ClassLoader
class MyClassLoader extends ClassLoader {

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        File f = new File("class文件全路径", name.replaceAll("\\.", "/").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 (IOException e) {
            e.printStackTrace();
        }
        return super.findClass(name);
    }
}
public class Demo {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        MyClassLoader classLoader = new MyClassLoader();
        Class<?> clz = classLoader.loadClass("com.example.lib_java.Hello");
        Hello h = (Hello) clz.newInstance();
        h.say();
        System.out.println(classLoader); 
        System.out.println(classLoader.getClass().getClassLoader()); 
        System.out.println(classLoader.getParent()); 
    }
}

//hello
//com.example.lib_java.MyClassLoader@4554617c
//sun.misc.Launcher$AppClassLoader@18b4aac2
//sun.misc.Launcher$AppClassLoader@18b4aac2
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-06 12:53:24  更:2022-03-06 12:55:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 8:29:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码