public abstract class MultiClassLoader extends ClassLoader{
...
public synchronized Class loadClass(String s, boolean flag)
throws ClassNotFoundException
{
/* 检查类s是否已经在本地内存*/
Class class1 = (Class)classes.get(s);
/* 类s已经在本地内存*/
if(class1 != null) return class1;
try/*用默认的ClassLoader 装入类*/ {
class1 = super.findSystemClass(s);
return class1;
}
catch(ClassNotFoundException _ex) {
System.out.println(">> Not a system class.");
}
/* 取得类s的字节数组*/
byte abyte0[] = loadClassBytes(s);
if(abyte0 == null) throw new ClassNotFoundException();
/* 将类字节数组转换为类*/
class1 = defineClass(null, abyte0, 0, abyte0.length);
if(class1 == null) throw new ClassFormatError();
if(flag) resolveClass(class1); /*解析类*/
/* 将新加载的类放入本地内存*/
classes.put(s, class1);
System.out.println(">> Returning newly loaded class.");
/* 返回已装载、解析的类*/
return class1;
}
...
}
三、Java虚拟机的类装载原理
前面我们已经知道,一个Java应用程序使用两种类型的类装载器:根装载器(bootstrap)和用户定义的装载器(user-defined)。根装载器是Java虚拟机实现的一部分,举个例子来说,如果一个Java虚拟机是在现在已经存在并且正在被使用的操作系统的顶部用C程序来实现的,那么根装载器将是那些C程序的一部分。根装载器以某种默认的方式将类装入,包括那些Java
API的类。在运行期间一个Java程序能安装用户自己定义的类装载器。根装载器是虚拟机固有的一部分,而用户定义的类装载器则不是,它是用Java语言写的,被编译成class文件之后然后再被装入到虚拟机,并像其它的任何对象一样可以被实例化。Java类装载器的体系结构如下所示:
Java的类装载模型是一种代理(delegation)模型。当JVM要求类装载器CL(ClassLoader)装载一个类时,CL首先将这个类装载请求转发给他的父装载器。只有当父装载器没有装载并无法装载这个类时,CL才获得装载这个类的机会。这样,所有类装载器的代理关系构成了一种树状的关系。树的根是类的根装载器(bootstrap
ClassLoader) ,在JVM中它以"null"表示。除根装载器以外的类装载器有且仅有一个父装载器。在创建一个装载器时,如果没有显式地给出父装载器,那么JVM将默认系统装载器为其父装载器。Java的基本类装载器代理结构如图2所示:
下面针对各种类装载器分别进行详细的说明。
根(Bootstrap)装载器:该装载器没有父装载器,它是JVM实现的一部分,从sun.boot.class.path装载运行时库的核心代码。
扩展(Extension)装载器:继承的父装载器为根装载器,不像根装载器可能与运行时的操作系统有关,这个类装载器是用纯Java代码实现的,它从java.ext.dirs (扩展目录)中装载代码。
系统(System or Application)装载器:装载器为扩展装载器,我们都知道在安装JDK的时候要设置环境变量(CLASSPATH ),这个类装载器就是从java.class.path(CLASSPATH环境变量)中装载代码的,它也是用纯Java代码实现的,同时还是用户自定义类装载器的缺省父装载器。
小应用程序(Applet)装载器:装载器为系统装载器,它从用户指定的网络上的特定目录装载小应用程序代码。
在设计一个类装载器的时候,应该满足以下两个条件:
对于相同的类名,类装载器所返回的对象应该是同一个类对象
如果类装载器CL1将装载类C的请求转给类装载器CL2,那么对于以下的类或接口,CL1和CL2应该返回同一个类对象:a)S为C的直接超类;b)S为C的直接超接口;c)S为C的成员变量的类型;d)S为C的成员方法或构建器的参数类型;e)S为C的成员方法的返回类型。
每个已经装载到JVM中的类都隐式含有装载它的类装载器的信息。类方法getClassLoader可以得到装载这个类的类装载器。一个类装载器认识的类包括它的父装载器认识的类和它自己装载的类,可见类装载器认识的类是它自己装载的类的超集。注意我们可以得到类装载器的有关的信息,但是已经装载到JVM中的类是不能更改它的类装载器的。
Java中的类的装载过程也就是代理装载的过程。比如:Web浏览器中的JVM需要装载一个小应用程序TestApplet。JVM调用小应用程序装载器ACL(Applet ClassLoader)来完成装载。ACL首先请求它的父装载器,即系统装载器装载TestApplet是否装载了这个类,由于TestApplet不在系统装载器的装载路径中,所以系统装载器没有找到这个类,也就没有装载成功。接着ACL自己装载TestApplet。ACL通过网络成功地找到了TestApplet.class文件并将它导入到了JVM中。在装载过程中,
JVM发现TestAppet是从超类java.applet.Applet继承的。所以JVM再次调用ACL来装载java.applet.Applet类。ACL又再次按上面的顺序装载Applet类,结果ACL发现他的父装载器已经装载了这个类,所以ACL就直接将这个已经装载的类返回给了JVM ,完成了Applet类的装载。接下来,Applet类的超类也一样处理。最后, TestApplet及所有有关的类都装载到了JVM中。
四、结论
类的动态装载机制是JVM的一项核心技术,也是容易被忽视而引起很多误解的地方。本文介绍了JVM中类装载的原理、实现以及应用,尤其分析了ClassLoader的结构、用途以及如何利用自定义的ClassLoader装载并执行Java类,希望能使读者对JVM中的类装载有一个比较深入的理解。
相关推荐
Java虚拟机类装载机制是Java运行环境的核心技术之一,它允许程序在运行时动态加载和使用类,极大地增强了软件的灵活性和可扩展性。本文主要探讨了类装载的原理、实现方式及其在实际应用中的作用。 首先,类装载的...
### Java虚拟机类装载的原理及实现 #### 引言 Java虚拟机(JVM)作为执行Java程序的核心,承担着解释执行字节码的重要任务。在这个过程中,类的装载是一个关键步骤,它确保了Java程序能够正确无误地运行。类装载...
理解类装载器的工作原理对于优化Java应用性能和实现动态加载类至关重要。 装载过程包括三个主要步骤:装载、链接和初始化。装载阶段,类装载器依据指定的全限定类名(如`java.lang.Object`)去寻找对应的二进制数据...
总的来说,Java虚拟机的类装载原理、实现和应用是一个深奥且重要的主题,涉及到Java运行时环境的多个核心层面,对于理解和调试Java程序,以及设计高效、灵活的系统架构都有着至关重要的作用。开发者需要深入理解这个...
### Java深度历险(2)--深入类装载器 #### 前言 在现代软件开发领域,特别是使用Java这样的高级...通过深入了解类装载器的工作原理和其实现方式,开发人员可以更好地利用Java的这一特性,为实际项目带来更大的价值。
本文将深入探讨Java虚拟机的类装载机制,包括其原理、工作流程以及在实际开发中的应用。 类装载机制是Java虚拟机在运行时动态加载和初始化类的过程。这一过程涉及到了四个主要角色:类装载器(ClassLoader)、类的...
1. **类装载器的层次结构**:Java的类装载器采用双亲委派模型,即当一个类装载器接到加载类的请求时,它首先会委托父类装载器去尝试加载,只有当父类装载器无法加载时,子类装载器才会尝试自己加载。这种模型保证了...
通过实践编写自己的类装载器,不仅可以加深对JVM内部工作原理的理解,还能锻炼对Java反射、字节码操作、类加载机制的掌握。这是一个提升Java技术水平的重要步骤,也是成为一名资深Java开发者必备的技能之一。
在Java中,类装载器 把一个类装入Java虚拟机中,要经过三个步骤来完成:装载、链接和初始化。其中链接又可以分成校验、准备和解析三步,除了解析外,其它步骤是严格按照顺序完成的。各个步骤的主要工作如下: * ...
Java中的所有类都必须先被装载到JVM中才能被执行,这个过程由JVM内的类装载器(ClassLoader)来完成。类装载器的工作是将类文件从硬盘读取到内存中,使得JVM能够识别和执行这些类。 Java类大致分为三类:系统类、...
Java类的装载过程主要由类加载器(ClassLoader)来完成,这是一个关键组件,它负责查找、加载和初始化类。Java类加载器分为系统类加载器(Bootstrap ClassLoader)、扩展类加载器(Extension ClassLoader)和应用...
2. **类装载器**:负责加载类文件到JVM中,包括引导类装载器、扩展类装载器和应用程序类装载器,它们按照双亲委托模型进行工作,确保类的唯一性。 3. **运行时数据区**:包括堆、栈、方法区、本地方法栈和程序...
classguard是防止java反编译工具的工具,它允许java类文件使用128bit的AES加密加密。AES密钥是随机生成的每次启动加密工具。解密是一个自定义的类装载器透明地做。这类装载器的主要部分是用C防止反编译等篡改。
3. **应用程序类装载器(Application Class Loader)**:它是默认的应用程序类装载器,负责加载用户类路径(`java.class.path`)中定义的类。用户可以通过环境变量`CLASSPATH`来控制哪些类路径被包含在内。应用程序类...
在运行阶段,java.exe 命令会启动 JVM,JVM 会启动类加载器 ClassLoader。ClassLoader 会去硬盘上搜索.class 文件,找到该文件则将该字节码文件装载到 JVM 中。然后,JVM 将字节码文件解释成二进制数据,并与操作...
1. **类装载器(Class Loader)**:负责加载程序运行所需的所有类。当程序请求加载一个类时,类装载器会查找并加载相应的字节码文件。类装载器能够根据需要动态加载类,从而支持程序的热更新。 2. **内存管理**:JVM...
"Softick PPP 2.21.rar"和"Samsung XXXX Java Uploder 汉化版.rar"这两个文件似乎与Java装载工具和方法不太直接相关,它们可能是Java应用程序或工具,如用于手机平台的Java应用上传工具,对于理解Java装载原理帮助较...