垃圾收集器与内存分配策略

目录
Class文件结构
魔数
主次版本号
常量池
访问标志
类索引及父类索引与接口索引集合
字段表
方法表
属性表
类加载子系统
运行时数据区
垃圾收集器与内存分配策略
虚拟机字节码执行引擎
OOM异常与JVM调优
Class文件结构 魔数
每个Class文件的头4个字节被称为魔数(Magic ),它的唯一作用是确定这个文件是否为一个能被虚拟机接受的Class文件 。
主次版本号
紧接着魔数的4个字节存储的是Class文件的版本号:第5和第6个字节是次版本号(Minor ),第7和第8个字节是主版本号(Major ) 。Java的版本号是从45开始的,JDK 1.1之后的每个JDK大版本发布主版本号向上加1(JDK 1.0~1.1使用了45.0~45.3的版本号),高版本的JDK能向下兼容以前版本的Class文件,但不能运行以后版本的Class文件 。
常量池
紧接着主、次版本号之后的是常量池入口,常量池可以比喻为Class文件里的资源仓库,它是Class文件结构中与其他项目关联最多的数据,通常也是占用Class文件空间最大的数据项目之一,另外,它还是在Class文件中第一个出现的表类型数据项目 。
由于常量池中常量的数量是不固定的,所以在常量池的入口需要放置一项u2类型的数据,代表常量池容量计数值() 。与Java中语言习惯不同,这个容量计数是从1而不是0开始的 。在Class文件格式规范制定之时,设计者将第0项常量空出来是有特殊考虑的,这样做的目的在于,如果后面某些指向常量池的索引值的数据在特定情况下需要表达“不引用任何一个常量池项目”的含义,可以把索引值设置为0来表示 。Class文件结构中只有常量池的容量计数是从1开始,对于其他集合类型,包括接口索引集合、字段表集合、方法表集合等的容量计数都与一般习惯相同,是从0开始 。
常量池中主要存放两大类常量:字面量()和 符号引用( )(类加载会提到一个解析过程,符号引用 -> 直接引用) 。
在Class文件中不会保存各个方法、字段最终在内存中的布局信息,这些字段、方法的符号引用不经过虚拟机在运行期转换的话是无法得到真正的内存入口地址(类加载说 。你的虚拟机不运行,你的类就是无用的 。一切都要基于jvm运行的时候,类才有他的意义),也就无法直接被虚拟机使用的 。当虚拟机做类加载时,将会从常量池获得对应的符号引用,再在类创建时或运行时解析、翻译到具体的内存地址之中 。
常量池项目类型:
常量池的项目类型 - 型常量的结构
值说明了这个UTF-8编码的字符串长度是多少字节,它后面紧跟着的长度为字节的连续数据是一个使用UTF-8缩略编码表示的字符串 。由于Class文件中方法、字段等都需要引用型常量来描述名称,所以型常量的最大长度也就是Java中方法、字段名的最大长度 。而这里的最大长度就是的最大值,既u2类型能表达的最大值65535 。所以Java程序中如果定义了超过64KB英文字符的变量或方法名,即使规则和全部字符都是合法的,也会无法编译 。(超出了 常量池里的 utf8 info里的u2的最大限度)
访问标志
在常量池结束之后,紧接着的2个字节代表访问标志(),这个标志用于识别一些类或者接口层次的访问信息,包括:这个Class是类还是接口;是否定义为类型;是否定义为类型;如果是类的话,是否被声明为final;等等 。
类索引及父类索引与接口索引集合
类索引()和父类索引()都是一个u2类型的数据,而接口索引集合()是一组u2类型的数据的集合,Class文件中由这三项数据来确定该类型的继承关系 。