提起JVM,大家应该脑海中浮现出下面这个结构图
Jvm结构中元空间和堆是线程共享 ,其他是线程私有.
我们编写的java源代码,先编译成了二进制字节码,在通过类加载器放到了Jvm中运行。
元空间:类的一些信息都放在了元空间,比如字段,静态属性,方法,常量等。
堆:类创建的实例对象都放到堆,例如通过new出来的对象,jdk8后 原来的永久区内的字符串常量也移到了堆。
一篇文章带你了解堆GC
堆内存诊断:
jps工具 :查看当前系统中有哪些java进程
jmap工具:查看堆内存占用情况
jconsole工具:图形界面,多功能监测工具,可连续监测
堆里的对象调用方法时又会用到程序计数器,虚拟机栈,本地方法栈。
虚拟机栈:想象成子弹夹,子弹都是先压进去后出来,并且只能使用最顶部的那颗子弹。JVM是基于栈结构的运行环境。
程序在执行方法时,会向内存中申请开辟一个空间,称之为栈帧,我们把每个方法的当初一颗子弹压入虚拟机栈中。
虚拟机栈包含:
- 局部变量表:存放方法参数和局部变量的区域
- 操作栈:初始化状态为空的桶式结构栈,相当于战斗的士兵
- 动态连接:每个栈中包含一个放在常量池中的对当前方法的引用
- 方法返回地址:方法的退出,相当于子弹射击后出退出弹夹。
一个弹夹是有容量限制的,如果子弹过多会导致装不进去,所以栈帧过多导致栈内存溢出。
如果一颗子弹又特别特别大,可能也会导致装不进去了,所以栈帧过大也可能导致栈内存溢出。
程序计数器:用来记住下一条jvm指令的执行地址,此区域不会发生内存溢出
解释器:方法执行时每行代码通过它来解释成机器可以看懂的机器码
即时编译器:方法里面重复调用的热点代码,会由JIT编译优化
GC:对堆里面不在引用的对象进行垃圾回收
本地方法接口:调用底层操作系统的功能方法。