首页 > 编程知识 正文

java类加载器有什么用,java是什么

时间:2023-05-03 22:35:26 阅读:17452 作者:1841

Java类加载器的作用是在运行时加载类。 Java类加载器基于三种机制:委托、可见性和单一性。 委托机制是将加载类的请求传递给父类加载器,并在父类加载器无法找到或加载类时加载。 可见性原理是子类加载器可以看到所有父类加载器加载的类,而父类加载器不能看到子类加载器加载的类。 单一性原理是指只加载一个类一次。 这由委托机制保证子类加载器不会再次加载父类加载器加载的类。 正确理解类加载器有助于解决问题,因为NoClassDefFoundError和Java.lang.classnotfoundexception与类加载有关。 类加载器通常也是相对高级的Java面试中的一个重要考试问题,人们经常问Java类加载器和如何工作以及classpath是如何工作的。 Java测试问题中也经常出现“一个类是否可以加载到两个不同的类加载器中”的问题。 在本教程中,您将学习什么是类加载器、它的工作原理以及有关类加载器的知识点。

什么是类加载器

类加载器是用于加载类文件的类。 Java源代码由javac编译器编译成类文件。 然后,JVM通过执行类文件中的字节码来运行程序。 类加载器加载文件系统、网络或其他源的类文件。 默认情况下使用三种类加载器: Bootstrap类加载器、Extension类加载器、System类加载器或Application类加载器。 各种加载器配置了从哪里加载类。

Bootstrap类加载器负责加载rt.jar中的JDK类文件。 这是所有类加载器的父加载器。 Bootstrap类加载器没有父类加载器。 调用String.class.getClassLoader ()时,将返回null,并且相应的代码将抛出NUllPointerException异常。 Bootstrap加载器称为初始类加载器。

Extension首先将其加载类的请求委托给其父加载器(即Bootstrap ),如果未成功加载,则由jre/lib/ext目录或java.ext.dirs系统属性定义的die 扩展加载器由sun.misc.launcher $ ext class loader实现。

第三个默认加载器是系统加载器(也称为APP加载器)。 通常,您可以从由-classpath或-cp命令行选项定义的classpath环境变量加载或jar manifest的classpath属性。 Application类加载器是扩展类加载器的子加载器。 在sun.misc.launcher $ app class loader中实现。

Bootstrap类加载器大部分是用c编写的,而其他类加载器则是用java.lang.ClassLoader实现的。

总之,以下是三种加载器加载类文件的位置。

1 ) Bootstrap类加载器JRE/lib/rt.jar

2 )扩展类加载器JRE/lib/ext或java.ext.dirs指向的目录

3 ) Application类加载器class path环境变量。 由- CLASSPATH或-cp选项定义,或由JAR的Manifest的classpath属性定义。

类加载器的工作原理

如前所述,类加载器的工作原理基于三种机制:委托、可见性和单一性。 在本节中,让我们详细看看这些规则,并通过一个实例来理解其工作原理吧。 以下是类加载器使用委托机制的机制:

委托机制

加载和初始化类后,仅在需要加载类时才加载类。 假设您有一个名为Abc.class的APP应用程序所需的类。 首先,加载此类的请求由Application类加载器委托给其父类加载器Extension类加载器,然后委托给Bootstrap类加载器。 Bootstrap类加载器首先检查rt.jar中是否存在此类。 因为没有这个类,所以这个请求会返回到扩展类加载器。 确定此类是否位于jre/lib/ext目录下。 如果在Extension类加载器中找到此类,则将其加载。 Application如果在扩展类加载器中找不到此类,请在classpath中查找Application类加载器。 请记住,classPATH定义类文件的加载目录,path定义可执行程序(如javac和java )的执行路径。

可见性机制

根据可见性机制,子类加载器可以看到父类加载器加载的类,但不能相反。 在以下示例中,如果Abc.class已经添加到APP应用程序类中

加载程序加载后,如果尝试使用Extension类加载器加载此类,则会抛出Java.lang.classnotfoundexception异常。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

package test;

import

java.util.logging.Level;

import

java.util.logging.Logger;

/**

* Java

program to demonstrate How ClassLoader works in Java,

* in

particular about visibility principle of ClassLoader.

*

* @author

Javin Paul

*/

public class

ClassLoaderTest {

public

static void main(String args[]) {

try

{

//printing

ClassLoader of this class

System.out.println("ClassLoaderTest.getClass().getClassLoader()

: "

+

ClassLoaderTest.class.getClassLoader());

//trying

to explicitly load this class again using Extension class loader

Class.forName("test.ClassLoaderTest",

true

,

ClassLoaderTest.class.getClassLoader().getParent());

}

catch (ClassNotFoundException ex) {

Logger.getLogger(ClassLoaderTest.class.getName()).log(Level.SEVERE,

null, ex);

}

}

}

输出:

1

2

3

4

5

6

7

8

9

10

11

12

13

ClassLoaderTest.getClass().getClassLoader()

: sun.misc.Launcher$AppClassLoader@601bb1

16/08/2012 2:43:48 AM

test.ClassLoaderTest main

SEVERE: null

java.lang.ClassNotFoundException:

test.ClassLoaderTest

at

java.net.URLClassLoader$1.run(URLClassLoader.java:202)

at

java.security.AccessController.doPrivileged(Native Method)

at

java.net.URLClassLoader.findClass(URLClassLoader.java:190)

at

sun.misc.Launcher$ExtClassLoader.findClass(Launcher.java:229)

at

java.lang.ClassLoader.loadClass(ClassLoader.java:306)

at

java.lang.ClassLoader.loadClass(ClassLoader.java:247)

at

java.lang.Class.forName0(Native Method)

at

java.lang.Class.forName(Class.java:247)

at

test.ClassLoaderTest.main(ClassLoaderTest.java:29)

单一性机制

根据这个机制,父加载器加载过的类不能被子加载器加载第二次。虽然重写违反委托和单一性机制的类加载器是可能的,但这样做并不可取。你写自己的类加载器的时候应该严格遵守这三条机制。

如何显式的加载类

Java提供了显式加载类的API:Class.forName(classname)和Class.forName(classname, initialized, classloader)。就像上面的例子中,你可以指定类加载器的名称以及要加载的类的名称。类的加载是通过调用 java.lang.ClassLoader的loadClass()方法,而loadClass()方法则调用了findClass()方法来定位相应

类的字节码。在这个例子中Extension类加载器使用了java.net.URLClassLoader,它从JAR和目录中进行查找类文件,所有 以”/”结尾的查找路径被认为是目录。如果findClass()没有找到那么它会抛出 java.lang.ClassNotFoundException异常,而如果找到的话则会调用defineClass()将字节码转化成类实例,然后 返回。

什么地方使用类加载器

类加载器是个很强大的概念,很多地方被运用。最经典的例子就是AppletClassLoader,它被用来加载Applet使用的类,而 Applets大部分是在网上使用,而非本地的操作系统使用。使用不同的类加载器,你可以从不同的源地址加载同一个类,它们被视为不同的类。J2EE使用 多个类加载器加载不同地方的类,例如WAR文件由Web-app类加载器加载,而EJB-JAR中的类由另外的类加载器加载。有些服务器也支持热部署,这 也由类加载器实现。你也可以使用类加载器来加载数据库或者其他持久层的数据。

以上是关于类加载器的工作原理。我们已经知道了委托、可见性以及单一性原理,这些对于调试类加载器相关问题时至关重要。这些对于Java程序员和架构师来说都是必不可少的知识。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。