学习笔记JVM之内存模型
Posted CodeMarker
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习笔记JVM之内存模型相关的知识,希望对你有一定的参考价值。
Java虚拟机所管理的内存由程序计数器、虚拟机栈、本地方法栈、Java堆、方法区组成。
如果根据受访权限的不同设置,可以将上述几个区域分为线程共享和非线程共享两大类。线程共享是指可以允许被所有的线程共享访问的内存区域,这类区域包括方法区和堆。非线程共享是指线程内部私有访问区域。这类区域包括虚拟机栈、本地方法栈、程序计数器。
1、程序计数器(Program Counter Register)
程序计数器是一个记录着当前线程所执行的字节码的行号指示器。它是一块很小的内存区域,也是运行速度最快的内存区域。它作为线程执行字节码解释器,用于存储程序执行过程中的字节码指令、分支、循环、异常处理、线程恢复等数据。
2、虚拟机栈(VM Stack)
虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应这一个栈帧在虚拟机栈中入栈到出栈的过程。虚拟机栈同程序计数器一样,它也是线程私有的。栈中存储基本数据类型和对象的引用。
虚拟机栈的特性:
线程私有。
先进后出(LIFO)
存储栈帧,支持Java方法的调用、执行和退出
可能出现OutOfMemoryError异常和StackOverflowError异常
3、本地方法栈(Native Stack)
本地方法栈和Java虚拟机栈的功能很相似。Java虚拟机栈用于管理Java函数的调用,而本地方法栈用于管理本地方法的调用。本地方法并不是用Java实现的,而是用C实现的。
本地方法栈的特性:
线程私有
后进先出(LIFO)栈
作用是支撑Native方法的调用、执行和退出
可能出现OutOfMemoryError异常和StackOverflowError异常
4、堆(Heap)
堆是一块用于存储对象实例和数组的内存区,是JVM虚拟机内存管理中最大的一块区域。所有的对象实例和数组都在堆上分配。
Java对象分为两类:一类是生命周期较短的,快速创建消亡的。还有一类是生命周期较长的。所以,又将堆分为新生代(Young Generation)和老年代(Old Generation),新生代和老年代采用不同的垃圾回收机制。
新生代(Young Generation)又可以分为 Eden Space 空间 (伊甸园区)、From Survivor 空间(From 生存区)、To Survivor 空间(To 生存区),它们的比例是8:1:1.
而老年代则是生命周期较长的对象和数组的存储区域。
堆是一块共享的区域,会出现线程安全的问题,而操作共享区域就需要锁和同步,通过- Xms设置堆的最小值,堆内存越小越容易发生内存不够用的情况而触犯 Full GC(对新生代、老年代、永久代进行垃圾回收)。官方推荐新生代大小占整个堆大小的 3/8,通过- Xmx设置堆的最大值,堆内存超过此值会发抛出 OutOfMemoryError 异常。
5、方法区(Method Area)
方法区也是所有线程共享的区域,主要存储被虚拟机加载的类信息、常量、静态变量,堆存储对象数据,方法区存储静态信息。
方法区不像 Java 堆区那样经常发生垃圾回收,但不表示不会发生。永久代的大小跟新生代、老年代比都是很小的,通过设置- XX:MaxPermSize来指定最大内存,方法区需要的内存超过此值会抛出 OutOfMemoryError 异常。以上是关于学习笔记JVM之内存模型的主要内容,如果未能解决你的问题,请参考以下文章