加载、链接与初始化
2014-04-06 14:31
309 查看
本文只是从Java开发程序员的角度去了解加载的过程,即在加载过程中可能会影响到我们将来对jvm内存管理的部分。而非加载,链接等等细节的实现。抽象,抽象,这里做的是尽力知其然,而不为知其所以然耗尽脑汁。
Java虚拟机动态地加载、链接与初始化类和接口。加载是根据特定名称查找类或接口类型的二进制表示(Binary Representation),并由此二进制表示创建类或接口的过程。链接是为了让类或接口可以被Java虚拟机执行,而将类或接口并入虚拟机运行时状态的过程。类或接口的初始化是指执行类或接口的初始化方法<clinit>。
Java虚拟机为每个类型都维护一个常量池。它是Java虚拟机中的运行时数据结构,像传统编程语言实现中的符号表一样有很多用途。当类或接口创建时,它的二进制表示中的constant_pool表被用来构造运行时常量池。运行时常量池中的所有引用最初都是符号引用。这些符号引用来自于类或接口的二进制表示的结构中。
可能在某种Java虚拟机的实现上,初始类会作为命令行参数被提供给虚拟机。当然,虚拟机实现也可以利用一个初始类让类加载器依次加载整个应用。初始类当然也可以选择组合上述的方式来工作。
Java虚拟机支持两种类加载器:Java虚拟机提供的引导类加载器(Bootstrap Class Loader)和用户自定义类加载器(User-Defined ClassLoader)。每个用户自定义的类加载器应该是抽象类ClassLoader的某个子类的实例。应用程序使用用户自定义类加载器是为了便于扩展Java虚拟机的功能,支持动态加载并创建类。当然,它也可以从用户自定义的数据来源来获取类的二进制表示并创建类。例如,用户自定义类加载器可以通过网络下载、动态产生或是从一个加密文件中提取类的信息。
加载类型:使用引导类加载器来加载类型、使用用户自定义类加载器来加载类型 、创建数组类、加载限制、从Class文件中获取类(细节略)。
在类或接口被链接之前,它必须是被成功地加载过。
在类或接口初始化之前,它必须是被成功地验证及准备过.
程序的直接或间接行为可能会导致链接发生,链接过程中检查到的错误应该在请求链接的程序处被抛出。
例如,Java虚拟机实现可以选择只有在使用类或接口中符号引用时才去逐一解析它(延迟解析),或是当类在验证时就解析每个引用(预先解析)。这意味着在一些虚拟机实现中,在类或接口被初始化动作开始后,解析动作可能还正在进行。不管使用哪种策略,解析过程中的任何错误都必须被抛出,抛出的位置是在通过直接或间接调用而导致解析过程发生的程序处。由于链接过程会涉及到新数据结构的内存分配,它也可能因为发生OutOfMemoryError异常而导致失败。
链接阶段包括:验证、准备、解析、访问控制、方法覆盖。
Java虚拟机动态地加载、链接与初始化类和接口。加载是根据特定名称查找类或接口类型的二进制表示(Binary Representation),并由此二进制表示创建类或接口的过程。链接是为了让类或接口可以被Java虚拟机执行,而将类或接口并入虚拟机运行时状态的过程。类或接口的初始化是指执行类或接口的初始化方法<clinit>。
Java虚拟机为每个类型都维护一个常量池。它是Java虚拟机中的运行时数据结构,像传统编程语言实现中的符号表一样有很多用途。当类或接口创建时,它的二进制表示中的constant_pool表被用来构造运行时常量池。运行时常量池中的所有引用最初都是符号引用。这些符号引用来自于类或接口的二进制表示的结构中。
启动:
Java虚拟机的启动是通过引导类加载器(Bootstrap ClassLoader)创建一个初始类(InitialClass)来完成,这个类是由虚拟机的具体实现指定。紧接着,Java虚拟机链接这个初始类,初始化并调用它的public void main(String[])方法。之后的整个执行过程都是由对此方法的调用开始。执行main方法中的Java虚拟机指令可能会导致Java虚拟机链接另外的一些类或接口,也可能会调用另外的方法。可能在某种Java虚拟机的实现上,初始类会作为命令行参数被提供给虚拟机。当然,虚拟机实现也可以利用一个初始类让类加载器依次加载整个应用。初始类当然也可以选择组合上述的方式来工作。
创建和加载:
如果要创建标记为N的类或接口C,就需要先在 Java虚拟机方法区上为C创建与虚拟机实现规定相匹配的内部表示。C的创建是由另外一个类或接口D所触发的,它通过自己的运行时常量池引用了C。当然,C的创建也可能是由D调用Java核心类库中的某些方法而触发,譬如使用反射等。 如果C不是数组类型,那么它就可以通过类加载器加载C的二进制表示来创建。数组类型没有外部的二进制表示;它们都是由Java虚拟机创建,而不是通过类加载器加载的。Java虚拟机支持两种类加载器:Java虚拟机提供的引导类加载器(Bootstrap Class Loader)和用户自定义类加载器(User-Defined ClassLoader)。每个用户自定义的类加载器应该是抽象类ClassLoader的某个子类的实例。应用程序使用用户自定义类加载器是为了便于扩展Java虚拟机的功能,支持动态加载并创建类。当然,它也可以从用户自定义的数据来源来获取类的二进制表示并创建类。例如,用户自定义类加载器可以通过网络下载、动态产生或是从一个加密文件中提取类的信息。
加载类型:使用引导类加载器来加载类型、使用用户自定义类加载器来加载类型 、创建数组类、加载限制、从Class文件中获取类(细节略)。
链接
链接类或接口包括验证和准备类或接口、它的直接父类、它的直接父接口、它的元素类型(如果是一个数组类型)及其它必要的动作。而解析这个类或接口中的符号引用是链接过程中可选的部分。《Java虚拟机规范》允许灵活地选择链接(并且会有递归加载)发生的时机,但必须保证下列几点成立: 在类或接口被链接之前,它必须是被成功地加载过。
在类或接口初始化之前,它必须是被成功地验证及准备过.
程序的直接或间接行为可能会导致链接发生,链接过程中检查到的错误应该在请求链接的程序处被抛出。
例如,Java虚拟机实现可以选择只有在使用类或接口中符号引用时才去逐一解析它(延迟解析),或是当类在验证时就解析每个引用(预先解析)。这意味着在一些虚拟机实现中,在类或接口被初始化动作开始后,解析动作可能还正在进行。不管使用哪种策略,解析过程中的任何错误都必须被抛出,抛出的位置是在通过直接或间接调用而导致解析过程发生的程序处。由于链接过程会涉及到新数据结构的内存分配,它也可能因为发生OutOfMemoryError异常而导致失败。
链接阶段包括:验证、准备、解析、访问控制、方法覆盖。
初始化
初始化(Initialization)对于类或接口来说,就是执行它的初始化方法。在类或接口被初始化之前,它必须被链接过,也就是经过验证、准备阶段,且有可能已经被解析完成了。多线程加载问题(略)绑定本地方法实现
绑定(Binding)是指将使用Java之外的语言编写的函数集成到Java虚拟机中的过程。此函数需要实现在代码中定义好的native方法,之后才可以在Java虚拟机中运行。这个过程在传统编译原理的表述中被称“链接”,所以规范里使用“绑定”这个词就,就是为了避免与Java虚拟机中链接类或接口的语义发生冲突。Java虚拟机退出
Java虚拟机的退出条件一般是:某些线程调用Runtime类或System类的exit方法,或是Runtime类的halt方法,并且Java安全管理器也允许这些exit或halt操作。除此之外,在JNI(Java Native Interface)规范中还描述了当使用JNI API来加载和卸载(Load & Unload)Java虚拟机时,Java虚拟机的退出过程。相关文章推荐
- Java深度历险(二)——Java类的加载、链接和初始化
- Java类的加载、链接和初始化
- 加载 - 链接 - 初始化 中的锁
- JVM第四天之加载,链接,初始化
- Java类的加载、链接和初始化(个人笔记)
- Java深度历险(二)——Java类的加载、链接和初始化
- Java深度历险(二)——Java类的加载、链接和初始化
- java 类的加载,链接,初始化
- 类的生命周期-加载,链接,初始化,卸载
- Java深度历险(二)——Java类的加载、链接和初始化
- Java深度历险(二)——Java类的加载、链接和初始化
- 类加载分为三个过程:装载、链接、初始化的一些心得
- Java深度历险(二)——Java类的加载、链接和初始化
- linux下由于线程局部存储未初始化导致加载动态链接库时程序崩溃的BUG
- 深入JVM及类的加载链接初始化
- 深度剖析类加载器系列文章:一、Java类的加载、链接、初始化
- Java深度历险(二)——Java类的加载、链接和初始化
- Java 加载、链接、初始化
- Java深度历险(二)——Java类的加载、链接和初始化
- Java类的加载、链接和初始化