一 JAVA运行时内存区域
JVM在加载class文件时,会将class文件定义的数据结构转为运行时内存中的数据,那么jvm是如何安排运行时的内存区域呢?
jvm将运行时内存划分为以下几个部分:
堆:所有线程共享
方法区:类信息、静态变量、常量等
运行时常量池:class文件的常量池(字面常量和符号引用)+运行时产生的常量
程序计数器: 当前线程执行的字节码的行号指示器
虚拟机栈:栈帧 = 本地局部变量表、操作数栈、动态链接、出口信息
本地方法栈:native方法
直接内存:不属于jvm管理,但是在nio中,会使用native方法申请堆外内存,并在java堆中保存其引用。
其中,堆和方法区是所有的线程所共享的,而虚拟机栈、本地方法栈和程序计数器是各线程所独享的。
二 class文件
class文件是怎样定义的呢?它与java运行时内存是什么关系呢?
class文件格式:
u4 魔数
u2 class文件版本号
u2 class文件版本号
u2 constant_pool_count 表示常量池容量大小,从1开始计数;
常量池中主要存放两大类:字面常量和符号引用
符号引用又包含三类:类、接口的全限定名,字段名称和描述,方法名称和描述
注意这里会定义字段常量与方法常量。与后面的字段表/方法表略有不同,但是会复用相同的简单名称和描述符。
cp_info constant_pool
共定义了11种常量项
u2 access_flag
是否是类/接口,是否是抽象类,是否是private等,是否是final等
u2 this_class
u2 super_class
u2 interface_count
u2 interfaces
都是指 常量池中的全限定名称,先指向类/接口索引,再找到utf-8的索引
u2 fields_count
field_info fields
字段表中会包含 字段access属性、字段名称索引、描述符索引以及attribute;
描述符:数组 [, V void, L 引用类型, 描述方法时,先用小括号描述参数列表,后面再跟上返回值描述。
字段表中不会列出父类和超类中继承而来的字段名
u2 methods_count
method_info methods
方法表:access属性,名称索引、描述索引以及attribute
如果方法没有被override,则不会出现父类继承而来的方法名
u2 attributes_count
attribute_info attributes
属性表中最重要的要数方法表的Code属性,其中包含了方法的具体信息,具体如下:
u2 attribute_name_index
u4 attribute_length
u2 max_stack 操作数栈的最大深度
u2 max_locals
u4 code_length
u1 code * code_length
....异常表等