JAVA ClassLoader - tenji/ks GitHub Wiki

JAVA 类加载器

什么是 ClassLoader?

我们知道 Java 程序在 Java 虚拟机(JVM)上运行。 当我们编译 Java 类时,它将以字节码的形式进行转换,该字节码是平台和机器独立编译的程序,并将其存储为.class文件。 之后,当我们尝试使用 Class 时,Java ClassLoader 会将该类加载到内存中。

Java 中有三种类型的内置 ClassLoader:

  1. Bootstrap Class Loader - 它加载 JDK 内部类,通常加载rt.jar和其他核心类,例如java.lang.*包下的类。
  2. Extensions Class Loader - 它从 JDK 扩展目录加载类,通常是$JAVA_HOME/lib/ext目录。
  3. System Class Loader - 它从当前类路径加载类,该类可以在使用-cp-classpath命令行选项调用程序时进行设置。

Java ClassLoader 是分层的,每当引发一个请求来加载一个类时,它就会将它委派给它的父类加载器,并以这种方式在运行时环境中保持唯一性。 如果父类加载器没有找到该类,那么类加载器本身会尝试加载该类。

package com.journaldev.classloader;

public class ClassLoaderTest {

    public static void main(String[] args) {

	    System.out.println("class loader for HashMap: "
			    + java.util.HashMap.class.getClassLoader());
	    System.out.println("class loader for DNSNameService: "
			    + sun.net.spi.nameservice.dns.DNSNameService.class
					    .getClassLoader());
	    System.out.println("class loader for this class: "
			    + ClassLoaderTest.class.getClassLoader());

	    System.out.println(com.mysql.jdbc.Blob.class.getClassLoader());

    }

}

上面的 Java Classloader 示例程序的输出是:

class loader for HashMap: null
class loader for DNSNameService: sun.misc.Launcher$ExtClassLoader@7c354093
class loader for this class: sun.misc.Launcher$AppClassLoader@64cbbe37
sun.misc.Launcher$AppClassLoader@64cbbe37

正如你所看到的那样,java.util.HashMap ClassLoader 的输出是 null,它反映了 Bootstrap ClassLoader,而 DNSNameService ClassLoader 是 ExtClassLoader。 由于 ClassLoaderTest 类本身在 CLASSPATH 中,因此 System ClassLoader 会加载它。

ClassLoader继承体系

JAVAEE 委派模型

为什么需要自定义 ClassLoader?

Java默认的 ClassLoader 可以从本地文件系统加载文件,这已经可以满足大多数的情况。 但是如果你需要在运行时、从FTP服务器、通过第三方 WEB 服务加载类的话,则必须扩展现有的类加载器。 例如,AppletViewers从远程 WEB 服务器加载类。

如何自定义 ClassLoader?

常见问题及分析

Java EE 委托模型可能会导致一些有趣的类加载问题。 NoClassDefFoundErrorLinkageErrorClassNotFoundExceptionNoSuchMethodErrorClassCastException等是开发Java EE应用程序时遇到的非常常见的异常。 我们可以对这些问题的根本原因做出各种假设,但验证我们的假设非常重要,以便我们遇到此类问题时不会束手无策。

NoClassDefFoundError

NoClassDefFoundError是开发 Java EE 应用程序时可能遇到的最常见问题之一。根本原因分析和解决过程的复杂性主要取决于 Java EE 中间件环境的大小;尤其是考虑到各种 Java EE 应用程序中存在大量的类加载器。

NoSuchMethodError

ClassCastException

LinkageError

Dynamic ClassLoading

何时会发生 ClassLoader 的泄露?

JAVAEE 应用程序中的 Dynamic ClassLoading

参考链接