JVM--类加载器

ops/2025/2/5 18:31:23/

概念

        类加载器:只参与加载过程中的字节码获取并加载到内存中的部分;java虚拟机提供给应用程序去实现获取类和接口字节码数据的一种技术,也就是说java虚拟机是允许程序员写代码去获取字节码信息

        类加载是加载的第一步,主要有以下三个步骤:

                (1)通过全类名获取定义此类的二进制字节流;

                (2)将字节码文件的静态存储结构转换成方法区运行时的数据结构;

                (3)在内存中生成一个该类的class对象,作为方法区的访问入口;

        类加载器:

                (1)类加载器是负责加载类的一个对象,用于类加载中加载这一步;

                (2)每一个java类都有一个引用指向加载他的ClassLoader;

                (3)数组类不是通过ClassLoader创建的(数组类没有对应的二进制字节流),是有jvm直接生成的

其实除了加载类之外,类加载器还可以加载 Java 应用所需的资源如文本、图像、配置文件、视频等等文件资源。本文只讨论其核心功能:加载类。

类加载器的分类

        (1)jvm底层源码实现:实现语言和虚拟机底层语言一致,比如Hotspot使用C++。主要目的是保证Java程序运行中基础类被正确地加载,比如java.lang.String,Java虚拟机需要确保其可靠性。

        (2)java代码实现:jdk默认提供的类加载器,或者是程序员按照需求定制,所有java实现的类加载类都需要继承classloader这个抽象类。

jdk8以前:

启动类加载器

  • 启动类加载器(Bootstrap ClassLoader)是由Hotspot虚拟机提供的、使用C++编写的类加载器。

  • 默认加载Java安装目录/jre/lib下的类文件,比如rt.jar,tools.jar,resources.jar等。

/*** 启动程序类加载器案例*/
public class BootstrapClassLoaderDemo {public static void main(String[] args) throws IOException {ClassLoader classLoader = String.class.getClassLoader();System.out.println(classLoader);System.in.read();}
}

       上面的代码打印出来的类加载器为null,因为启动类加载器在jdk8中是由c++来编写的,在java代码中获取不安全,所以返回了null。

如果用户想扩展一些比较基础的jar包,让启动类加载器加载,有两种途径:

  • 放入jre/lib下进行扩展。不推荐,尽可能不要去更改JDK安装目录中的内容,会出现即时放进去由于文件名不匹配的问题也不会正常地被加载。

  • 使用参数进行扩展。推荐,使用-Xbootclasspath/a:jar包目录/jar包名 进行扩展,参数中的/a代表新增。

扩展类加载器和应用程序加载器

(1)扩展类加载器和应用程序加载器都是由jdk提供,使用java代码编写;

(2)它们的源码都位于sun.misc.Launcher中,是一个静态内部类。继承自URLClassLoader(具备通过目录或者指定jar包将字节码文件加载到内存中)

扩展类加载器

       扩展类加载器(Extension Class Loader)是JDK中提供的、使用Java编写的类加载器。默认加载Java安装目录/jre/lib/ext下的类文件。

/*** 扩展类加载器*/
public class ExtClassLoaderDemo {public static void main(String[] args) throws IOException {ClassLoader classLoader = ScriptEnvironment.class.getClassLoader();System.out.println(classLoader);}
}

通过扩展类加载器去加载用户jar包:

  • 放入/jre/lib/ext下进行扩展。不推荐,尽可能不要去更改JDK安装目录中的内容。

  • 使用参数进行扩展使用参数进行扩展。推荐,使用-Djava.ext.dirs=jar包目录 进行扩展,这种方式会覆盖掉原始目录,可以用;(windows):(macos/linux)追加上原始目录

如下图中:

        使用引号将整个地址包裹起来,这样路径中即便是有空格也不需要额外处理。路径中要包含原来ext文件夹,同时在最后加上扩展的路径。

应用程序加载器

/*** 应用程序类加载器案例*/
public class AppClassLoaderDemo {public static void main(String[] args) throws IOException, InterruptedException {//当前项目中创建的Student类Student student = new Student();ClassLoader classLoader = Student.class.getClassLoader();System.out.println(classLoader);//maven依赖中包含的类ClassLoader classLoader1 = FileUtils.class.getClassLoader();System.out.println(classLoader1);Thread.sleep(1000);System.in.read();}
}

双亲委派机制

        概念:

                向上检查是加载过这个类,向下加载;在类加载的过程中,每个类加载器都会先检查是

        否已经加载了该类,如果已经加载则直接返回,否则会将加载请求委派给父类加载器。

例子:

        B类在扩展类加载器加载路径中,同样应用程序类加载器接到了加载任务,按照案例1中的方式一层一层向上查找,发现都没有加载过。那么启动类加载器会首先尝试加载。它发现这类不在它的加载目录中,向下传递给扩展类加载器。

如果第二次再接收到加载任务,同样地向上查找。扩展类加载器发现已经加载过,就可以返回了。

        作用:

                1.保证类加载的安全性。通过双亲委派机制避免恶意代码替换JDK中的核心类库,比如

        java.lang.String,确保核心类库的完整性和安全性。

                2.避免重复加载。双亲委派机制可以避免同一个类被多次加载。

打破双亲委派机制:

(1)自定义类加载器;

(2)线程上下文加载器;

(3)osgi框架的类加载器;


http://www.ppmy.cn/ops/155940.html

相关文章

基于UKF-IMM无迹卡尔曼滤波与交互式多模型的轨迹跟踪算法matlab仿真,对比EKF-IMM和UKF

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于UKF-IMM无迹卡尔曼滤波与交互式多模型的轨迹跟踪算法matlab仿真,对比EKF-IMM和UKF。 2.测试软件版本以及运行结果展示 MATLAB2022A版本运行 3.核心程序 .…

java多线程学习笔记

文章目录 关键词1.什么是多线程以及使用场景?2.并发与并行3.多线程实现3.1继承 Thread 类实现3.2Runnable 接口方式实现3.3Callable接口/Future接口实现3.4三种方式总结 4.常见的成员方法(重点记忆)94.1setName/currentThread/sleep要点4.2线程的优先级…

Fortunately 和 luckily区别

Fortunately 和 luckily 的确是同义词,都表示“幸运地”,用于描述某件事发生得很幸运,带有积极、正面的含义。然而,尽管它们的意思相近,fortunately 和 luckily 在使用上有一些细微的差别。 1. 含义相似 Fortunately…

Pluto固件编译笔记

前段时间我已经做到在电脑上交叉编译一个简单的c/c程序,然后复制到pluto上运行。 要做到这一点,其实参考adi pluto官网的wiki就能做到了。 但这样有几个问题,只能做到简易程序,如果程序复杂,要调用更多库而SYSROOT里…

2.4寒假作业

web:[HNCTF 2022 Week1]Interesting_include 打开环境,叫我们尝试访问一下文件 尝试对应的路径,没有结果,代码审计,检查用户十分使用get的方式传参filter,后面使用一个正则判断传参的数据中是否包含flag&a…

攻防世界_PHP2

(你能验证这个网站吗?) 【参考大佬博客writeup】 尝试查看源代码:无事发生 再用burp抓包该网页:还是没啥特别的 查看index.php,无事发生 请求一下index.phps:得到一段php代码片段&#xff0…

Spring的AOP的JoinPoint和ProceedingJoinPoint

Spring的AOP的JoinPoint 在Spring AOP中,JoinPoint 是一个核心接口,用于表示程序执行过程中的一个连接点(如方法调用或异常抛出)。它提供了访问当前被拦截方法的关键信息的能力。以下是关于 JoinPoint 的详细说明: 一…

【Envi遥感图像处理】009:envi5.6设置中文界面的方法

ENVI软件从5.0版本开始,界面发生了大的变化,并开始支持中文。本文讲述envi5.6设置中文界面的方法。 文章目录 一、中文界面预览二、设置中文界面三、注意事项一、中文界面预览 以下为envi5.6新版的中文界面: 二、设置中文界面 打开英文版的envi5.6软件,首先需要从安装App…