网站改版十,电销系统开发,网站的数据库选择,wordpress ydg themeJVM对象分布 对象头
第一类是用于存储对象自身的运行时数据#xff0c;如哈希码#xff08;HashCode#xff09;、GC 分代年龄、锁状态标志、线程持有的锁、偏向线程 ID、偏向时间戳等 另外一部分是类型指针#xff0c;即对象指向它的类型元数据的指针#xff0c;Java 虚…JVM对象分布 对象头
第一类是用于存储对象自身的运行时数据如哈希码HashCode、GC 分代年龄、锁状态标志、线程持有的锁、偏向线程 ID、偏向时间戳等 另外一部分是类型指针即对象指向它的类型元数据的指针Java 虚拟机通过这个指针来确定该对象是哪个类的实例。
实例数据部分
是对象真正存储的有效信息即我们在程序代码里面所定义的各种类型的字段内容无论是从父类继承下来的还是在子类中定义的字段都必须记录起来。这部分的存储顺序会受到虚拟机分配策略参数-XXFieldsAllocationStyle 参数和字段在 Java 源码中定义顺序的影响 HotSpot 虚拟机默认的分配顺序为 longs/doubles、ints、shorts/chars、bytes/booleans、oopsOrdinary Object PointersOOPs
对齐填充
它仅仅起着占位符的作用。由于 HotSpot 虚拟机的自动内存管理系统要求对象起始地址必须是 8字节的整数倍换句话说就是任何对象的大小都必须是 8 字节的整数倍。对象头部分已经被精心设计成正好是 8 字节的倍数1 倍或者 2 倍因此如果对象实例数据部分没有对齐的话就需要通过对齐填充来补全。
class类文件结构
魔数与 Class 文件的版本
每个 Class 文件的头 4 个字节被称为魔数Magic Number它的唯一作用是确定这个文件是否为一个能被虚拟机接受的 Class 文件。
紧接着魔数的 4 个字节存储的是 Class 文件的版本号第 5 和第 6 个字节是次版本号Minor Version第 7 和第 8 个字节是主版本号Major Version。
常量池
紧接着主、次版本号之后的是常量池入口常量池可以比喻为 Class文件里的资源仓库它是 Class 文件结构中与其他项目关联最多的数据通常也是占用 Class 文件空间最大的数据项目之一另外它还是在 Class文件中第一个出现的表类型数据项目。
访问标志
在常量池结束之后紧接着的 2 个字节代表访问标志access_flags这个标志用于识别一些类或者接口层次的访问信息包括这个 Class 是类还是接口是否定义为 public 类型是否定义为abstract 类型如果是类的话是否被声明为 final等等。
类索引、父类索引与接口索引集合
类索引this_class和父类索引super_class都是一个 u2 类型的数据而接口索引集合interfaces是一组 u2 类型的数据的集合Class 文件中由这三项数据来确定该类型的继承关系。类索引用于确定这个类的全限定名父类索引用于确定这个类的父类的全限定名。由于 Java 语言不允许多重继承所以父类索引只有一个除了 java.lang.Object 之外所有的Java 类都有父类因此除了 java.lang.Object 外所有 Java 类的父类索引都不为 0。接口索引集合就用来描述这个类实现了哪些接口这些被实现的接口将按 implements 关键字如果这个 Class 文件表示的是一个接口则应当是 extends 关键字后的接口顺序从左到右排列在接口索引集合中。
字段表集合
字段表field_info用于描述接口或者类中声明的变量。Java 语言中的“字段”Field包括类级变量以及实例级变量但不包括在方法内部声明的局部变量。
方法表集合
Class 文件存储格式中对方法的描述与对字段的描述采用了几乎完全一致的方式方法表的结构如同字段表一样依次包括访问标志access_flags、名称索引name_index、描述符索引descriptor_index、属性表集合attributes几项。
属性表集合
属性表attribute_info在前面的讲解之中已经出现过数次Class 文件、字段表、方法表都可以携带自己的属性表集合以描述某些场景专有的信息。
JVM类加载
类加载的时机 一个类型从被加载到虚拟机内存中开始到卸载出内存为止它的整个生命周期将 会经历加载Loading、验证Verification、准备Preparation、解析Resolution、初始化Initialization、使用Using和卸载Unloading七个阶段其中验证、准备、解析三个部分统称为连接Linking。
加载
“加载”Loading阶段是整个“类加载”Class Loading过程中的一个阶段。在加载阶段Java 虚拟机需要完成以下三件事情
通过一个类的全限定名来获取定义此类的二进制字节流。将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。在内存中生成一个代表这个类的 java.lang.Class 对象作为方法区这个类的各种数据的访问入口。
验证
验证是连接阶段的第一步这一阶段的目的是确保 Class 文件的字节流中包含的信息符合《Java 虚拟机规范》的全部约束要求保证这些信息被当作代码运行后不会危害虚拟机自身的安全。验证阶段大致上会完成下面四个阶段的检验动作文件格式验证、元数据验证、字节码验证和符号引用验证。
文件格式验证第一阶段要验证字节流是否符合 Class 文件格式的规范并且能被当前版本的虚拟机处理。元数据验证对字节码描述的信息进行语义分析以保证其描述的信息符合《Java 语言规范》的要求。字节码验证第三阶段是整个验证过程中最复杂的一个阶段主要目的是通过数据流分析和控制流分析确定程序语义是合法的、符合逻辑的。在第二阶段对元数据信息中的数据类型校验完毕以后这阶段就要对类的方法体Class 文件中的 Code 属性进行校验分析保证被校验类的方法在运行时不会做出危害虚拟机安全的行为。符号引用验证最后一个阶段的校验行为发生在虚拟机将符号引用转化为直接引用[3]的时候这个转化动作将在连接的第三阶段——解析阶段中发生。
准备
准备阶段是正式为类中定义的变量即静态变量被 static 修饰的变量分配内存 并设置类变量初始值的阶段。
解析
解析阶段是 Java 虚拟机将常量池内的符号引用替换为直接引用的过程。
初始化
类的初始化阶段是类加载过程的最后一个步骤之前介绍的几个类加载的动作里除了在加载阶段用户应用程序可以通过自定义类加载器的方式局部参与外其余动作都完全由 Java 虚拟机来主导控制。直到初始化阶段Java 虚拟机才真正开始执行类中编写的 Java 程序代码将主导权移交给应用程序
类加载
双亲委派模型 Java类加载器主要是分成以下三种
启动类加载器Bootstrap Class Loader前面已经介绍过这个类加载器负责加载存放在 JAVA_HOME\lib 目录或者被-Xbootclasspath 参数所指定的路径中存放的而且是 Java 虚拟机能够识别的按照文件名识别如 rt.jar、tools.jar名字不符合的类库即使放在 lib 目录中也不会被加载类库加载到虚拟机的内存中。扩展类加载器Extension Class Loader这个类加载器是在类sun.misc.Launcher$ExtClassLoader 中以 Java 代码的形式实现的。它负责加载JAVA_HOME\lib\ext 目录中或者被 java.ext.dirs 系统变量所指定的路径中所有的类库。应用程序类加载器Application Class Loader这个类加载器由 sun.misc.Launcher$AppClassLoader 来实现。由于应用程序类加载器是ClassLoader 类中的 getSystem-ClassLoader()方法的返回值所以有些场合中也称它为“系统类加载器”。它负责加载用户类路径ClassPath上所有的类库开发者同样可以直接在代码中使用这个类加载器。