什么是 Java 类加载器?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2424604/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 07:26:47  来源:igfitidea点击:

What is a Java ClassLoader?

javaclassloader

提问by EugeneP

In a few simple sentences, what is a Java ClassLoader, when is it used and why?

简单说几句,什么是Java ClassLoader,什么时候用,为什么用?

OK, I read a wiki article. ClassLoader loads classes. OK. So if I include jar files and import, a ClassLoader does the job.

好的,我读了一篇维基文章。ClassLoader 加载类。好的。因此,如果我包含 jar 文件并导入,则 ClassLoader 会完成这项工作。

Why should I bother with this ClassLoader? I've never used it and didn't know it existed.

为什么我要打扰这个类加载器?我从未使用过它,也不知道它的存在。

The question is, why does the ClassLoader class exist? And also, how do you use it in practice? (Cases exist, I know.)

问题是,ClassLoader 类为什么存在?而且,您如何在实践中使用它?(案例存在,我知道。)

采纳答案by JRL

Taken from this nice tutorialfrom Sun:

取自 Sun 的这个不错的教程

Motivation

动机

Applications written in statically compiled programming languages, such as C and C++, are compiled into native, machine-specific instructions and saved as an executable file. The process of combining the code into an executable native code is called linking - the merging of separately compiled code with shared library code to create an executable application. This is different in dynamically compiled programming languages such as Java. In Java, the .class files generated by the Java compiler remain as-is until loaded into the Java Virtual Machine (JVM) -- in other words, the linking process is performed by the JVM at runtime. Classes are loaded into the JVM on an 'as needed' basis. And when a loaded class depends on another class, then that class is loaded as well.

以静态编译的编程语言(例如 C 和 C++)编写的应用程序被编译为本地机器特定指令并保存为可执行文件。将代码组合成可执行本机代码的过程称为链接——将单独编译的代码与共享库代码合并以创建可执行应用程序。这在动态编译的编程语言(如 Java)中有所不同。在 Java 中,Java 编译器生成的 .class 文件在加载到 Java 虚拟机 (JVM) 之前保持原样——换句话说,链接过程由 JVM 在运行时执行。类在“根据需要”的基础上加载到 JVM 中。当一个加载的类依赖于另一个类时,那个类也会被加载。

When a Java application is launched, the first class to run (or the entry point into the application) is the one with public static void method called main(). This class usually has references to other classes, and all attempts to load the referenced classes are carried out by the class loader.

当 Java 应用程序启动时,要运行的第一个类(或应用程序的入口点)是具有称为 main() 的 public static void 方法的类。这个类通常有对其他类的引用,所有加载被引用类的尝试都由类加载器执行。

To get a feeling of this recursive class loading as well as the class loading idea in general, consider the following simple class:

要大致了解这种递归类加载以及类加载思想,请考虑以下简单类:

public class HelloApp {
   public static void main(String argv[]) {
      System.out.println("Aloha! Hello and Bye");
   }
}

If you run this class specifying the -verbose:class command-line option, so that it prints what classes are being loaded, you will get an output that looks as follows. Note that this is just a partial output since the list is too long to show here.

如果您指定 -verbose:class 命令行选项运行此类,以便打印正在加载的类,您将获得如下所示的输出。请注意,这只是部分输出,因为列表太长而无法在此处显示。

prmpt>java -verbose:class HelloApp



[Opened C:\Program Files\Java\jre1.5.0\lib\rt.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jsse.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jce.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\charsets.jar]
[Loaded java.lang.Object from shared objects file]
[Loaded java.io.Serializable from shared objects file]
[Loaded java.lang.Comparable from shared objects file]
[Loaded java.lang.CharSequence from shared objects file]
[Loaded java.lang.String from shared objects file]
[Loaded java.lang.reflect.GenericDeclaration from shared objects file]
[Loaded java.lang.reflect.Type from shared objects file]
[Loaded java.lang.reflect.AnnotatedElement from shared objects file]
[Loaded java.lang.Class from shared objects file]
[Loaded java.lang.Cloneable from shared objects file]
[Loaded java.lang.ClassLoader from shared objects file]
[Loaded java.lang.System from shared objects file]
[Loaded java.lang.Throwable from shared objects file]
.
.
.
[Loaded java.security.BasicPermissionCollection from shared objects file]
[Loaded java.security.Principal from shared objects file]
[Loaded java.security.cert.Certificate from shared objects file]
[Loaded HelloApp from file:/C:/classes/]
Aloha! Hello and Bye
[Loaded java.lang.Shutdown from shared objects file]
[Loaded java.lang.Shutdown$Lock from shared objects file]

As you can see, the Java runtime classes required by the application class (HelloApp) are loaded first.

如您所见,应用程序类(HelloApp)所需的 Java 运行时类首先被加载。

Class Loaders in the Java 2 Platform

Java 2 平台中的类加载器

The Java programming language keeps evolving to make the life of applications developers easier everyday. This is done by providing APIs that simplify your life by allowing you to concentrate on business logic rather than implementation details of fundamental mechanisms. This is evident by the recent change of J2SE 1.5 to J2SE 5.0 in order to reflect the maturity of the Java platform.

Java 编程语言不断发展,使应用程序开发人员的日常生活变得更加轻松。这是通过提供 API 来实现的,这些 API 允许您专注于业务逻辑而不是基本机制的实现细节,从而简化您的生活。最近为了反映 Java 平台的成熟度而将 J2SE 1.5 更改为 J2SE 5.0 就证明了这一点。

As of JDK 1.2, a bootstrap class loader that is built into the JVM is responsible for loading the classes of the Java runtime. This class loader only loads classes that are found in the boot classpath, and since these are trusted classes, the validation process is not performed as for untrusted classes. In addition to the bootstrap class loader, the JVM has an extension class loader responsible for loading classes from standard extension APIs, and a system class loader that loads classes from a general class path as well as your application classes.

从 JDK 1.2 开始,JVM 内置的引导类加载器负责加载 Java 运行时的类。该类加载器仅加载在引导类路径中找到的类,并且由于这些是受信任的类,因此不会像对不受信任的类那样执行验证过程。除了引导类加载器之外,JVM 还具有一个扩展类加载器,负责从标准扩展 API 加载类,以及一个系统类加载器,它从通用类路径以及您的应用程序类加载类。

Since there is more than one class loader, they are represented in a tree whose root is the bootstrap class loader. Each class loader has a reference to its parent class loader. When a class loader is asked to load a class, it consults its parent class loader before attempting to load the item itself. The parent in turn consults its parent, and so on. So it is only after all the ancestor class loaders cannot find the class that the current class loader gets involved. In other words, a delegation model is used.

因为有多个类加载器,所以它们用一棵树表示,其根是引导类加载器。每个类加载器都有一个对其父类加载器的引用。当要求类加载器加载一个类时,它会在尝试加载项目本身之前咨询其父类加载器。父级依次咨询其父级,依此类推。所以只有在所有祖先类加载器都找不到当前类加载器涉及的类之后。换句话说,使用了委托模型。

The java.lang.ClassLoader Class

java.lang.ClassLoader 类

The java.lang.ClassLoaderis an abstract class that can be subclassed by applications that need to extend the manner in which the JVM dynamically loads classes. Constructors in java.lang.ClassLoader(and its subclasses) allow you to specify a parent when you instantiate a new class loader. If you don't explicitly specify a parent, the virtual machine's system class loader will be assigned as the default parent. In other words, the ClassLoader class uses a delegation model to search for classes and resources. Therefore, each instance of ClassLoader has an associated parent class loader, so that when requested to find a class or resources, the task is delegated to its parent class loader before attempting to find the class or resource itself. The loadClass()method of the ClassLoader performs the following tasks, in order, when called to load a class:

java.lang.ClassLoader是,可以由需要延长在其中JVM动态加载类的方式应用作为子类的抽象类。java.lang.ClassLoader(及其子类)中的构造函数允许您在实例化新类加载器时指定父类。如果您没有明确指定父级,虚拟机的系统类加载器将被分配为默认父级。换句话说,ClassLoader 类使用委托模型来搜索类和资源。因此,ClassLoader 的每个实例都有一个关联的父类加载器,因此当请求查找类或资源时,在尝试查找类或资源本身之前,将任务委托给其父类加载器。loadClass()ClassLoader的方法在调用加载类时按顺序执行以下任务:

If a class has already been loaded, it returns it. Otherwise, it delegates the search for the new class to the parent class loader. If the parent class loader doesn't find the class, loadClass()calls the method findClass()to find and load the class. The finalClass()method searches for the class in the current class loader if the class wasn't found by the parent class loader.

如果一个类已经被加载,它会返回它。否则,它将对新类的搜索委托给父类加载器。如果父类加载器未找到该类,则loadClass()调用该方法findClass()查找并加载该类。finalClass()如果父类加载器未找到该类,该方法将在当前类加载器中搜索该类。



There's more in the original article, which also shows you how to implement your own network class loaders, which answers your question as to why (and how). See also the API docs.

原始文章中有更多内容,它还向您展示了如何实现自己的网络类加载器,它回答了您关于为什么(以及如何)的问题。另请参阅API 文档

回答by sleske

The question is "Why should one bother this ClassLoader class exists" ?

问题是“为什么要打扰这个 ClassLoader 类的存在”?

Well, mostly so you can fix things if they go wrong :-).

嗯,主要是这样你就可以在出错时解决问题:-)。

It's true, as long as you just write an application, compile it to a JAR and maybe include a few extra library JARs, you don't need to know about class loaders, it will just work.

没错,只要您只是编写一个应用程序,将其编译为 JAR 并可能包含一些额外的库 JAR,您就不需要了解类加载器,它就可以工作。

Still, it is helpful to know a bit about class loaders and class loading to better understand what goes on behind the scenes. As an example, "static initializers" will run when a class is loaded, so to understand when they will run, you need to know how the class loader decides when to load them.

尽管如此,了解一些类加载器和类加载的知识有助于更好地理解幕后发生的事情。例如,“静态初始化器”将在类加载时运行,因此要了解它们何时运行,您需要知道类加载器如何决定何时加载它们。

also.. how do you use it in practice ?

还有..你如何在实践中使用它?

For simple cases, you don't need them. However, if you need to load code dynamically at runtime with explicit control where it comes from (e.g. loading over a network, loading plugins not available at compile time, etc.), you may need to do more. Then you can e.g. write your own class loader. See the other answers for links.

对于简单的情况,您不需要它们。但是,如果您需要在运行时动态加载代码并明确控制代码的来源(例如通过网络加载、加载在编译时不可用的插件等),您可能需要做更多的事情。然后你可以编写你自己的类加载器。有关链接,请参阅其他答案。

回答by Michael Borgwardt

Most Java developers will never need to explicitly use class loaders (except to load resources so that it still works when they're bundled in JARs), let alone write their own.

大多数 Java 开发人员永远不需要显式使用类加载器(除了加载资源,以便在将它们捆绑在 JAR 中时它仍然可以工作),更不用说编写自己的类加载器了。

ClassLoaders are used in large systems and server applications to do things like:

类加载器在大型系统和服务器应用程序中用于执行以下操作:

  • Modularize a system and load, unload and update modules at runtime
  • Use different versions of an API library (e.g. an XML parser) in parallel
  • Isolate different applications running within the same JVM (ensuring they don't interfere with each other, e.g. through static variables)
  • 模块化系统并在运行时加载、卸载和更新模块
  • 并行使用不同版本的 API 库(例如 XML 解析器)
  • 隔离在同一 JVM 中运行的不同应用程序(确保它们不会相互干扰,例如通过静态变量)

回答by bitan

Class Loaders are a functional component of JVM, which loads class data from the '.class' file or from over the network in to the Method Area in Heap.

类加载器是 JVM 的一个功能组件,它将类数据从“.class”文件或通过网络加载到堆中的方法区。

Looks like a integral part of the JVM, but as an end java user why should I be concerned? Here is why:

看起来像是 JVM 的一个组成部分,但作为最终的 Java 用户,我为什么要担心呢?原因如下:

Each class loader has it's own name space and classes invoked by a particular class loader gets into it's name space.

每个类加载器都有自己的命名空间,由特定类加载器调用的类进入它的命名空间。

Classes invoked by two different class loaders will not have visibility over each other, resulting in enhanced security.

由两个不同的类加载器调用的类不会相互可见,从而增强了安全性。

Class loader parent child delegation mechanism ensures java api classes could never be hacked by unauthorized code.

类加载器父子委托机制确保 java api 类永远不会被未经授权的代码破解。

For details look here

详情请看这里

回答by Srinivas Balasani

Class loaders are hierarchical. Classes are introduced to the JVM as they are referenced by name in a class that is already running in the JVM.

类加载器是分层的。类被引入 JVM,因为它们在 JVM 中已运行的类中按名称引用。

How the very first class loaded?
The very first class is loaded with the help of static main()method declared in your class. All the subsequently loaded classes are loaded by the classes, which are already loaded and running.

头等舱怎么装?
第一个类是static main()在类中声明的方法的帮助下加载的。所有随后加载的类都由已经加载并运行的类加载。

A class loader creates a namespace. All JVMinclude at least one class loader that is embedded within the JVM called the primordial (or bootstrap)class loader. That is one thing, and we will look at non-primordial class loaders. The JVM has hooks in it to allow user defined class loaders to be used in place of primordial class loader. Here are the class loaders created by the JVM.

类加载器创建一个命名空间。所有JVM 都包含至少一个嵌入在 JVM 中的类加载器,称为原始(或引导)类加载器。这是一回事,我们将研究非原始类加载器。JVM 中有钩子,允许使用用户定义的类加载器代替原始类加载器。下面是 JVM 创建的类加载器。

Bootstrap (primordial)This class loader not re loadable. Loads JDK internal classes, java.* packages ( typically loads rt.jar and i18n.jar). Extesions This class loader not re loadable. Loads jar files from JDK extensions directory (usually lib/ext of JRE). System This class loader not re loadable. Loads classes from system class path.

Bootstrap (primordial)此类加载器不可重新加载。加载 JDK 内部类、java.* 包(通常加载 rt.jar 和 i18n.jar)。Extesions 这个类加载器不可重新加载。从 JDK 扩展目录(通常是 JRE 的 lib/ext)加载 jar 文件。System 此类加载器不可重新加载。从系统类路径加载类。

http://www.sbalasani.com/2015/01/java-class-loaders.html

http://www.sbalasani.com/2015/01/java-class-loaders.html

回答by roottraveller

ClassLoaderin Java is a class which is used to load class files in Java. Java code is compiled into class file by javaccompiler and JVM executes Java program, by executing byte codes written in class file.

ClassLoader在 Java 中是一个类,用于在 Java 中加载类文件。Java代码由javac编译器编译成类文件,JVM通过执行写入类文件的字节码来执行Java程序。

ClassLoader is responsible for loading class files from file system, network or any other source. There are three default class loader used in Java, Bootstrap, Extensionand System or Applicationclass loader.

ClassLoader 负责从文件系统、网络或任何其他来源加载类文件。Java 中使用了三个默认的类加载器,BootstrapExtensionSystem or Application类加载器。

ClassLoader

类加载器



How ClassLoader works

类加载器的工作原理

## ClassLoader interaction with JVMenter image description here

## ClassLoader 与 JVM 的交互在此处输入图片说明

More @ : how-classloader-works-in-java.html

更多 @ :how-classloader-works-in-java.html

回答by Johnny

When you asking why does the ClassLoader class exist, the reason is pretty simple - it's the class responsible for finding and loading class files at run time.

当你问为什么 ClassLoader 类存在时,原因很简单——它是负责在运行时查找和加载类文件的类

Let's elaborate it.

让我们详细说明一下。

In JVM, every Class is loaded by some instance of java.lang.ClassLoader. Whenever a new JVM is started by you usual Java program launching java <classname>command, the first step is to load all the key classes in memory required for proper working like java.lang.Objectand other runtime classes (rt.jar).

在 JVM 中,每个类都由java.lang.ClassLoader. 每当一个新的 JVM 通过您通常的 Java 程序启动java <classname>命令启动时,第一步是将所有关键类加载到内存中,以便像java.lang.Object其他运行时类一样正常工作( rt.jar)。

Now, there are actually 3 parts to ClassLoader:

现在,ClassLoader 实际上有 3 个部分:

  • The BootstrapClassLoaderis responsible for making these classes available i.e. loading these classes in memory.

  • The next task is to load any external libraries / JARs into the memory for proper working of the application. The ExtClassLoaderis responsible for this task. This class loader is responsible for loading all the .jar files mentioned in java.ext.dirs path.

  • The third and the main important class loader is the AppClassLoader. The application class loader is responsible for loading of the class files mentioned in the java.class.path system property.

  • BootstrapClassLoader负责使这些类可用,即将这些类加载到内存中。

  • 下一个任务是将任何外部库/JAR 加载到内存中,以便应用程序正常工作。该ExtClassLoader负责这项任务。这个类加载器负责加载 java.ext.dirs 路径中提到的所有 .jar 文件。

  • 第三个也是主要的重要类加载器是AppClassLoader. 应用程序类加载器负责加载 java.class.path 系统属性中提到的类文件。

It's also important to note that the default ClassLoader implementations could be overridden enabling you to customize the JVM in useful and interesting ways, allowing you to completely redefine how class files are brought into the system.

同样重要的是要注意,默认的 ClassLoader 实现可以被覆盖,使您能够以有用和有趣的方式自定义 JVM,允许您完全重新定义类文件被引入系统的方式。

enter image description here

在此处输入图片说明

Check it out to learn more about Java Class Loader.

查看它以了解有关Java 类加载器的更多信息。