简体   繁体   English

为什么Java ClassLoader加载此类

[英]Why the Java ClassLoader is loading this class

I'm trying to understand why the JVM decides to load certain classes when it doesn't appear it needs to. 我试图了解为什么JVM决定在不需要时加载某些类。 Consider the following example code: 考虑以下示例代码:

public class Foo {
    public void foo() {
    }

    static class Bar {
    }

    public Bar bar() {
        return new Bar();
    }
}

When calling new Foo().foo() , Bar is not loaded by the classloader since it's not needed. 当调用new Foo().foo() ,类加载器不会加载Bar ,因为它是不需要的。 But, if we change the example to have bar return an instance of a sub-class: 但是,如果我们更改示例以使bar返回一个子类的实例:

public class Foo {    
    public void foo() {
    }

    static class Bar {
    }

    static class BigBar extends Bar {
    }

    public Bar bar() {
        return new BigBar();
    }
}

Calling new Foo().foo() causes the classloader to load both the Bar and BigBar classes even though neither of them are needed. 调用new Foo().foo()会使类加载器加载BarBigBar类,即使它们都不是必需的。 Why? 为什么?

Aside from this specific scenario, is there a way to learn why the JVM decides it needs to load a class, in general? 除了这种特定情况之外,还有一种方法可以了解为什么JVM通常决定需要加载类吗?

Here is a good read from Internals of Java Class Loading 这是从Java类加载的内部知识中很好地读到的

Whenever a new JVM is started by typing java MyMainClass, the "bootstrap class loader" is responsible for loading key Java classes like java.lang.Object and other runtime code into memory first. 每当通过键入java MyMainClass启动新的JVM时,“引导类加载器”负责将关键Java类(如java.lang.Object和其他运行时代码)首先加载到内存中。 The runtime classes are packaged inside of the JRE\\lib\\rt.jar file. 运行时类打包在JRE \\ lib \\ rt.jar文件中。 We cannot find the details of the bootstrap class loader in the Java documentation, since this is a native implementation. 在Java文档中找不到引导类加载器的详细信息,因为这是本机实现。 For the same reason, the behavior of the bootstrap class loader will also differ across JVMs. 出于相同的原因,引导类加载器的行为在JVM之间也将有所不同。

In a related note, we will get null if we try to get the class loader of a core Java runtime class, like this: 在相关说明中,如果尝试获取核心Java运行时类的类加载器,则将获得null,如下所示:

 log(java.lang.String.class.getClassLoader()); 

Next comes the Java extension class loader. 接下来是Java扩展类加载器。 We can store extension libraries, those that provide features that go beyond the core Java runtime code, in the path given by the java.ext.dirs property. 我们可以在Java.ext.dirs属性给定的路径中存储扩展库,这些扩展库提供的功能超出了Java核心运行时代码。 The ExtClassLoader is responsible for loading all .jar files kept in the java.ext.dirs path. ExtClassLoader负责加载保存在java.ext.dirs路径中的所有.jar文件。 A developer can add his or her own application .jar files or whatever libraries he or she might need to add to the classpath to this extension directory so that they will be loaded by the extension class loader. 开发人员可以将自己的应用程序.jar文件或他或她可能需要添加的任何库添加到此扩展目录的类路径中,以便扩展类加载器加载它们。

The third and most important class loader from the developer perspective is the AppClassLoader. 从开发人员的角度来看,第三个也是最重要的类加载器是AppClassLoader。 The application class loader is responsible for loading all of the classes kept in the path corresponding to the java.class.path system property. 应用程序类加载器负责加载保存在与java.class.path系统属性相对应的路径中的所有类。

well explained http://javarevisited.blogspot.in/2012/07/when-class-loading-initialization-java-example.html 详细解释了http://javarevisited.blogspot.in/2012/07/when-class-loading-initialization-java-example.html

When Class is loaded in Java Class loading is done by ClassLoaders in Java which can be implemented to eagerly load a class as soon as another class references it or lazy load the class until a need of class initialization occurs. 在Java中加载类时,类加载由Java中的ClassLoaders完成,可以实现为一旦另一个类引用它就立即加载一个类,或者延迟加载该类,直到需要初始化类为止。 If Class is loaded before its actually being used it can sit inside before being initialized. 如果Class在实际使用之前加载,则可以在初始化之前放入其中。 I believe this may vary from JVM to JVM. 我相信这可能因JVM而异。 While its guaranteed by JLS that a class will be loaded when there is a need of static initialization. 尽管JLS保证在需要静态初始化时将加载类。 When a Class is initialized in Java 1) an Instance of class is created using either new() keyword or using reflection using class.forName(), which may throw ClassNotFoundException in Java. 在Java 1中初始化类时,将使用new()关键字或使用class.forName()的反射创建类的实例,这可能会在Java中引发ClassNotFoundException。

2) an static method of Class is invoked. 2)调用Class的静态方法。 3) an static field of Class is assigned. 3)分配了Class的静态字段。 4) an static field of class is used which is not a constant variable. 4)使用不是静态变量的类的静态字段。 5) if Class is a top level class and an assert statement lexically nested within class is executed. 5)如果Class是顶级类,并且执行了嵌套在class中的assert语句。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM