研究Java类加载机制

来源:互联网 发布:交互流程图软件 编辑:程序博客网 时间:2024/06/05 08:45
研究Java类加载机制
 
    类加载是Java程序运行的第一步,研究类的加载有助于了解JVM执行过程,并指导开发者采取更有效的措施配合程序执行。研究类加载机制的第二个目的是让程序能动态的控制类加载,比如热部署等,提高程序的灵活性和适应性。

     类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。一般来说,Java 虚拟机使用 Java 类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成java.lang.Class类的一个实例。每个这样的实例用来表示一个 Java 类。通过此实例的 newInstance()方法就可以创建出该类的一个对象。实际的情况可能更加复杂,比如 Java 字节代码可能是通过工具动态生成的,也可能是通过网络下载的。

         Java类加载器图解 - 沉默 - 断尘居

 
一、简单过程
 
    Java程序运行的场所是内存,当在命令行下执行:
    java HelloWorld
    命令的时候,JVM会将HelloWorld.class加载到内存中,并形成一个Class的对象HelloWorld.class。
    其中的过程就是类加载过程:
    1、寻找jre目录,寻找jvm.dll,并初始化JVM;
    2、产生一个Bootstrap Loader(启动类加载器);
    3、Bootstrap Loader自动加载Extended Loader(标准扩展类加载器),并将其父Loader设为Bootstrap Loader。
    4、Bootstrap Loader自动加载AppClass Loader(系统类加载器),并将其父Loader设为Extended Loader。
    5、最后由AppClass Loader加载HelloWorld类。
 
以上就是类加载的最一般的过程

我们需要明白在JAVA中任何class都要装载在虚拟机上才能运行,而forClass就是装载类用的,这是要和new不一样,要分清楚哦。
A a = (A)Class.forName(“package.A”).newInstance();和 A a = new A;是等价的。












JAVA中获取Class对象有3种方式:
1.Class.forName()
2.Object.getClass()
3.类字面常量 xx.class


方法loadClass

    ClassLoader.loadClass()是ClassLoader的入口点。其特征如下:

Class loadClass(String name, boolean resolve);name参数指定了JVM需要的类的全名,如java.lang.Object;resolve参数告诉方法是否需要解析类。在准备执行类之前,应考虑类解析。并不总是需要解析。

 

方法defineClass

    defineClass方法是ClassLoader的主要诀窍。该方法接受由原始字节组成的数组并把它转换成Class对象。原始数组包含如从文件系统或网络装入的数据。defineClass管理JVM的许多复杂、神秘和倚赖于实现的方面——它把字节码分析成运行时数据结构、校验有效性等等。不必担心,我们不必也不能覆盖它。


方法findSystemClass

    findSystemClass方法从本地文件系统装入文件。它在本地文件系统中寻找类文件,如果存在,就使用defineClass将原始字节转换成Class对象,以将该文件转换成类。对于定制的ClassLoader,只有在尝试其它方法装入类之后,再使用findSystemClass。原因很简单:ClassLoader是负责执行装入类的特殊步骤,不是负责所有类。例如,即使ClassLoader从远程的Web站点装入了某些类,仍然需要在本地机器上装入大量的基本Java库。而这些类不是我们所关心的,所以要JVM以缺省方式从本地文件系统装入它们:


 方法resolveClass

    正如前面所提到的,可以不完全地(不带解析)装入类,也可以完全地(带解析)装入类。当编写我们自己的loadClass时,可以调用resolveClass,这取决于loadClass的resolve参数的值。


方法findLoadedClass

    findLoadedClass充当一个缓存:当请求loadClass装入类时,它调用该方法来查看ClassLoader是否已装入这个类,这样可以避免重新装入已存在类所造成的麻烦。应首先调用该方法。


定制ClassLoader的作用

    JVM已经有一个ClassLoader,那么我们还有必要再做一个吗?在一般情况下,没有必要,但在一些特定的时候还是有必要的。缺省的ClassLoader只知道如何从本地文件系统装入类文件,那么在什么情况下,可以用到定制的ClassLoader呢?简单举两个例子:

    1)可以使用定制的ClassLoader从Web站点装入可执行内容,以执行远程代码。

    2) 可以使用定制的ClassLoader装入加密的字节码,以保护我们的源代码。


如何运行定制的ClassLoader

    要使用定制的ClassLoader,必须以特殊方式调用程序。不能直接运行该程序,如:% java Foo arg1 arg2; 而是应该写成:


% java MyLoader Foo arg1 arg2


其中MyLoader就是我们定制的ClassLoader。



0 0