繁体   English   中英

Bootstrap类加载器加载的类

[英]The classes loaded by Bootstrap Classloader

这个帖子激起了这个问题。 当运行如下的简单程序时

public class Sample
{
    public static void main(String[] args)
    {
    }
}

使用选项-versbose:class ,它在加载此类之前列出了一堆类

[Opened C:\jdk1.6.0_14\jre\lib\rt.jar]
[Loaded java.lang.Object from C:\jdk1.6.0_14\jre\lib\rt.jar]
[Loaded java.io.Serializable from C:\jdk1.6.0_14\jre\lib\rt.jar]
[Loaded java.lang.Comparable from C:\jdk1.6.0_14\jre\lib\rt.jar]
.
.
.
.
.
.
[Loaded java.security.cert.Certificate from C:\jdk1.6.0_14\jre\lib\rt.jar]
[Loaded Sample from file:/D:/tmp/]
[Loaded java.lang.Shutdown from C:\jdk1.6.0_14\jre\lib\rt.jar]
[Loaded java.lang.Shutdown$Lock from C:\jdk1.6.0_14\jre\lib\rt.jar]

我的问题是,

我的程序从不需要java.util.CollectionSet List等类。 那么为什么Bootstrap类加载器正在加载它们。 这是JVM规范要求的方式或Bootstrap类加载器如何决定加载哪些类?

编辑:

另一方面:

即使您尝试运行不存在的类,程序也会以ClassNotFoundException结束,但不会加载前面提到的所有类。 所以这些类只是在调用JVM时加载! 所以JVM默认加载一组类,但是这个行为是什么?

Classjava.lang包的一部分,因此bootstrap类加载器会将其选中以进行加载,但Class本身需要一些依赖的框架类,如ListSet ,因此它们也会被加载。

如果您将在JDK中看到Class的代码,您将找到以下导入

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.LinkedList;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.Map;
import java.util.HashMap;

Class源在内部使用Collections ,因此需要加载它。

似乎有一些误解了bootstrap类加载器是什么:

  • 它解决了鸡/蛋问题:拥有一个你需要的类加载器实例 - 很多类,包括对象/类/集合/ io / nio等
  • 又名VM's built-in classloader
  • 它加载所有java. 类,即以java开头的类。 不能被其他任何东西加载(这是安全模型的一部分)
  • 实际上,bootstap类加载器加载了JRE提供的所有类(例如来自rt.jar的所有类),尽管如果包没有启动w / java。 可以通过应用程序类加载器加载它
  • object.getClass().getClassLoader()返回null因为bootstrap类加载器通常位于native / C代码(JVM的一部分)中,即它不是java类(因为它不能自己加载,见上面的鸡/蛋) )
  • 它不是任何其他类加载器的直接父类,ClassLoader.getParent()不会返回它。
  • 没有正式的直接方法来调用它上面的方法(因为它不作为java类存在),

现在回答直接的问题:“这种行为是什么?” - 当第一次尝试通过'Class.forName'加载类时,通常当前类的类加载器要求其自己的父类执行此操作。 Bootstrap类加载器被认为是系统类加载器的父级(加载主类)。 如果引导类加载器已经加载了当前类,则它使用VM来解析所需加载的类。

最后 - java中的类总是在需要时动态加载,每次尝试调用方法时 - 它都需要从常量池中获取必须解析的完全限定类名。 该行为独立于类的类加载器。 因此当JVM实现第一类时,球开始滚动。

JRE可能会进行延迟加载,即只在需要时才加载类。

但是,在访问主类之前,JRE已经在执行许多其他java代码,特别是sun.misc.Launcher 这就是为什么在课前加载很多课程的原因。


一般来说,无论何时,JRE都可以自行决定加载它喜欢的任何类。

http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.1.2

实现可以解析来自非常早期链接的类或接口的符号引用,甚至可以递归地解析来自进一步引用的类和接口的所有符号引用。

相反,实现可以选择仅在主动使用时解析符号引用; 对所有符号引用一致使用此策略将代表“最懒惰”的分辨率形式。

请注意,类的初始化发生在严格指定的时刻; 没有“急切”的初始化 - http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.1

暂无
暂无

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

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