JVM的内存结构

       整个JVM的内存区域包括方法区、本地方法栈、虚拟机栈、堆、程序计数器。

       其中程序计数器与虚拟机栈为线程私有:

       程序计数器:用来记录当前JVM执行字节码的地址,之所以为线程私有是因为Java的多线程会有线程的切换,假如A线程在执行过程中失去对资源的支配权,此刻A线程的执行状态就保存在程序计数器中,以便重新获得资源支配权时能继续之前的工作,如果线程正在执行一个java方法,则计数器的内容为JVM执行字节码的地址,若是一个本地方法(操作系统中的函数),则为空。

       虚拟机栈:每个方法执行时都会在虚拟机栈中创建一个栈帧,用于存放局部变量表、操作数栈、动态链接、方法返回地址等。每个方法从调用开始到调用结束的过程都对应虚拟机栈的进栈与出栈。


      局部变量表:为一个数组,通过索引来访问,保存java方法的形参、局部变量、对象的引用。将java源文件反编译后,“locals”表示局部变量表,紧跟其后的数字表示局部变量表中的变量的个数。局部变量表的基本单位为slot(槽),每个slot占用32位长度的内存空间,其中存放的数据的类型是在编译期间就可知的各种基本数据类型、对象引用,对于类的非静态方法,0号索引为this指针,静态方法则不是,局部变量表的大小在编译时就已经确定,当一个方法进入虚拟机栈时,所需的局部变量表的大小是确定的,类型short、byte、char会被转换成int存储(之所以这样是因为java虚拟机指令集不支持short、byte、char类型,由于指令集的字节有限,所以必须去掉某些基本数据类型),long、double在局部变量表中占连续两个存储单元,以最第一个存储单元的索引为访问时的索引,为了节约内存,slot可重用(意味着原先该slot存储的数据会丢失)。


    操作数栈:操作数栈也被组织成数组,访问数据是通过进栈与出栈操作实现的,在操作数栈中存储数据的方式与在局部变量表中一样,该内存的大小在编译期间确定,在方法的执行过程中,会有各种字节码指令向操作栈写入和提取内容,相当于一个数据操作的中转站,例如执行i=2+6,则JVM会先后将2和6压入栈内,然后从栈中弹出两个操作数进行相加,压入栈内,然后弹出结果,写入局部变量表。


     动态链接:每个栈帧都包含一个指向运行时常量池的引用,持有者个引用是为了方法执行过程中的动态链接,在class文件中存在运行时常量池,包括有大量的符号引用,这些符号引用一部分在类加载或是第一次使用时转换成直接引用,称为静态解析,另一部分在每一次运行时转换为直接引用,称为动态链接。

符号引用:在编译时,java类并不知道引用类的实际内存地址,用一个符号来表示。

直接引用:知道了引用类的实际内存地址后符号引用转换成直接引用。


      方法返回地址:当一个方法被执行后,有两种方法退出方法,一是执行引擎执行到一个方法的返回字节码指令,此时如有返回值,则压入对应的操作数栈中,这种方式称为正常完成出口。

二是当执行方法出现异常时,若本方法内没有对应异常的处理,则会导致方法的退出,以这种方式退出时不会产生返回值,称为异常完成出口。

无论以何种方式退出,都需要返回地址,如果是正常完成出口,则会返回调用者PC计数器的内容,在本方法的栈帧中可能保存有调用者PC计数器的内容,若是异常完成出口,则返回地址由异常处理器决定。


      线程共有:堆、方法区、本地方法区

     堆:是大部分对象的聚集地,用new申请内存空间就是在这里申请。JDK8堆内存的结构如下(之所以这样划分与垃圾回收机制有关,之后会整理一篇博客):

JDK8的堆内存包括:新生代、老年代,JDK8之前的存储元数据的永久代换移到了本地内存中,从而永久内存不在占用堆内存,

JDK8也提供了一个新的设置Matespace内存大小的参数,通过这个参数可以设置Matespace内存大小

-XX:MaxMetaspaceSize=128m 设置最大的元内存空间128兆,

如果不设置JVM将会根据一定的策略自动增加本地元内存空间。

如果你设置的元内存空间过小,你的应用程序可能得到以下错误:

java.lang.OutOfMemoryError: Metadata space

新创建的对象会在新生代中的Eden区域分配内存,若经过了两个Survivior(应该有标记字段记录是否存活了两个survivor),则会转移到老年代

       方法区(包含运行时常量区):主要存储JVM加载类的类信息,类变量、常量、即时编译器编译后的编译后的代码的数据。

     运行时常量区:用于存放编译器生成的各种字面量和符号引用

     本地方法区:类似于虚拟机栈,本地方法区为执行本地操作系统的方法服务

      


  

      

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值