首页 > 资讯 > 正文
jvm内存结构
来源:网络 阅读量:
 



程序计数器
程序计数器是用来指示当前线程要执行哪条指令,并且在执行完该条指令后让程序计数器指向下一条指令,直到将程序执行完毕。指令需要靠cpu来执行,在多线程中,多个线程是通过轮流切换分配cpu的时间片而执行的,在切换时需要记录当前执行到了哪条指令以便将来继续执行,每一个线程都需要有自己的程序计数器,所以程序计数器是线程私有的内存。
 
虚拟机栈
通常我们把jvm的内存粗略的分为堆和栈,其中的栈指的就是虚拟机栈,虚拟机栈也是线程私有的。
 
虚拟机栈对应的是方法的内存区域,每个方法执行时都会创建一个栈帧,用来存储该方法的局部变量表,操作数栈,动态链接,方法返回地址:
 

 
1. 局部变量表:局部变量表中存储的是方法的参数和方法中定义的局部变量,在编译期间就为局部变量表分配好了内存空间。局部变量表中存储三种类型的数据:
 
(1) 基本数据类型
 
(2) 引用类型:指向一个对象在内存中的地址
 
(3) returnAddress类型:指向指令的地址(已经很少见了,指向异常处理的指令,现在已经由异常表代替)
 
2. 操作数栈:当虚拟机执行一些指令的时候会对操作数栈进行入栈或出栈的操作,比如iadd指令将两个数相加,会先将操作数栈中的两个数弹出来(出栈),相加后再压入栈(入栈)中。
 
3. 动态链接:在运行时常量池中存储了诸如类名,方法名,我们要找到目标类,执行相应的方法就需要用到动态链接,栈帧中有一个指向运行时常量池的引用,通过这个引用可以找到相应的类名和方法名,但是光知道名称是没法执行方法的,需要通过名称找到相应的类和方法在内存中的地址,这个过程就是动态链接。
 
4. 方法返回地址:当方法执行完以后如果有返回值,就会把这个返回值返回给该方法的调用者,方法的返回就是我们java中用到的return命令。方法返回之后调用者需要继续往下执行就需要知道要执行的地址,该地址就是方法返回地址,它被记录在了栈帧中,当然在发生异常的情况下不会有返回值,要继续执行的地址可以通过异常处理器表来确定。
 
虚拟机栈可能出现两种类型的异常:
 
1. 线程请求的栈深度大于虚拟机允许的栈深度会抛出StackOverflowError,(虚拟机栈空间不能动态扩展的情况下)
 
2. 如果虚拟机栈空间可以动态扩展(目前多数的虚拟机都可以),当动态扩展无法申请到足够的空间时会抛出OutOfMemory异常。
 
本地方法栈
本地方法栈与虚拟机栈的作用是一样的,区别在于虚拟机栈为虚拟机执行java方法服务,而本地方法栈为虚拟机执行native方法服务,native方法为本地方法,不是用java语言写的有可能是c或者c++写的,在jdk中就有很多c的代码,就是提供给本地方法来调用的。
 

通常我们把jvm的内存粗略的分为堆和栈,其中的堆就是指它,它是虚拟机中占用内存最大的一块,是被所有线程共享的一块区域,它是用来存放对象实例的。是垃圾收集器管理的主要区域。
 
方法区
方法区也是被所有线程共享的一块区域,它存储的是类信息,常量,静态变量,编译后的字节码等信息。方法区中还有一块区域“运行时常量池“:运行时常量池中存储的是编译期生成的各种字面量和符号引用。字面量相当于Java里常量的概念,比如字符串,声明为final的常量值等,符号引用包括了:类和接口名,字段名,方法名。
 

 
OutOfMemoryError异常到底是怎么引起的?
当堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。
当方法区再扩展时会抛出OutOfMemoryError异常。
程序计数器是唯一没有OutOfMemoryError异常的区域
如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机栈动态扩展时无法申请到足够的内存时会抛出OutOfMemoryError异常。
本地方法栈(Native Method Stacks)与虚拟机栈作用相似,也会抛出StackOverflowError和OutOfMemoryError异常
 
为什么jdk1.8要把方法区从JVM里移到直接内存?
原因一:因为直接内存,JVM将会在IO操作上具有更高的性能,因为它直接作用于本地系统的IO操作。而非直接内存,也就是堆内存中的数据,如果要作IO操作,会先复制到直接内存,再利用本地IO处理。
 
从数据流的角度,非直接内存是下面这样的作用链:本地IO --> 直接内存 --> 非直接内存 --> 直接内存 --> 本地IO
而直接内存是:本地IO --> 直接内存 --> 本地IO
 
原因二:整个永久代有一个 JVM 本身设置固定大小上线,无法进行调整,而元空间使用的是直接内存,受本机可用内存的限制,并且永远不会得到java.lang.OutOfMemoryError。
 
可以使用 -XX:MaxMetaspaceSize 标志设置最大元空间大小,默认值为 unlimited,这意味着它只受系统内存的限制。
-XX:MetaspaceSize 调整标志定义元空间的初始大小如果未指定此标志,则 Metaspace 将根据运行时的应用程序需求动态地重新调整大小。
 
Java中基本数据类型和引用数据类型的存放位置

  局部变量 成员变量
基本数据类型 变量名和值都在方法栈中 变量名和值在堆内存
引用数据类型 变量在方法栈,变量指向的对象在堆 变量名和变量名指向的对象都在堆
 
 
堆内存该设置多大?如何进行JVM调优?JVM的垃圾回收是如何?创建一个String对象,JVM都做了些什么?后续内容逐步介绍
 


jvm
内存结构

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.link66.cn/news/3190.html