类加载分为:加载(loading),链接(linking),初始化(initialization)三个阶段。
loading:the process of bringing a binary form for a type into the jvm.
1: given the type's fully qualified name produce a stream of binary data that represent that type.
2: parse the stream of binary data into internal data structure in the method area
3: create an instance of Class that represent the type. it is the end product of the loading step ,serving as an interface between the program and the internal data structures, to access information about a type that is stored in the internal data structures, the program invokes methods on the Class instance for that type!
if a classloader encounters a missing or malformated class file during early loading, it must wait to report that error until the class's first active use by the program, never report if the class is never actively used!
linking又分为verification, preparation,resolution.
verification: parsers of the java class file formate might check the magic number, make sure each component is in the right place and of the proper length. although these checks take place during loading before the official verification phase of linking, they are still logically part of the verification phase.
another check that occurs during loading is make sure that every class except Object has a superclass, because when the java virtual machine loads a class it must also make sure all of the class's super class are loaded also.
子类loaded 父类一定loaded, 包括interface, 但初始化interface就不一定。
The only way of a jvm can know the name of a given class's superclass is by peering into the binary data for the class so it must check.
还有一些verification在解析阶段,在解析符号引用时, 首先要check这个实体是否存在,是否有权限访问等,这些在逻辑上也属于verification。
official verification:
1: check the final class are not subclassed, checking the final methods are not overridden. make sure no incompatible method declaration( such as two methods that have the same name)
2: checking all the special strings contained in the constant pool (class name field and method name, method descriptor are well-formed)
3: verifying the integrity of the byte codes.(the most complicated task); eg: implementations are not allowed to crash because a jump instruction sends the jvm beyond the end of a method . they must detect that the jump is invalid through some process of the bytecode verification. when verifying bytecodes via a data flow analyzer , the vm may have to load other classes to ensure that the semantics of java language are being followed, image a class contained a method that assigned a reference to an instance of java Lang.Float to a field of type java.lang.Number, the vm would have to load class Float to make sure it was a subclass of Class Number. and make sure class Number was not declared final.
Preparation:
No java code is executed during preparation step. the vm set the newly allocated memory for the class variables to default value determined bye the type of the variable.
jvm may also allocate memory for data structures that are intended to improve the performance of the running program. an example of such data structure is a method table which contains a pointer to the data for every method in a class, including those inherited from its super classes. which enables an inherited method to be invoked on an object without a search of superclasses at the point of invocation.
Resolution:
the process of locating classes, interfaces, fields and methods referenced symbolically from a type's constant pool and replacing those symbolic references with direct references. it is the resolution of symbolic references contained in the referenced type not the referencing type.
each jvm must maintain an internal list of references to string objects that have been interned, basically, a string object is said to be interned simply if it appears in jvm's internal list of interned string object. the point of maintaining this list is that any particular sequence of characters is guaranteed to appear in the list no more than once.
to intern a sequence of characters represented by a Constant_String_info entry, the virtual machine checks to see if the sequence of characters is already in the list of interned strings, if so , the vm uses the reference to the existing , previously-interned string object, otherwise the vm create a new string object with the proper character sequence and adds a reference to that string object to the list. to complete the resolution process for a constant_string_info entry, the virtual machine places the reference to the interned string object in the data of the constant pool entry being resolved.
all literal string are interned via the process of resolving constant_string_info entry, if a string with the same sequence of unicode character has been previously interned the intern() method returns a reference to the matching already-interned string object,.
the ultimate goal of constant pool resolution is to replace a symbolic reference with a direct reference. direct references to types, class variables and class methods are likely native pointers into the method area, direct references to instance variables and instance methods are offsets.
as part of executing the ldc instruction, the virtual machine resolves the constant pool entry, it creates and interns a new string object with the value string literal, place a reference to the string object in the constant pool entry, marks the entry as resolved.
classloader object which includes a reference to a hashtable object in which a class instance is stored.
Initialization:
all the class variable initializers and static initializers (a block of code introduced by static keyword) of a type are collected by the java compiler and placed into one special method.
initialization of a class consist of two steps:
1: initializing the class's direct superclasses if the direct superclass has not already been initialized
2: executing the class's class initialization method if it has one
初始化过程必须synchronized,来保证一个类只被初始化一次。
note: 1: Initialization of an interface does not require initialization of its super interfaces, just executing the interface's interface initialization method if has one .
2: only those classes that actually require java code to be executed to initialize class variables to proper initial value will have a class initiazation method, eg: static final int age=10 , age is not stored as class variables in the method area, they are constants, which are treated specially by the java compiler . 编译器就能够确定的值并不会在使用这些值的类中存在指向他们的引用, 可能就直接在嵌入在代码中!!
会导致类的初始化的有:
1: 创建类的实例
2: 引用类的静态变量和对静态变量赋值,(static final 不算)
3: 作为启动类(main方法所在的类)
4: class.forname (调用反射api)
5: 初始化一个类的子类会导致父类被初始化(接口不会)
静态编译时常量和类名.class不会导致类的初始化(加载阶段就会产生class对象,并不需要到类初始化阶段)。 通过子类引用父类元素不会导致子类的初始化。
委托机制(delegate to parent):
jvm会为每一个类加载器维护一个名字空间,为每一个类加载器维护一张列表,记录它装载过的类型。
the term current namespace refers to the namespace of the current classloader , the set of all type names for which the current classloader has been marked as an initiating loader.
for each classloader , the java virtual machine maintains a list of the names of all the types for which the class loader has served as an initiating class loader. the jvm use the list during resolution to determine whether a class has already been loaded by a particular classloader.