java虚拟机内存情况检测,测试啦啦啦啦啦1111

图中能够看到的就不赘述了,细说一下各个模块:(1)、程序计数器:在图中可以看到是一个很大的绿块,其实程序计数器本身只是很小的一部分内存,顾名思义,他的功能就是记录程序当前执行到哪一个指令的,图中可以看到程序计数器是非线程共享的,也就是每一个线程都有一个自己的程序计数器,原因是单核情况下多线程是由于切换上线文实现的,也就是在某一时刻实际上只有一个执行在执行,而当前线程结束之后需要回到另外一个线程去,所以这个时候就需要一个程序计数器记录另一个线程执行到哪里了,否则就找不到了。当线程执行的是java方法时,计数器记录的值即为正在执行的jvm中字节码指令的地址,如果线程执行的是native方法(非java方法时),此时计数器的值为空(Undefined)。程序计数器是虚拟机中唯一一块不会OOM的区域。(2)、虚拟机栈:虚拟机栈也是线程独占的内存,不共享,生命周期和线程相同。虚拟机栈是做什么用的呢?在java方法执行过程中所产生的的对象就存储在这个区域中。当一个方法执行时就会创建一个栈帧,用于存放局部变量表,操作数栈,动态链接,方法出口等信息,方法执行的过程就对应着虚拟机栈入栈出栈的过程。虚拟机栈中的局部变量表应该是我们最容易理解也最关键的部分,我们在方法中的创建的每一个变量都在这里面。? ? ? ? ? ? 需要注意的是:局部变量表的大小在编译时就已经确定了,并且不会改变,因为我们编译的时候就能清楚的知道方法中定义的每一个基本数据类型和引用。其中64位的double和long占用两个局部变量空间,其他的数据类型都只占用一个。? ? ? ? ? ? 在虚拟机栈中是会出现两种溢出,一种是栈深超过了指定长度就会报出stack溢出异常,但是的虚拟机栈基本都是定义的可扩展的,所以一般不容易发生前面这种异常,同时也会带来后一种溢出异常,当栈进行扩展时发现无可用的内存进行扩展,就会报内存溢出。

(3)、本地方法栈:本地方法栈和虚拟机栈的功能是一样的,唯一区别是虚拟机栈是为java方法服务,而本地方法栈是为native方法服务。由于java虚拟机规范中对本地方法栈的限制很少,所以各家厂商的实现不尽相同,甚至有把本地方法栈融入到虚拟机栈中的。

异常方面和虚拟机栈一样存在栈溢出和内存溢出两种异常。

(4)、堆:上面说的三块区域属于线程独占内存,而堆则是属于线程共享内存了。java虚拟机规范上描述是:所有的对象实例包括数组的内存都要在堆上分配(随着jit编译器,逃逸分析技术的发展,现在不是那么绝对了),所以很好理解对于大多数应用来说堆是最大的一块内存区域了,对的生命周期是和虚拟机共生共灭的,但是堆上的对象则是会被回收的,堆也是GC回收的主要战场。根据java虚拟机规范定义,堆是可以在不连续的内存空间上的,所以只要逻辑允许,堆是可扩展的。(堆上的各种细分以及垃圾回收机制我们到GC章节单独细说)

堆上会发生内存溢出,当没有内存能够进行生成实例,并且也没有内存可以扩展的时候就会报内存溢出。

(5)、方法区:和堆一样,这部分是线程共享区。同样,顾名思义方法区可以理解为代码逻辑层,或者说叫堆的逻辑层,比如编译后的正在执行的代码,静态变量,加载的那些类的基本信息,以及常量池都在方法区中。方法区和堆一样也需要参与到垃圾回收,主要回收目标是常量池和对类进行卸载。

异常方面和堆一样,当无法满足内存分配需求时就会报内存溢出。

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

微信扫一扫

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值