`
clq9761
  • 浏览: 592809 次
  • 性别: Icon_minigender_1
  • 来自: 福建
社区版块
存档分类
最新评论

Java类加载器入门应用

 
阅读更多

1、类加载器负责加载 Java 类的字节代码到 Java 虚拟机中。最初是为了满足 Java Applet的需要而开发出来的,
  Java Applet需要从远程下载Java类文件到浏览器中并执行。类加载器使得Java类可以被动态加载到Java虚拟机中并执行。


2、基本上所有的类加载器都是java.lang.ClassLoader类的一个实例,java.lang.ClassLoader类的基本职责
就是根据一个指定的类的名称,找到或者生成其对应的字节代码,然后从这些字节代码中定义出一个Java类,
即java.lang.Class类的一个实例。除此之外,ClassLoader还负责加载Java应用所需的资源,
如图像文件和配置文件等。
ClassLoader中与加载类相关的方法如下:
(1)getParent() 返回该类加载器的父类加载器。 
(2)loadClass(String name) 加载名称为 name的类。
(3)findClass(String name) 查找名称为 name的类。
(4)findLoadedClass(String name) 查找名称为 name的已经被加载过的类。
(5)defineClass(String name, byte[] b, int off, int len) 把字节数组 b中的内容转换成 Java类。
(6)resolveClass(Class<?> c) 链接指定的 Java 类。

 

3、java虚拟机中可以安装多个类加载,系统默认三个主要类加载器,每个类负责加载特定位置的类:
(1)引导类加载器(BootStrp):
   它用来加载 Java的核心库,是用C++来实现的,并不继承自 java.lang.ClassLoader,
   主要加载目录JRE/lib/rt.jar
(2)扩展类加载器(ExtClassLoader):
    它用来加载 Java 的扩展库。主要加载目录JRE/lib/ext/*.jar。
(3)系统类加载器(AppClassLoader):
   它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类,主要加载目录CLASSPATH指定的所有jar或目录。
  Java 应用的类都是由它来完成加载的,可以通过 ClassLoader.getSystemClassLoader()来获取它。


4. 除了引导类加载器(BootStrp)之外,所有的类加载器都有一个父类加载器。可通过getParent()方法得到父类加载器。
   JDK 的实现对于父类加载器是引导类加载器(BootStrp)的情况,getParent()方法返回 null。例:

public class ClassLoaderTree {
	public static void main(String[] args) { 
        ClassLoader loader = ClassLoaderTree.class.getClassLoader(); 
        while (loader != null) { 
            System.out.println(loader.toString()); 
            loader = loader.getParent(); 
        } 
    } 
}

 输出结果如下:

sun.misc.Launcher$AppClassLoader@187c6c7
sun.misc.Launcher$ExtClassLoader@10b62c9

 

5、类加载器的委托机制
   当Java虚拟机要加载一个类时,首先当前线程的类加载器去加载线程中的第一个类,如果类A中引用了类B,
Java虚拟机将使用加载类A的加载器来加载类B.也可以直接使用loadClass()方法直接指定某个类加载器去加载某个类。
每个类加载器加载类时,会先委托给其上级类加载器,当所有上级类加载器没有加载到类时,回到发起者类加载器,
如果发起者类加载器还加载不了,则抛出ClassNotFoundException。

 

6、Java 虚拟机是如何判定两个 Java 类是相同的,Java 虚拟机不仅要看类的全名是否相同,
还要看加载此类的类加载器是否一样。只有两者都相同的情况,才认为两个类是相同的。即便是同样的字节代码,
被不同的类加载器加载之后所得到的类,也是不同的。
为了保证Java核心库的类型安全。所有 Java 应用都至少需要引用 java.lang.Object类,
也就是说在运行的时候,java.lang.Object这个类需要被加载到 Java 虚拟机中。如果这个加载过程由Java应用
自己的类加载器来完成的话,很可能就存在多个版本的 java.lang.Object类,而且这些类之间是不兼容的。
通过代理模式,对于Java核心库的类的加载工作由引导类加载器来统一完成,保证了 Java 应用所使用的
都是同一个版本的 Java 核心库的类,是互相兼容的。

 

7、Class.forName
Class.forName是一个静态方法,同样可以用来加载类。该方法有两种形式:

Class.forName(String name, boolean initialize, ClassLoader loader)

 第一种形式的参数 name表示的是类的全名;initialize表示是否初始化类;loader表示加载时使用的类加载器。

Class.forName(String className)

 第二种形式则相当于设置了参数 initialize的值为 true,loader的值为当前类的类加载器。

Class.forName的一个很常见的用法是在加载数据库驱动的时候。如

Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance()

 用来加载 Apache Derby 数据库的驱动。

 

8、编写自己的类加载器
一般来说,自己开发的类加载器只需要覆写 findClass(String name)方法即可。
java.lang.ClassLoader类的方法 loadClass()封装了前面提到的代理模式的实现,
该方法会首先调用 findLoadedClass()方法来检查该类是否已经被加载过;如果没有加载过的话,
会调用父类加载器的 loadClass()方法来尝试加载该类;如果父类加载器无法加载该类的话,
就调用 findClass()方法来查找该类。因此,为了保证类加载器都正确实现代理模式,在开发自己的类加载器时,
最好不要覆写 loadClass()方法,而是覆写 findClass()方法。例:

public class FileSystemClassLoader extends ClassLoader { 
    private String rootDir; 
    public FileSystemClassLoader(String rootDir) { 
        this.rootDir = rootDir; 
    } 
    protected Class<?> findClass(String name) throws ClassNotFoundException { 
        byte[] classData = getClassData(name); 
        if (classData == null) { 
            throw new ClassNotFoundException(); 
        } 
        else { 
            return defineClass(name, classData, 0, classData.length); 
        } 
    } 
    private byte[] getClassData(String className) { 
        String path = classNameToPath(className); 
        try { 
            InputStream ins = new FileInputStream(path); 
            ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
            int bufferSize = 4096; 
            byte[] buffer = new byte[bufferSize]; 
            int bytesNumRead = 0; 
            while ((bytesNumRead = ins.read(buffer)) != -1) { 
                baos.write(buffer, 0, bytesNumRead); 
            } 
            return baos.toByteArray(); 
        } catch (IOException e) { 
            e.printStackTrace(); 
        } 
        return null; 
    } 
    private String classNameToPath(String className) { 
        return rootDir + File.separatorChar 
                + className.replace('.', File.separatorChar) + ".class"; 
    } 
}

 

8.Tomcat6的类加载器(从上至下)
(1)BootStrapClassLoader,Java的核心库,实际没有这个类
(2)ExtensionClassLoader,对于Sun JVM,是sun.misc.Launcher$ExtClassLoader,加载 Java 的扩展库。                     
(3) SystemClassLoader,对于Sun JVM,是sun.misc.Launcher$AppClassLoader,加载java的应用库。                     
(4) CommonClassLoader,对于Tomcat 6,是org.apache.catalina.loader.StandardClassLoader,
加载的类目录通过{tomcat}/conf/catalina.properties中的common.loader指定,
以SystemClassLoader为parent(目前默认定义是common.loader=${catalina.base}/lib,
${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jar)
(5) CatalinaClassLoader,加载的类目录通过{tomcat}/conf/catalina.properties中server.loader指定,
 以CommonClassLoader为parent,如果server.loader配置为空,
 则ServerClassLoader 与CommonClassLoader是同一个(默认server.loader配置为空)
(6) SharedClassLoader:加载的类目录通过{tomcat}/conf/catalina.properties中share.loader指定,
 以CommonClassLoader为parent,如果server.loader配置为空,
 则CatalinaClassLoader 与CommonClassLoader是同一个(默认share.loader配置为空)
(7) WebappClassLoader:每个Context一个WebappClassLoader实例,
 负责加载context的/WEB-INF/lib和/WEB-INF/classes目录,
 context间的隔离就是通过不同的WebappClassLoader来做到的。
 由于类定义一旦加载就不可改变,因此要实现tomcat的context的reload功能,
 实际上是通过新建一个新的WebappClassLoader来做的,
 因此reload的做法实际上代价是很高昂的,需要注意的是,JVM内存的Perm区是只吃不拉的,
 抛弃掉的WebappClassLoader加载的类并不会被JVM释放,
 因此tomcat的reload功能如果应用定义的类比较多的话,reload几次就OutOfPermSpace异常了。
(8)JasperLoader:每个JSP一个JasperLoader实例,与WebappClassLoader做法类似,
JSP支持修改生效是通过丢弃旧的JasperLoader,建一个新的JasperLoader来做到的,
同样的,存在轻微的PermSpace的内存泄露的情况。

 

分享到:
评论

相关推荐

    java经典入门教程

    - 代码安全性:Java提供了多层安全机制,包括字节码验证器、类加载器和安全沙箱,来确保Java代码的安全执行。 - 开发环境配置:Java开发需要配置JDK(Java Development Kit),包括JRE和编译工具等。 - 简单Java...

    JAVA虚拟机解读入门

    通过学习《JAVA虚拟机解读入门》,你将能够了解JVM如何加载和解析类,以及类加载的双亲委托模型。你还将掌握栈帧的工作方式,理解方法调用和返回的过程。此外,书中还会详细介绍垃圾收集的工作原理,包括如何判断...

    JAVA反射机制的入门代码

    总的来说,"JAVA反射机制的入门代码"是初学者理解Java反射机制的好教材,通过它,你可以学习如何动态地操作Java类,提高代码的灵活性,并掌握处理`properties`文件的基础方法。在深入学习和实践中,你将进一步理解...

    Java经典入门教程.pdf

    3. **加载与链接**:类加载器负责将字节码加载至内存,并进行链接和初始化。 4. **执行**:JVM解释执行字节码,调用操作系统API完成具体操作。 5. **垃圾收集**:JVM自动管理内存,定期回收不再使用的对象,释放...

    java入门基础知识补充学习

    Java的类加载器分为三个层次:Bootstrap ClassLoader(引导类加载器)、Extension ClassLoader(扩展类加载器)和App ClassLoader(应用程序类加载器)。当JVM启动时,会按照一定的顺序加载类,通常是从BootStrap...

    Java Web从入门到精通光盘源码1-15

    这个"Java Web从入门到精通光盘源码1-15"提供了学习者深入理解和实践Java Web应用开发的资源。以下是一些核心知识点的详细说明: 1. **Servlet与JSP**:Servlet是Java Web的基础,用于处理HTTP请求并生成动态响应。...

    java入门课件(java初学者必备)

    JDK包含了编译器javac、解释器java以及各种开发工具,如javadoc用于生成API文档,jconsole用于监控Java应用程序等。安装完成后,还需要配置环境变量,包括JAVA_HOME、PATH和CLASSPATH,确保系统能够正确识别和执行...

    Java2入门经典9

    为了学习和使用Java2,开发者需要安装Java开发工具包(JDK),其中包含了Java编译器、解释器和其他工具。此外,集成开发环境(IDE)如Eclipse、IntelliJ IDEA等也是Java开发的常用工具,它们提供了代码编辑、调试、...

    java入门笔记.pdf

    文档中介绍了类加载器、反射的使用、注解等高级概念,这些都是在编写动态、灵活的Java应用程序时不可或缺的知识点。 ### Java新特性 随着Java版本的不断更新,引入了许多新的特性。文档中提到了JDK新特性,例如泛型...

    JAVA初级入门教程

    【JAVA初级入门教程】 JAVA,由SUN公司(现已被甲骨文公司收购)开发,是一种广泛应用的跨平台、面向对象的编程语言。JAVA在设计时摒弃了C/C++中一些复杂且较少使用的特性,使得它更适合初学者学习。JAVA以面向对象...

    Java语言入门Java语言入门的必备

    - **类加载器**:Java使用类加载器来加载和管理不同来源的类,这种机制有助于保护系统不受外部代码的影响。 - **1.2.7 Java的数据类型** - Java的数据类型是固定的,无论在哪种平台上运行都保持一致,例如byte...

    JAVA入门级小程序

    【JAVA入门级小程序】 在计算机编程领域,Java是一种广泛使用的高级编程语言,以其“一次编写,到处运行”的特性而著名。对于初学者来说,Java提供了一个友好的学习平台,能够帮助他们快速掌握编程基础。本资源包...

    Java基础,Java入门

    12. **Java虚拟机(JVM)**:理解JVM的工作原理,如类加载机制、内存模型(堆、栈、方法区)和垃圾回收,对于优化性能和解决内存问题有很大帮助。 13. **Junit测试**:单元测试是软件开发的重要部分,JUnit是Java中...

    Java 手机程序设计入门与应用

    Java 手机程序设计是移动开发领域中的一个重要分支,它主要关注如何利用Java语言来创建在智能手机和平板电脑上运行的应用程序。Java由于其“一次编写,到处运行”的特性,成为跨平台移动开发的理想选择。本教程将带...

    Java Web从入门到精通光盘18-21

    【Java Web从入门到精通光盘18-21】是一个涵盖了Java Web开发基础到进阶的教程资源,旨在帮助初学者系统学习并掌握这一领域。在这个光盘中,你可能会遇到一系列关于Web应用程序开发的知识点,包括但不限于以下内容:...

    Java新手入门的30个基本概念 .txt

    Java程序在运行时可以动态加载类库,这使得Java应用能够适应不断变化的环境,同时也方便了软件的更新和扩展。 #### 7. 可移植性 Java字节码的跨平台特性使得Java程序可以轻松地在不同的操作系统上运行,无需修改或...

    JAVA手机程序入门2

    同时,JVM提供了强大的类加载器系统,包括引导类加载器(Bootstrap ClassLoader)、扩展类加载器(Extension ClassLoader)和应用类加载器(Application ClassLoader),它们负责从不同来源加载类,如JRE的lib目录、...

    java入门ppt下载

    - **动态性**:Java允许程序在运行时加载新的类和资源。 - **丰富的类库**:Java拥有大量的标准库,涵盖各种功能。 2. Java的应用场景: - **Web Applet**:Java小程序,嵌入在网页中,提供互动体验。 - **...

Global site tag (gtag.js) - Google Analytics