首页 > 代码库 > JVM(三)——类结构与类加载器
JVM(三)——类结构与类加载器
类文件结构
class文件是一个8位的字节流。所有16、32、64位数据以连续的数个8位,以big-endian形式存储。
Class文件中数据类型
u1、u2、u4代表无符号1、2、4字节数据。
0……*类型数据将会以table的形式表示。
ClassFile结构
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
magic
识别文件类型,值为0xCAFEBABE。
minor_version, major_version
类文件机构的次要、主要版本号
constant_pool_count
值为onstant_pool长度+1
constant_pool[]
常量池(索引由[1,constant_pool_count-1]),存储了字符串常量, 类和接口名称, field名称和其他被类文件结构以及子结构引用的常量。
常量池中每一个单元以"tag"字节标示。
access_flags
访问权限标志
类和接口访问权限标示
ACC_PUBLIC 0x0001 Declared public; may be accessed from outside its package.
ACC_FINAL 0x0010 Declared final; no subclasses allowed.
ACC_SUPER 0x0020 Treat superclass methods specially when invoked by the invokespecial instruction.
ACC_INTERFACE 0x0200 Is an interface, not a class.
ACC_ABSTRACT 0x0400 Declared abstract; must not be instantiated.
ACC_SYNTHETIC 0x1000 Declared synthetic; generated by a compiler and not present in the source code.
ACC_ANNOTATION 0x2000 Declared as an annotation type.
ACC_ENUM 0x4000 Declared as an enum type.
The ACC_ENUM flag indicates that this class or its superclass is declared as an enumerated type.
An annotation type must have its ACC_ANNOTATION flag set. If the ACC_ANNOTATION flag is set, the ACC_INTERFACE flag must be set as well. If the ACC_INTERFACE flag of this class file is not set, it may have any of the other flags in Table 4.1 set, except the ACC_ANNOTATION flag. However, such a class file cannot have both its ACC_FINAL and ACC_ABSTRACT flags set (JLS §8.1.1.2).
The ACC_SUPER flag indicates which of two alternative semantics is to be expressed by the invokespecial instruction (§invokespecial) if it appears in this class. Compilers to the instruction set of the Java Virtual Machine should set the ACC_SUPER flag.
The ACC_SUPER flag exists for backward compatibility with code compiled by older compilers for the Java programming language. In Oracle’s JDK prior to release 1.0.2, the compiler generated ClassFile access_flags in which the flag now representing ACC_SUPER had no assigned meaning, and Oracle‘s Java Virtual Machine implementation ignored the flag if it was set.
All bits of the access_flags item not assigned in Table 4.1 are reserved for future use. They should be set to zero in generated class files and should be ignored by Java Virtual Machine implementations.
this_class
必须是一个常量池的有效索引号,指向该类文件的CONSTANT_Class_info结构。
super_class
0或非0。如果为非0则必须是一个常量池的有效索引号,指向超类的CONSTANT_Class_info结构。
interfaces_count
指明直接父类、接口的接口数。
interfaces[]
[0,interfaces_count),指向了超接口的CONSTANT_Class_info结构。
fields_count
标示了field_info结构中,类或接口中定义的类变量、实例变量的数量。
fields[]
存储了此类中定义的变量的field_info结构。不包括超类和超接口中定义的部分。
methods_count
method表中method_info结构的数量。
methods[]
method表存储了类或接口中定义的方法的method_info结构。不包括超类和超接口中继承的方法。
attributes_count
attributes中数据数量。
attributes[]
略。详见jvms7中4.7节。
加载、连接和初始化
引用自http://www.cnblogs.com/mengdd/p/3562003.html
运行时常量池
其中引用初始化为符号引用。
加载
寻找类或接口的二进制文件并将其在内存中创建。
连接
将加载的类或接口转换为在JVM可运行的状态。
校验
校验类结构。
准备
初始化类或接口的静态field为默认值。
解析
符号引用转换为直接引用。
初始化
类或接口的初始化,包括运行类或接口的方法。当Java虚拟机初始化一个类时,要求它的所有父类都已经被初始化,但是这条规则并不适用于接口。
类的初始化
在初始化阶段,Java虚拟机执行类的初始化语句,为类的静态变量赋予初始值。静态变量的声明语句,以及静态代码块都被看做类的初始化语句,Java虚拟机会按照初始化语句在类文件中的先后顺序来依次执行它们。
在程序中,静态变量的初始化有两种途径:
在静态变量的声明处进行初始化;
在静态代码块中进行初始化。
类的初始化步骤
假如这个类还没有被加载和连接,那就先进行加载和连接。
假如类存在直接的父类,并且这个父类还没有被初始化,那就先初始化直接的父类。
假如类中存在初始化语句,那就依次执行这些初始化语句。
类的初始化时机
每个类或接口被Java程序首次主动使用时才初始化它们。
创建类的实例
访问某个类或接口的静态变量,或者对该静态变量赋值。
调用类的静态方法。
反射。
初始化一个类的子类。
Java虚拟机启动时被标明为启动类的类。
接口的特殊性
在初始化一个类时,并不会先初始化它所实现的接口。
在初始化一个接口时,并不会先初始化它的父接口。
final类型的静态变量
final类型的静态变量是编译时常量还是变量,会影响初始化语句块的执行。
如果一个静态变量的值是一个编译时的常量,就不会对类型进行初始化(类的static块不执行);
如果一个静态变量的值是一个非编译时的常量,即只有运行时会有确定的初始化值,则就会对这个类型进行初始化(类的static块执行)。
主动使用的归属明确性
只有当程序访问的静态变量或静态方法确实在当前类或当前接口中定义时,才可以认为是对类或接口的主动使用。
类加载器
三种系统提供的类加载器
启动类加载器(Bootstrap ClassLoader)
将位于JAVA_HOME\lib下或者被-Xbootclasspath指定路径下,由虚拟机识别的(按文件名)类库加载到内存中。不能被java程序直接使用。
扩展类加载器(Extension ClassLoader)
将位于JAVA_HOME\lib\ext下或者被java.ext.dirs系统变量指定路径下类库加载到内存中。开发者可直接使用。
应用类加载器(Application ClassLoader)
负责加载用户ClassPath下指定的类库。开发者可直接使用。
双亲委派模型
该模型中,类加载器以组合模式实现层次关系,除顶层类加载器之外,其余类加载器都应该有父类加载器。当发生类加载时,优先由父类加载器加载。
线程上下文加载器(Thread Context ClassLoader)
由父类加载器指派子类加载器加载。应用于涉及SPI(Service Provider Interface)的加载动作,如JNDI、JDBC、JCE、JAXB、JBI等。
OSGI
略,请参考具体的实现框架。
本文出自 “JAVA技术栈笔记” 博客,请务必保留此出处http://stroll.blog.51cto.com/11038467/1852661
JVM(三)——类结构与类加载器