Learning java virtual machine - class loading mechanism

Learning java virtual machine - class loading mechanism

 First, what is

   The virtual machine data that describes the classes loaded from Class file into memory, and data validation, parsing, and initialization, and ultimately the formation Java types can be used directly in virtual machines , this is the class loading mechanism of the virtual machine.

  Inside the Java language, type of load, a link initialization process is completed during the program run, Java can dynamically expand in the natural language features is the dynamic loading and dynamic linking This feature relies achieved during the run. For example, if you write an interface-oriented application, you can wait until runtime in the development of the actual implementation class; users can Java predefined and custom class loader, so that a local application from a network or other runtime loading a binary stream where part of the program code.

 

 

Second, the class loading process

   Classes begin to be loaded into the virtual machine memory, to unload a memory location , its entire life cycle, including: Load (Loading), verification (Verification), preparation (Preparation), analytical (Resolution) , initializing (Initialization), use (Using) and unloading (unloading) 7 stages. Among them, validation, preparation, analytical three stages collectively referred to as the link (Link).

 

 

 

   1) Load (Loading): 

  1.1)) by a fully qualified name of the class to get the definition of such a binary byte stream. (Acquisition mode can be customized to achieve, can be obtained from .class files may be retrieved from the network, can be read from the zip file, calculates and generates run time)

    1.2) static storage structure represented by the byte stream converted into run-time data structure area method .

    1.3) in the memory to generate a representative of this class java.lang.Class objects , as the various data entry area methods of this class. (This is associated with the application of reflection)

 

  2) Verify (the Verification)

    The purpose is to ensure that the information contained in the Class byte stream to meet the requirements of the current virtual machine and the virtual machine will not jeopardize their own safety.    

    2.1) file format validation

    Verify byte stream for compliance with Class file format, and can be the current version of virtual machine processing.

    2.2) metadata validation

    Bytecode information described semantic analysis, to ensure compliance with the information which describes the Java language specification.

    2.3) bytecode verification

    The data flow and control flow analysis to determine the semantics of the program is legitimate, logical.

    2.4) verification of symbolic references

  Occurred in the parsing stage, coming into direct symbol references occur when a reference. The purpose is to ensure that the analysis operation can be performed normally.

  For the class loading mechanism of the virtual machine, the validation phase is a very important, but non-essential stage. If all the code is running and has been repeatedly proven in the implementation phase could consider using -Xverify: none parameter to shut down most of the class verification measures to reduce virtual machine class load time.

 

  3) Preparation (Preparing)

  Official allocates memory for class variables (non instance variables) and set the class variable an initial value (zero value). Class variables used in the process of the memory area is allocated, with the object instance variable distribution when an object is instantiated with the heap in Java.

   public static int value=123;

  value is set to an initial value 0, and the value assigned to putstatic instruction 123 is compiled program, stored in the class constructor <clinit> () method, so the value assigned to operation 123 will be performed during the initialization phase .

 

  4) parsing (Resolution)

  Virtual machine constant pool of symbolic references to the process of replacing direct references.

  Reference symbol (Symbolic Refrences): Symbol reference to a certain set of symbols described in the referenced, literal symbols may be in any form, can be positioned unambiguously as long as the goal to use.

  A direct reference (Direct References): direct reference pointer may be performed directly in the target, a relative offset or indirectly targeted to handle targets.

    

  除了invokedynamic指令以外,虚拟机实现可以对第一次解析的结果进行缓存(在运行时常量池中记录直接引用,并把常量标识为已解析状态)从而避免解析动作重复进行。

  invokedynamic指令的目的适用于动态语言支持,它所对应的引用称为“动态调用点限定符”(Dynamic Class Site Specifier), 等到程序执行到这条指令的时候解析动作在能进行。

 

  5)初始化(Initialization)

   类初始化阶段是类加载过程的最后一步,在准备阶段,变量已经付过一次系统要求的初始值,而在初始化阶段,则根据程序员通过程序制定的主观计划去初始化类变量和其他执行。

  类初始化阶段是执行类构造器<clinit>()方法的过程。该方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块(static{}块)中的语句合并产生的,编译器收集的顺序是由语句在源文件中出现的顺序决定的。

 

 

三、双亲委派模型、类加载器

  虚拟机设计团队把类加载阶段中的”通过一个类的全限定名来获取描述此类的二进制字节流“这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块称为”类加载器“。

  对于任意一个类,需要由加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性。比较两个类是否”相等“,只有在这两个类是由同一个类加载器的前提下才有意义,否则,及时这两个类来源于同一个Class文件,被同一个虚拟机加载,只要加载他们的类加载器不同,那这两个类就必定不同。

 

   3.1) 三种加载器 

  1) 启动类加载器(Bootstrap ClassLoader) , 这个类加载器使用C++语言实现,是虚拟机自身的一部分。

  负责将存放在<JAVA_HOME>\lib目录中的,或者被-Xbootclasspath参数所指定的路径中的,并且被虚拟机识别的(仅按照文件名识别)类库加载到虚拟机内存中。

  2) 扩展类加载器(Extension ClassLoader):

    负责加载<JAVA_HOME>\lib\ext目录中的,或者被java.ext.dirs系统变量所制定的路径中的所有类库。

  3)   应用程序类加载器(Application ClassLoader)

   程序中默认的类加载器,一般称它为系统类加载器,因为它是ClassLoader#getSystemClassLoader()方法的返回值。它负责加载用户类路径(Classpath)上所指定的类库。

 

  3.2) 双亲委派模型的工作过程:

   如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需要的类)时,子加载器才会尝试自己去加载。

 

   破坏双亲委派模型:

  a) jdk1.0时代, 并未实现双亲委派模型, 为引入双亲委派模型, 而不得不"破坏"之前的设计.

  b) 线程上下文类加载器。

  “基础”代码,总是作为被用户代码调用的API,如果基础类想要调回用户的代码, 就需要线程上下文类加载器了.

  如JNDI, JDNI的目的是对资源进行集中管理和查找,它需要调用由独立仓上实现并部署在应用程序的ClassPath下的JNDI提供者的代码。然而父类加载器并不"认识"classpath路径下的类, 所以需要使用线程上下文类加载器加载该类, 也就是父类加载器请求子类加载器完成类加载的动作.线程上下文类加载器通过Thread的setClassLoader()来设置, 线程创建时, 没有设置, 则从父类加载器继承一个, 如果应用程序全局范围内都没有设置, 则默认是应用类加载器.

  c) 热部署

  OSGI热部署. 每个程序模块(OSGI 成为bundle)都有一个自己的类加载器. 当需要更换一个bundle时, 就联通bundle中的类加载器也一起换掉, 以达到热部署的目的.

 

 

学习资料:

  <深入理解java虚拟机>

 

 

Guess you like

Origin www.cnblogs.com/timfruit/p/10501874.html