根据JVM的规范,方法区用来存储类的结构,好比运行时常量池,字段和方法数据,方法和构造函数的代码,以及类和实例初始化,接口初始化中使用的一些特殊方法。规范把方法区从逻辑上看作是属于堆的一部分,不一样的实现能够选择是否要对这块代码作垃圾回收和压缩,可是虚拟机规范自己并不强制规定方法区的位置(JDK 7 规范 JDK 8 规范 JDK 9 规范 JDK 10 规范 JDK 11 规范 在这一点上都是如此)。也就是说不一样的实现能够放在不一样的地方html
如下来自hotspotjava
Hostspot中特有,它是方法区的一种实现。在jdk 7中,经过 -XX:MaxPermSize
来决定最大的永久代大小,-XX:PermSize
来控制方法区的初始大小。注意这里讲到 PermGem 是指permanent generation
,它是从垃圾回收的角度来产生了一个generation
的概念数组
在JVM中,有些对象很快被回收,有的则相对比较慢,为了优化不一样的对象回收的场景,就提出
分代
处理的概念 Generation详见oracle
要看“堆”的上下语境。jvm
Native memory
,这里所指的角度就是 GC heap。常量池有不少种,要看常量池的角度函数
好比字符串常量,Integer常量,全量地址戳这里优化
StringTable 就是经过hash存储一般的String的字符串常量表 ;SymbolTable用来保存定位和从新定位符号定义和符号引用所须要的信息this
运行时常量池 表示类文件中每一个类或者每一个接口运行时的表示,它包括编译时已知的数字常量到必须在运行时解析的方法和字段引用spa
hotspot中移除了PermGen,使用Metaspace,可使用-XX:MetaspaceSize
和-XX:MaxMetaspaceSize
配置线程
帧用来存储数据和部分结果,包括动态链接、方法返回值和打包异常。 一个新的帧会在方法执行的时候建立,并在方法执行完毕的时候销毁。每一个帧都会包含本身的局部变量,操做数栈和类当前运行方法对运行时常量池的引用。在编译的时候,局部变量和操做数栈的大小就定下来了。任什么时候候,给定一个线程只有一个帧是Active,它又被称做当前帧
线程本身建立的帧是不能和其它线程共享的
局部变量经过下标索引的方式访问。第一个局部变量的索引是0,方法执行过程当中的传参也是使用局部变量来实现的,他们从0开始一直按照递增的方式连续的增加下标表示不一样的参数。特别的下标0永远表示传递的对象的引用,在java中就是 this
每一个帧都包含了一个 后进先出 的栈,包含操做数的帧刚创建的时候,它是空的,JVM会提供指令来把常量、字段值、局部变量加载如栈,而后由其它的指令取出并操做,而后把结果放回到栈中
传递给下一个方法的参数和接收方法的返回值也都是放在这里
操做数栈中的每个值的类型和操做方法必定是匹配上的,这种关系在class文件上会作验证。在任意的时刻,栈自己都会对应着栈的深度,它支持JVM中的任何类型,除去long和double会占据两个单元,其它类型都只占据一个单元
class文件的代码中,对要执行的方法和变量都是经过符号引用获取的,动态链接负责把这些符号引用转换成对应的方法引用,加载那些还未定义过的符号,并把变量运行时的位置转换成存储结构中正确偏移处。
经过维持常量池的引用就能够达到这种动态链接的实现