天天看点

jvm内存分配的基本概念

  • 程序计数器         是一块较小的内存空间,可以把它当做是当前线程所执行的字节码的行号指示器。每个线程都会有一个独立的程序计数器,各个线程之间的计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。此内存区域是唯一一个在jvm中没有规定任何内存溢出(OutOfMemoryError)情况的区域。
  • java虚拟机栈      和程序计数器一样也是线程私有的,生命周期和线程的周期相同,描述的是java方法执行的的内存模型:每个方法在执行的同时会创建一个栈帧用来存储局部变量,操作数栈,动态链接,方法出口等信息,每个方法从调用直至执行完成的过程,就对应这一个栈帧在卷虚拟机栈中的入栈和出栈的过程。此区域有两种异常:1、如果线程请求的栈深度大于虚拟机栈所容许的深度,将抛出StackOverFlowError异常。2、如果虚拟机栈可以动态扩容,当扩展到无法申请足够的内存,就会抛出OutOfMemoryError异常。
  • 本地方法栈      与虚拟机栈类似也是线程私有的。不过本地方法栈是为虚拟机栈使用到的Native方法(C语言中的)服务。在虚拟机规范中没有对本地方法栈中方法使用的语言,数据结构做强制规定。他们也会抛出StackOverFlowError异常和 OutOfMemoryError异常。
  • java堆            对于大多数应用来说,java堆(java Heap)是java虚拟机中占内存最大的一块。java堆是被所有的线程共享的一块内存区域。在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例以及数组都要在堆上分配。                                                        也是垃圾收集器管理的主要区域。故也被称为GC堆。一般分为:老年代和新生代。在细分一下:Eden空间,From Survivor空间,To Survivor空间等。                                                                                                                                                             根据Java虚拟机的规范,java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可。目前主流的虚拟机是通过-Xmx和-Xms可实现堆内存的大小的。
  • 方法区          和java堆一样也是被所有的线程共享的内存区域.它用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。 此区域也会抛出OutOfMemoryError异常。
  • 运行时常量池   是方法区的一部分,class文件中除了有类的版本,字段,方法,接口等描述信息外,还有一项信息是常量池。用于存放编译期生成的各种字面量和符号引用,这部门内容被加载后进入方法区的运行时常量池中。一般来说。除了保持class文件中描述的符号引用外,还会把翻译出来的直接引用也存储在运行时常量池中。                                                                                               运行时常量池相对于class文件中的常量池的另一个重要特征是具备了动态性,java语言并不要求常量一定只有编译期才能产生,也就是并非预置入Class文件中常量池的内容才能进入方法区的运行时常量池,运气期间也能将新的常量放进池中。一般用的多的就是String类的insert()方法。      此区域也会抛出OutOfMemoryError异常。
  • 直接内存       此内存并不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域。但是这部分也被频繁的使用,而且也可能导致OutOfMemoryError异常。NIO就是可以直接使用Native函数库直接分配堆为内存。虽然本机直接分配内存不使用java虚拟机的内存,但是既然是内存,那么它当然受制于本机的总内存。所以当内存不能动态扩展的时候,也会抛出异常。