平舆专业网站建设,网站开发周期,网站规划设计方案,大数据精准营销论文一、内存模型概览
本文介绍的是JDK1.8的内存模型。1.8同1.7相比#xff0c;最大的差别就是元空间取代了永久代。元空间的本质和永久代类似#xff0c;都是堆JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于#xff1a;元空间并不存在虚拟机中#xff0c;而是…一、内存模型概览
本文介绍的是JDK1.8的内存模型。1.8同1.7相比最大的差别就是元空间取代了永久代。元空间的本质和永久代类似都是堆JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于元空间并不存在虚拟机中而是使用本地内存。
内存模型概览如下
其中程序计数器、虚拟机栈、本地方法栈是线程私有的。方法区、堆是线程公有的。 二、运行时数据区
2.1、程序计数器
程序计数器是一块较小的内存空间它可以看做是当前线程所执行的字节码的行号指示器。
字节码解释器的工作就是通过改变这个计数器的值来选取下一条需要执行的字节码指令它是程序控制流的指示器分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
每条线程都有一个独立的程序计数器各条线程之间计数器互不影响独立存储。
2.2、虚拟机栈
和程序计数器一样虚拟机栈也是线程私有的它的生命周期和线程相同。
虚拟机栈描述的是方法执行的线程内存模型方法执行的时候Java虚拟机都会在虚拟机栈里面创建一个栈帧栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。
每一个方法被调用直至执行完毕的过程就对应着一个栈帧在虚拟机中从入栈到出栈的过程。
入栈出栈图解 栈的溢出(StackOverflowError)
如果栈帧的数量过多或者某些栈帧过大会引发SOE(StackOverflowError)
如果允许虚拟机栈动态扩展那么当内存不足时会导致OOM(OutOfMemoryError) 栈帧图解 局部变量表
局部变量表存放了这个栈帧对应的方法的局部变量(基本类型是值、引用类型是句柄或者指针) 操作数栈
主要用于保存计算过程中的中间结果,同时作为计算过程中变量临时的存储空间
当一个方法开始执行的时候这个方法的操作数栈是空的在方法的执行过程中会有各种字节码指令向操作数栈中写入和提取内容也就是出栈和入栈操作。
例如整数加法(23)的字节码指令iadd这条指令在运行的时候要求操作数栈中最接近栈顶的两个元素已经存入了int类型的数据当执行这个指令时会把这两个int值出栈并相加然后将相加的结果重新入栈。 动态连接
动态连接
将符号引用转化为直接引用的过程。
符号引用符号引用以一组符号来描述所引用的目标符号可以是任何形式的字面量只要使用时能够无歧义地定位到目标即可。
直接引用直接引用可以是直接指向目标的指针也可以是能间接定位到目标的句柄还可以是相对偏移量。
每个栈帧都包含一个指向运行时常量池在方法区中后面介绍中该栈帧所属方法的引用持有这个引用是为了支持方法调用过程中的动态连接
方法出口
无论是程序正常返回或者是异常调用完成返回都必须回到最初方法被调用时的位置。
2.3、本地方法栈
本地方法栈也是线程私有的。
本地方法栈与虚拟机栈所发挥的作用是类似的区别是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务而本地方法栈是为虚拟机使用到的本地Native方法服务。
与虚拟机栈一样本地方法栈也会在栈深度溢出或者栈扩展失败时分别抛出StackOverflowError和OutOfMemoryError。
2.4、方法区
方法区只是一个概念上的东西JDK1.8元空间是方法区的实现
方法区是线程共享的内存区域它用于存储已经被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。它有一个别名叫Non-Heap。
类型信息对于加载的类型包括class、interface、enum、annotationJVM必须在方法区中存储以下类型信息
① 这个类型的完整有效名称(全名包名.类名)
② 这个类型直接父类完整有效名(对于interface或者是java.langlObject都没有父类)
③ 这个类型的修饰符(public、abstract、final的某个子集)
④ 这个类型直接接口的一个有序列表
2.4.1、运行时常量池
Class文件中除了有类的版本、字段、方法、接口等描述信息外、还有一项信息是常量池表的引用用于存放编译期生成的各种字面量与符号引用。
Java中的字节码需要数据支持通常这种数据很大以至于不能直接存到字节码里面所以就存到常量池而字节码文件存储的就是指向常量池的引用在动态链接的时候会用到运行时常量池。
在方法区中有一个非常重要的部分就是运行时常量池它是每一个类或接口的常量池表的运行时表示形式在类或接口被加载到JVM后对应的运行时常量池就被创建出来常量池表的字面量与符号引用就会放到运行时常量池。
2.5、堆
堆是线程共享的内存区域它是虚拟机管理内存中最大的一块。此区域的唯一目的就是存放对象实例Java世界里几乎所有的对象实例都在这里分配内存。当堆中没有内存分配给对象实例时会抛出OutOfMemoryError
新生代gc流程
刚刚新建的对象在Eden中经历一次Minor GCEden中存活对象就会被移动到s0Eden被清空。等Eden区再满了就出发一次Minor GCEden和s0中存活的对象又会被复制到s1中这个过程非常重要因为这种复制算法保证了s1中来自s0和Eden两部分的存活对象占用了连续的空间避免碎片化s0和Eden被清空然后下一轮s0与s1互换角色如此循环。 三、本地内存
3.1、元数据区
元数据区也叫元空间是方法区的一种实现。
存储的是类的元数据信息。
3.2、直接内存
直接内存并不是虚拟机运行时数据区的一部分。但是这部分内存也经常被使用到也有可能导致OutOfMemoryError出现。
在JDK1.4中新加入了NIO(New Input/Output)类引入了一种基于通道(channel)与缓冲区(Buffer)的I/O方式它可以用Native函数库直接分配堆外内存然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能避免了在Java堆和Native堆中来回复制数据。