jvm运行时数据区表示

方法区的概念

根据JVM的规范,方法区用来存储类的结构,好比运行时常量池,字段和方法数据,方法和构造函数的代码,以及类和实例初始化,接口初始化中使用的一些特殊方法。规范把方法区从逻辑上看作是属于堆的一部分,不一样的实现能够选择是否要对这块代码作垃圾回收和压缩,可是虚拟机规范自己并不强制规定方法区的位置(JDK 7 规范 JDK 8 规范 JDK 9 规范 JDK 10 规范 JDK 11 规范 在这一点上都是如此)。也就是说不一样的实现能够放在不一样的地方html

如下来自hotspotjava

PermGem的概念

Hostspot中特有,它是方法区的一种实现。在jdk 7中,经过 -XX:MaxPermSize来决定最大的永久代大小,-XX:PermSize来控制方法区的初始大小。注意这里讲到 PermGem 是指permanent generation,它是从垃圾回收的角度来产生了一个generation的概念数组

在JVM中,有些对象很快被回收,有的则相对比较慢,为了优化不一样的对象回收的场景,就提出分代处理的概念 Generation详见oracle

方法区与“堆”的关系

要看“堆”的上下语境。jvm

  • 若是堆指的是 GC heap,那么它就是在堆中,值得注意的是,若是说 Native memory,这里所指的角度就是 GC heap。
  • 若是这个堆是从广义上讲java heap的定义:哪儿存储了java对象,哪儿就是 java heap,那它就是在堆中 (java.lang.String的一些实例会存在这里)
  • 若是堆指的是运行时数据区中,用来分配类实例和数组的这块区域,那么它就再也不堆中,从这个角度讲它也称做 non-heap

常量池与PermGen的关系

常量池有不少种,要看常量池的角度函数

好比字符串常量,Integer常量,全量地址戳这里优化

  • 若是是 runtime constant pool,它还在PermGen里面
  • 若是是 SymbolTable、StringTable,它们一直存在 native memory
  • 若是是说 SymbolTable、StringTable的引用,jdk 7开始,SymbolTable引用的Symbol移动到了native memory,而StringTable则移到了普通的hava heap

StringTable 就是经过hash存储一般的String的字符串常量表 ;SymbolTable用来保存定位和从新定位符号定义和符号引用所须要的信息this

运行时常量池 表示类文件中每一个类或者每一个接口运行时的表示,它包括编译时已知的数字常量到必须在运行时解析的方法和字段引用spa

jdk8 对PermGen 的改进

hotspot中移除了PermGen,使用Metaspace,可使用-XX:MetaspaceSize-XX:MaxMetaspaceSize配置线程

permGen,“heap”,常量池之间的关系参考

栈帧

帧用来存储数据和部分结果,包括动态链接、方法返回值和打包异常。 一个新的帧会在方法执行的时候建立,并在方法执行完毕的时候销毁。每一个帧都会包含本身的局部变量,操做数栈和类当前运行方法对运行时常量池的引用。在编译的时候,局部变量和操做数栈的大小就定下来了。任什么时候候,给定一个线程只有一个帧是Active,它又被称做当前帧

线程本身建立的帧是不能和其它线程共享的

局部变量

局部变量经过下标索引的方式访问。第一个局部变量的索引是0,方法执行过程当中的传参也是使用局部变量来实现的,他们从0开始一直按照递增的方式连续的增加下标表示不一样的参数。特别的下标0永远表示传递的对象的引用,在java中就是 this

操做数栈

每一个帧都包含了一个 后进先出 的栈,包含操做数的帧刚创建的时候,它是空的,JVM会提供指令来把常量、字段值、局部变量加载如栈,而后由其它的指令取出并操做,而后把结果放回到栈中

传递给下一个方法的参数和接收方法的返回值也都是放在这里

操做数栈中的每个值的类型和操做方法必定是匹配上的,这种关系在class文件上会作验证。在任意的时刻,栈自己都会对应着栈的深度,它支持JVM中的任何类型,除去long和double会占据两个单元,其它类型都只占据一个单元

动态链接

class文件的代码中,对要执行的方法和变量都是经过符号引用获取的,动态链接负责把这些符号引用转换成对应的方法引用,加载那些还未定义过的符号,并把变量运行时的位置转换成存储结构中正确偏移处。

经过维持常量池的引用就能够达到这种动态链接的实现

相关文章
相关标签/搜索