资讯专栏INFORMATION COLUMN

深度理解JVM-----运行时数据区域

tuantuan / 1999人阅读

摘要:在之后,原来永久代的数据被分到了堆和元空间中。元空间存储类的元信息,静态变量和常量池等放入堆中。这样能在一些场景中显著提高性能,因为避免了在堆内存和堆外内存来回拷贝数据。

以下内容部分转载于: CS-Notes

程序计数器(Program Counter Register)

记录正在执行的虚拟机字节码指令的地址(如果正在执行的是本地方法则为空)。

ps:什么是本地方法?

本地方法是由其他语言(如C、C++ 或其他汇编语言)编写,编译成和处理器相关的代码。本地方法保存在动态连接库中,格式是各个平台专用的,运行中的java程序调用本地方法时,虚拟机装载包含这个本地方法的动态库,并调用这个方法。

学过计算机组成的同学将不难理解,通过计数器寻找到下一条指令

每一个线程都必须存在一个程序计数器,因为一个处理器在同一时间只能处理一个线程(对于单核处理器,或者多核处理器的一个内核)

通过程序计数器,来记录每一个线程所执行到的位置,方便线程直接的切换

Java虚拟机栈(Java Virtual Machine Stacks)

虚拟机栈也是每个线程私有的,它的生命周期与线程相同,虚拟机栈描述的是Java方法执行的内存模型

包括:局部变量表,操作数栈,动态链接,方法出口等信息

每一个方法的从执行到完成,就代表着一个栈的在虚拟机栈中的入栈和出栈的过程

该区域可能抛出以下异常

StackOverflowError :当线程请求的栈深度超过最大值,如递归造成的方法多次调用

OutOfMemoryError :栈进行动态扩展时如果无法申请到足够内存

本地方法栈(Native Method Stack)

本地方法(Native Method): 由其他语言(如C、C++ 或其他汇编语言)编写,编译成和处理器相关的代码。本地方法保存在动态连接库中,格

式是各个平台专用的,运行中的java程序调用本地方法时,虚拟机装载包含这个本地方法的动态库,并调用这个方法。

具体用法和虚拟机栈类似,只不过它服务的对象为本地方法,在Sun公司的HotSpot虚拟机中,就将把本地方法栈和虚拟机栈合二为一

同样会出现 StackOverflowErrorOutOfMemoryError 错误

堆(Heap)

堆是一块被Java所有线程共享的一块内存区域,主要用于存放对象实例和数组

在堆中可以分为

新生代(Young Generation)

老年代(Old Generation)

我们常说的 GC(Garbage Collected Heap) 说的就是整理这一块的内存区域

堆的内存区域不需要连续,可以动态的增加内存,增加失败会抛出 OutOfMemoryError 异常。

可以通过 -Xms 和 -Xmx 这两个虚拟机参数来指定一个程序的堆内存大小,第一个参数设置初始值,第二个参数设置最大值。

java -Xms1M -Xmx2M HackTheJava
方法区(Method Area)

方法区和堆一样,也谁被所有线程共享的内存区域,用于存储已被虚拟机加载的类,常量,静态变量,即时编译器编译后的代码等数据

有一个别名 Non-Heap(非堆),在HotSpot虚拟机上人们习惯称之为 永久代(Permanent Generation)

方法区为JVM的一个规范,定义为存放某些数据,在不同的虚拟机中存在着不同的实现

因为在HotSpot虚拟机上,也存在这方法区的垃圾回收,所以称为永久代。

在永久代中经常会产生对永久代的回收不完全导致内存泄漏爆出OutOfMemoryError的错误

为了更容易管理方法区,在JDK8中,废弃了永久代,改用元空间代替

方法区移至到元空间中,元空间存储于本地内存中,而不是在JVM虚拟机

方法区是一个 JVM 规范,永久代与元空间都是其一种实现方式。

在 JDK 1.8 之后,原来永久代的数据被分到了堆和元空间中。元空间存储类的元信息,静态变量和常量池等放入堆中。

运行时的常量池(Runtime Constant Pool)

运行时的常量池是方法区的一部分,用于存放编译期产生的各种字面量和符号引用

这部分内容将在类加载后进去方法区的运行时常量池存放

除了在编译期生成的常量,还允许动态生成,例如 String 类的 intern()。

直接内存(Direct Memory)

直接内存并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域

但是这个区域的内存被频繁使用,任然会造成OutOfMemoryError的异常

JDK 1.4 中新引入了 NIO 类,它可以使用 Native 函数库直接分配堆外内存,然后通过 Java 堆里的 DirectByteBuffer 对象作为这块内存的引用进行操作。

这样能在一些场景中显著提高性能,因为避免了在堆内存和堆外内存来回拷贝数据。

PS: 直接内存不受Java堆大小的限制,但是既然是内存肯定还是会受本机总内存的影响

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/74584.html

相关文章

  • 《深入理解java虚拟机》学习笔记系列——java内存区域划分

    摘要:运行时数据区域的学习,是学习以及机制的基础,也是深入理解对象创建及运行过程的前提。了解内存区域划分,是学习概念的前提。 Java 运行时数据区域的学习,是学习 jvm 以及 GC 机制的基础,也是深入理解 java 对象创建及运行过程的前提。废话不多说,直接进入正题: 一张图总结 showImg(https://segmentfault.com/img/bVOMAn?w=685&h=5...

    史占广 评论0 收藏0
  • 【修炼内功】[JVM] 浅谈虚拟机内存模型

    摘要:也正是因此,一旦出现内存泄漏或溢出问题,如果不了解的内存管理原理,那么将会对问题的排查带来极大的困难。 本文已收录【修炼内功】跃迁之路 showImg(https://segmentfault.com/img/bVbsP9I?w=1024&h=580); 不论做技术还是做业务,对于Java开发人员来讲,理解JVM各种原理的重要性不必再多言 对于C/C++而言,可以轻易地操作任意地址的...

    sanyang 评论0 收藏0
  • JVM的内存模型

    摘要:的内存模型概述虚拟机在执行程序的过程中,会把它所管理的内存划分为若干个不同的数据区域。程序计数器这是一块较小的内存,它可以看做是当前线程所执行的字节码的行号指示器。 JVM的内存模型 概述 Java虚拟机在执行java程序的过程中,会把它所管理的内存划分为若干个不同的数据区域。这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖用户线程的启动...

    andycall 评论0 收藏0
  • JVM内存模型与运行数据区域

    摘要:内存模型和运行时数据区域的关系主内存对应着堆,工作内存对应着栈。在的单例模式中有运用到二运行时数据区域内存区域因为的运行时数据区域一直在改善,所以不同版本之间会有不同。 一、java内存模型 showImg(https://segmentfault.com/img/remote/1460000016694250?w=1810&h=941); java定义内存模型的目的是:为了屏蔽各种...

    canopus4u 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<