1、程序计数器
特点:程序计数器是一块较小的内存空间,可以看做当前线程所执行的字节码的行号指示器,它是线程私有的,生命周期与线程相同。
作用:字节码解释器通过改变程序计数器的值来选取下一条需要执行的字节码指令,从而实现代码的流程控制。
异常情况:程序计数器是唯一不会出现OutOfMemoryError的内存区域。
2、Java虚拟机栈
特点:Java虚拟机栈描述的是Java方法执行的线程内存模型,每个方法被执行时,Java虚拟机都会同步创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口信息等。
异常情况:如果线程请求的栈深度超过最大深度,将抛出StackOverflowError;如果虚拟机栈可以动态扩展,但无法申请到足够的内存,则会抛出OutOfMemoryError。
3、本地方法栈
特点:本地方法栈与Java虚拟机栈类似,区别在于本地方法栈为Native方法服务。
异常情况:同样会抛出StackOverflowError和OutOfMemoryError。
4、堆
特点:堆是Java虚拟机所管理的最大内存区域,所有线程共享,它的主要目的是存放实例对象,几乎所有的对象实例和数组都在这里分配内存。
分代:堆内存分为新生代和老年代,新生代又分为Eden区和Survivor区,大部分新创建的对象首先在Eden区分配内存,经过垃圾回收后仍然存活的对象会被移动到Survivor区,最终可能晋升到老年代。
异常情况:最容易出现OutOfMemoryError错误。
5、方法区
特点:方法区是各个线程共享的内存区域,用于存储已被虚拟机加载的类信息、静态变量、常量、即时编译器编译后的代码等数据。
发展历史:JDK 7及之前的版本中,方法区被称为永久代;JDK 8之后,永久代被元空间(MetaSpace)取代,元空间使用的是直接内存。
运行时常量池:方法区的一部分,用于存放编译期生成的各种字面量和符号引用,当常量池无法再申请到内存时会抛出OutOfMemoryError错误。
6、直接内存
特点:直接内存并不是JVM运行时数据区的一部分,但它也是由Java虚拟机管理的内存,在JDK 1.4引入了NIO机制后,可以直接使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。
相关问题与解答:
1、问题一:为什么JDK 8之后要用元空间替代永久代?
解答:JDK 8之后用元空间替代永久代的原因有以下几点:永久代有JVM本身设置的固定内存大小上限,而元空间使用直接内存,受本机可用内存的限制,使得溢出的几率减小;元空间的大小仅受本地内存限制,可以指定元空间大小;将字符串常量池从永久代移除可以避免永久代出现性能问题和内存溢出。
2、问题二:什么是逃逸分析?它对Java对象的内存分配有什么影响?
解答:逃逸分析是一种在编译期间确定对象动态作用域的技术,如果某个方法中的对象引用没有被返回或被外面使用(即未逃逸出去),那么这个对象可以直接在栈上分配内存,而不是在堆上分配,这种技术可以减少堆上的内存分配,提高程序的运行效率。
小伙伴们,上文介绍了“一、JVM内存区域详解 _JVM监控”的内容,你了解清楚吗?希望对你有所帮助,任何问题可以给我留言,让我们下期再见吧。
原创文章,作者:未希,如若转载,请注明出处:https://www.kdun.com/ask/1169553.html
本网站发布或转载的文章及图片均来自网络,其原创性以及文中表达的观点和判断不代表本网站。如有问题,请联系客服处理。
发表回复