首页 > 编程语言 >Java类加载器实现机制详细笔记

Java类加载器实现机制详细笔记

时间:2024-07-27 12:26:12浏览次数:14  
标签:Java String ClassLoader classPath 校验 笔记 加载 name

1. 类加载器的基本概念
  • 类加载器(ClassLoader):在Java中,类加载器负责将Java类动态加载到JVM中。它是实现动态类加载机制的核心组件,对于开发复杂应用程序(如插件系统、模块化设计等)至关重要。
2. 类加载过程
  • 加载(Loading):从文件系统或网络读取.class文件,创建包含类数据的Class对象。
  • 链接(Linking):将类的二进制数据合并到JVM中,包括:
    • 验证(Verification):确保类文件符合JVM规范。
    • 准备(Preparation):为静态变量分配内存并初始化默认值。
    • 解析(Resolution):将符号引用替换为直接引用。
  • 初始化(Initialization):为静态变量赋予正确的初始值,并执行静态代码块。
3. 双亲委派模型
  • 模型概述:Java类加载器遵循双亲委派模型(Parent Delegation Model),确保核心类库的加载安全性,避免类冲突。
  • 工作机制:类加载器收到类加载请求时,先委托给父类加载器,父类加载器找不到时,再自行加载。
4. 类加载器层次结构
  • Bootstrap ClassLoader:最顶层的类加载器,用本地代码实现,负责加载核心Java类库(如java.lang.*)。
  • Extension ClassLoader:加载扩展目录(JAVA_HOME/lib/ext)中的类。
  • Application ClassLoader:加载系统类路径(classpath)下的类,是默认的类加载器。
5. 常见类加载器
  • Bootstrap ClassLoader:由JVM实现,加载JRE核心类库。
  • Extension ClassLoader:继承自ClassLoader类,加载扩展目录中的类。
  • Application ClassLoader:继承自ClassLoader类,加载用户类路径下的类。
6. 自定义类加载器
  • 应用场景
    • 插件系统:动态加载和卸载插件,避免类冲突。
    • 热部署:不重启应用更新代码。
    • 隔离环境:隔离不同组件或模块。
    • 从非标准源加载类:如数据库、网络、加密文件。
    • 安全考虑:加载加密的类文件并解密。
7. 自定义类加载器示例
  • 示例代码
    public class CustomClassLoader extends ClassLoader {
        private String classPath;
    
        public CustomClassLoader(String classPath) {
            super(null); // 不使用默认父类加载器
            this.classPath = classPath;
        }
    
        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            byte[] classData = loadClassData(name);
            if (classData == null) {
                throw new ClassNotFoundException();
            } else {
                return defineClass(name, classData, 0, classData.length);
            }
        }
    
        @Override
        public Class<?> loadClass(String name) throws ClassNotFoundException {
            if (name.startsWith("java.")) {
                return super.loadClass(name); // 委托给Bootstrap ClassLoader加载
            }
            try {
                return findClass(name); // 尝试自己加载类
            } catch (ClassNotFoundException e) {
                return super.loadClass(name); // 如果失败,委托给父类加载器
            }
        }
    
        private byte[] loadClassData(String className) {
            String filePath = classPath + className.replace('.', '/') + ".class";
            try (InputStream inputStream = new FileInputStream(filePath);
                 ByteArrayOutputStream byteStream = new ByteArrayOutputStream()) {
                int nextValue;
                while ((nextValue = inputStream.read()) != -1) {
                    byteStream.write(nextValue);
                }
                return byteStream.toByteArray();
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }
    
        public static void main(String[] args) {
            String classPath = "path_to_classes/";
            CustomClassLoader customClassLoader = new CustomClassLoader(classPath);
            try {
                Class<?> clazz = customClassLoader.loadClass("com.example.MyClass");
                Object instance = clazz.newInstance();
                System.out.println(instance.getClass().getName());
            } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
    
8. 字节码校验
  • 文件格式校验
    • 检查文件头的魔数:0xCAFEBABE。
    • 验证版本号。
    • 检查常量池。
  • 元数据校验
    • 访问标志、继承关系、字段和方法描述符。
  • 字节码校验
    • 操作数栈校验、局部变量表校验、类型检查、控制流检查。
  • 符号引用校验
    • 类引用、字段和方法引用。
  • 权限校验
    • 字段和方法访问权限。
9. 魔数的重要性
  • 魔数:Class文件的前四个字节,值为0xCAFEBABE。
  • 作用:标识文件类型,防止误处理其他类型文件,确保后续解析和校验的正确性。

标签:Java,String,ClassLoader,classPath,校验,笔记,加载,name
From: https://blog.csdn.net/modelsetget/article/details/140681716

相关文章

  • 读书笔记-《从码农到工匠》+ 《程序员的底层思维》
    思想很重要。在晚上睡不着的时候就刷到了这本《程序员的底层思维》看了下目录。就下单了。作者是阿里巴巴的大佬。已经实现财富自由了吧。要学习的思维有哪些呢。第一就是抽象了。抽离+具象。抽象越高。挣的越多。哈哈。金字塔、分类、层次、分治、简单、成长(这个思维对人生......
  • 3.5 JavaScript——常用库
    jQuery更加方便控制前端组件和属性使用方式在<head>元素中添加:<scriptsrc="https://cdn.acwing.com/static/jquery/js/jquery-3.3.1.min.js"></script>按jQuery官网提示下载选择器$(selector)类似于CSS选择器。例如:let$div=$('div');//通过jQuery获取div,$符号用......
  • FFmpeg开发笔记(四十一)结合OBS与MediaMTX实现SRT直播推流
    ​《FFmpeg开发实战:从零基础到短视频上线》一书的“10.2 FFmpeg推流和拉流”提到直播行业存在RTSP和RTMP两种常见的流媒体协议。除此以外,还有于2017年推出的SRT协议,相比常见的RTMP协议,SRT协议具有更低的延迟,并且消除了卡帧、抖动等花屏现象。腾讯视频云已经引入了SRT协议,在实践......
  • Java漏洞复现(ctfshow279-297)strust 漏洞复现及原理解释
    Java漏洞复现Strust原理JavaEE--------Struts2框架-CSDN博客Web279struts2漏洞S2-001是当用户提交表单数据且验证失败时,服务器使用OGNL表达式解析用户先前提交的参数值,%{value}并重新填充相应的表单数据。这里的%{value}简单理解就是和flask的模板注入{{}}差不多......
  • 编写Java,实现客户端向服务端上传文件的功能
    需求说明:实现客户端向服务端上传文件的功能当启动服务端后,运行客户端程序,系统提示客户在客户端输入上传文件的完整路径。当客户在客户端输入完成后,服务端实现文件上传实现思路:创建客户端类FileClient和服务端类FileServer在客户端类中定义uploadFile(Socketsocket)方......
  • java学习进度
    7.21(1)方法练习代码示例://判断数组中某一个数是否存在importjava.util.Scanner;publicclassFangfa{publicstaticvoidmain(String[]args){intarr[]=newint[]{11,45,14,19,19};Scannersc=newScanner(System.in);inttemp=sc.nextInt();sc.close();boolean......
  • Java使用xlsx-streamer和EasyExcel解决读取超大excel文件数据处理方法
    前言最近有个项目在生产环境做数据导入时,发现开始执行导入任务会出现cpu狂飙的情况。几番定位查找发现是在读取excel的时候导致此问题的发生,因此在通常使用的为POI的普通读取,在遇到大数据量excel,50MB大小或数五十万行的级别的数据容易导致读取时内存溢出或者cpu飙升。需要注意,本......
  • Java基础语法(变量)
    +号的使用在Java中,如果在一个运算表达式中,从左往右只要有一方是字符串,那么后续的运算就会被视为字符串的拼接运算。一、基本数据类型整数类型byte:占用1个字节(8位)。取值范围:-128到127。示例:byteb=10;short:占用2个字节(16位)。取值范围:-32768到32......
  • Java初学-8.3-代码块(实例初始化块/普通代码块和静态初始化块/静态代码块)
    代码块又称初始化块,属于类中的成员,即类的一部分。类似于方法,将逻辑语句封装在方法体中,用{}包围起来。与方法不同的是,代码块没有方法名,没有返回值,没有参数,只有方法体,而且不能通过对象或类显式调用,而是在加载类时或创建对象时隐式调用。 代码块可以用访问修饰符修饰,也可以写st......
  • Java计算机毕业设计精品课程网站的设计与实现(开题报告+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在数字化教育日益普及的今天,传统的教学模式正逐步向线上线下融合的方向转变。精品课程作为高等教育质量提升的重要载体,其传播与分享已不再局限于课堂......