在java中,有java程序、虚拟机、操作系统三个层次,其中java程序与虚拟机交互,而虚拟机与操作系统间交互。先看下Java运行中内存从获取到分配的大致流程,分为3步。
程序运行前:JVM向操作系统请求一定的内存空间,称为初始内存空间!程序执行过程中所需的内存都是由java虚拟机从这片内存空间中划分的。
程序运行中:java程序一直向java虚拟机申请内存,当程序所需要的内存空间超出初始内存空间时,java虚拟机会再次向操作系统申请更多的内存供程序使用。
内存溢出:程序接着运行,当java虚拟机已申请的内存达到了规定的最大内存空间,但程序还需要更多的内存,这时会出现内存溢出的错误。
Java 程序所使用的内存是由 Java 虚拟机进行管理、分配的。Java 虚拟机规定了 Java 程序的初始内存空间和最大内存空间,开发者只需要关心 Java 虚拟机是如何管理内存空间的,而不用关心某一种操作系统是如何管理内存的。
----------------------------------------------------------------------------------以上摘自JAVA内存管理 -----------------------------------------------------------------------------------------------------
JVM将申请到的内存分为三个部分,分别是栈(stack)、堆(heap)和方法区(method aera)。
stack存取速度最快,仅次于位于CPU中的寄存器(近水楼台自然更快),它的存取过程遵循LIFO(后进先出)原则,负责存储代码中基本类型变量和引用类型变量。当在一段代码块定义一个变量时,Java 就在stack中为这个变量分配内存空间,当超过变量的作用域后,Java 会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作他用。正因为如此,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。
heap个线程共享,存取速度次于stack,其存储空间可以通过new进行分配,所以使用new产生的对象类型变量是存储在heap中的。即使代码运行超出了new所在的代码块,heap中的对象类型变量空间也不会被立即被释放,只有在没有引用类型变量指向对象类型变量时,改对象才会变成“垃圾”,在之后的某个不确定的时间上被JVM的垃圾回收器清理,并释放其所占用的存储空间。
method aera是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息,保存类的结构(属性和方法)、常量、静态变量、即时编译器编译后的代码等数据。常量池位于该区。