jvm模型

1、 总体结构

    JVM内存模型,又称为JVM运行时数据区,总体结构如下图:
jvm模型

1.1 共享数据区

    一个jvm进程中一般会存在多个线程,而共享数据区就是指所有线程都可以访问到的内存空间,图中灰色部分几位共享数据区。

1.1.1 堆

    我们上学的时候老师说过java内存中分为堆和栈,而老师口中的堆,其实就是这里的堆,java虚拟机规范上描述中说,所有的对象实例包括数组的内存都要在堆上分配(随着jit编译器,逃逸分析技术的发展,现在不是那么绝对了),所以很好理解对于大多数应用来说堆是最大的一块内存区域了,其生命周期是和虚拟机共生共灭的,但是堆上的对象则是会被回收的,堆也是GC回收的主要战场。根据java虚拟机规范定义,堆是可以在不连续的内存空间上的,所以只要逻辑允许,堆是可扩展的。

1.1.2 方法区

    方法区可以理解为代码逻辑层,或者说叫堆的逻辑层,比如编译后的正在执行的代码,静态变量,加载的那些类的基本信息,以及常量池都在方法区中。方法区和堆一样也需要参与到垃圾回收,起主要回收目标是常量池和对类进行卸载。异常方面和堆一样,当无法满足内存分配需求时就会报内存溢出。

1.2 线程独占内存区

    线程独占也很好理解,指这部分内存归属于当前线程,其他线程是无法访问的,所以我们一般讨论线程安全的时候,都是只共享数据区中数据存在线程安全问题。线程独占内存区是不存在线程安全问题的,他们都是线程安全的,其他线程根本无法访问。

1.2.1 程序计数器

    图中程序计数器占了很大一块地方,实际上在jvm内存中,程序计数器是一块很小的内存。程序计数器是用来记录当前线程,目前执行到了哪一行指令的,原因是多线程之间是存在上下文切换的(写多线程的时候讲过),而程序计数器的存在就是为了防止当上下文重新切换回来时还找得到当前线程执行到了哪一步了。当线程执行的是java方法时,计数器记录的值即为正在执行的jvm中字节码指令的地址,如果线程执行的是native方法(非java方法时),此时计数器的值为空(Undefined)。程序计数器是虚拟机中唯一一块不会OOM的区域。

1.2.2 虚拟机栈

    在java方法执行过程中所产生的的对象就存储在这个区域中。当一个方法执行时就会创建一个栈帧,用于存放局部变量表,操作数栈,动态链接,方法出口等信息,方法执行的过程就对应着虚拟机栈入栈出栈的过程。虚拟机栈中的局部变量表应该是我们最容易理解也最关键的部分,我们在方法中的创建的每一个变量都在这里面。

1.2.2 本地方法栈

    本地方法栈和虚拟机栈的功能是一样的,唯一区别是虚拟机栈是为java方法服务,而本地方法栈是为native方法服务。由于java虚拟机规范中对本地方法栈的限制很少,所以各家厂商的实现不尽相同,甚至有把本地方法栈融入到虚拟机栈中的。异常方面和堆一样,当无法满足内存分配需求时就会报内存溢出。

    jvm内存模型是我们经常在面试中遇到的问题,但是从实用角度来说,学习jvm内存模型到底有什么用呢?在一个低并发,低内存消耗的系统中这些自然都不用考虑,但是反之则需要认真考虑内存是否够用的问题,是哪部分内存溢出了,溢出原因是什么,是选择添加集群还是可以尝试优化代码?这些判断都需要建立在我们对jvm内存模型掌握的基础之上。

发布了39 篇原创文章 · 获赞 9 · 访问量 993

猜你喜欢

转载自blog.csdn.net/qq_30095631/article/details/104033299