java动态加载类

本文深入探讨了Java类加载机制,包括JVM启动时的类加载动作、类加载的时机和方式,以及如何定义自己的ClassLoader。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一部分:Java虚拟机启动时,关于类加载方面的一些动作

当使用java ProgramName.class运行程序时,Java找到JRE,接着找到jvm.dll,把该动态库载入内存,这就是JVM。然后加载其它动态库, 并激活JVM。JVM激活之后会进行一些初始化工作,之后生成BootstrapLoader,该Class Loader是由C++写的。BootstrapLoader加载Launcher.java中的ExtClassLoader,并设定其Parent为null,意思是ExtClassLoader的Parent Class Loader就是BootstrapLoader。然后BootstrapLoader又加载Launcher.java中的AppClassLoade,并设定其Parent Class Loader是ExtClassLoader。不过如果调用ExtClassLoader的getParent( )方法,则返回的是null。这两个Class Loader都是以静态类的形式存在,并且都是用Java编写的。

这三个Class Loader它们都有自己的类查找路径:

BootstrapLoader: sun.boot.class.path

ExtClassLoader: java.ext.dirs

AppClassLoader: java.class.path

以上三个路径都是Java的系统属性,可以通过System.getProperty(String key)方法来查看其设置:

System.out.println(System.getProperty("sun.boot.class.path"));

输出:

C:\Program Files\Java\jre1.5.0_04\lib\rt.jar;

C:\Program Files\Java\jre1.5.0_04\lib\i18n.jar;

C:\Program Files\Java\jre1.5.0_04\lib\sunrsasign.jar;

C:\Program Files\Java\jre1.5.0_04\lib\jsse.jar;

C:\Program Files\Java\jre1.5.0_04\lib\jce.jar;

C:\Program Files\Java\jre1.5.0_04\lib\charsets.jar;

C:\Program Files\Java\jre1.5.0_04\classes

即BootstrapLoader加载的是jre和jre\lib目录下的class

System.out.println(System.getProperty("java.class.path"));

输出:

C:\Program Files\Java\jre1.5.0_04\lib\ext

即ExtClassLoader加载的是jre\lib\ext下的class

System.out.println(System.getProperty("java.class.path"));

输出:应用里的路径

由此可见,BootstrapLoader负责Java核心类(所有以java.*开头的类)。ExtClassLoader负责加载扩展类(所以以javax.*开头的类以及存在ext目录下的类)。AppClassLoader负责加载应用程序自身的类。

第二部分:Java的类加载机制。Java是如何加载类的,其流程。

类加载按照加载时机,是否自动加载分为两种:预先加载和按需加载。

预先加载的类是在JVM启动之后,应用程序运行之前。至少包含rt.jar中的所有类。

按需加载则是在应用程序运行之后,在程序运行过程中,JVM遇到一个还未被装载的类,这时由Class Loader把该类载入内存。

类加载按照方式来分,也是两种:隐式加载和显式加载。

隐式加载是通过new的方式,在类初始化时由JVM根据相应的Class Loader将类载入。

显式加载则是程序员在代码中显式利用某个Class Loader将类载入。

JVM自动装载类的算法是这样的:如果Class A的实例引用了Class B的实例,则在默认情况下,JVM会先找到Class A的Class Loader,然后用该Class Loader来装载Class B。

Class Loader装载类的一般算法如下:

Background: Class Loader是按照层次关系组织起来的,每一个Class Loader都有一个Parent。如果在创建Class Loader时不显式指定其父Class Loader,JVM会把系统Class Loader指定为该Class Loader的Parent。每一个Class Loader都有自己对应的Loaded Class Cache,换句话说,Loaded Class Cache由两部分组成:ClassLoader,以及由它加载的Class类名。

检查这个类是否已经被加载进去了

如果还没有加载,调用父对象加载该类

如果父对象无法加载,调用本对象的findClass()取得这个类。

所以当创建自己的Class Loader时,只需要重载findClass()方法。

Java 1.2之后,类的装载采用委托模式。

一个已经加载的类是无法被更新的,如果试图用同一个ClassLoader再次加载 同一个类,会得到异常java.lang.LinkageError: duplicate class definition。只能够重新创建一个新的ClassLoader实例来再次加载新类。

第三部分:定义自己的Class Loader

为什么要使用自己的ClassLoader?

因为JVM自带的ClassLoader只是懂得从本地文件系统加载标准的java class文件,如果编写自己的ClassLoader,可以

在执行非置信代码之前,自动验证数字签名

动态地创建符合用户特定需要的定制化构建类

从特定的场所取得java class,例如数据库和网络。

当创建自己的ClassLoader时,需要继承java.lang.ClassLoader或者它的子类。在实例化每个ClassLoader对 象时,需要指定一个父对象;如果没有的话,系统自动指定ClassLoader.getSystemClassLoader()为父对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值