Java中的堆、栈、方法区、运行时常量池的简单介绍

在上次咱们简单介绍了Java的反射机制,在学习Java的反射的时候,咱们有一张Java内存的模型图,以下:java

如今咱们来简单讲讲这个内存模型图中的堆、栈、方法区吧!程序员

        栈(stack)与堆(heap)都是Java用来在RAM中存放数据的地方。与C++不一样,Java自动管理栈和堆,程序员不能直接地设置栈或堆。 数组

Java栈:函数

      每一条 Java 虚拟机线程都有本身私有的 Java 虚拟机栈(Java Virtual Machine Stack),这个栈与线程同时建立,用于存储栈帧。Java 虚拟机栈的做用与传统语 言(例如 C 语言)中的栈很是相似,就是用于存储局部变量与一些过程结果的地方。另外,它在 方法调用和返回中也扮演了很重要的角色。由于除了栈帧的出栈和入栈以外,Java 虚拟机栈不会再受其余因素的影响,因此栈帧能够在堆中分配,Java 虚拟机栈所使用的内存不须要保证是连续的。学习

      在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的做用域后,java会自动释放掉为该变量分配的内存空间,该内存空间能够马上被另做他用。线程

Java堆:对象

        在Java虚拟机中,堆(Heap)是可供各条线程共享的运行时内存区域,也是供全部类实例和数组对象分配内存的区域。Java 堆在虚拟机启动的时候就被建立,它里面存储了被自动内存管理系统(即咱们常说的垃圾回收器)所管理的各类对象。Java 堆的容量能够是固定大小的,也能够随着程序执行的需求动态扩展,并在不须要过多空间时自动收缩。Java 堆所使用的内存不须要保证是连续的。接口

方法区:内存

        在Java虚拟机中,方法区(Method Area)是可供各条线程共享的运行时内存区域。它存储了每个类的结构信息,例如运行时常量池、字段和方法数据、构造函数和普通方法的字节码内容、还包括一些在类、实例、接口初始化时用到的特殊方法。方法区的容量能够是固定大小的,也能够随着程序执行的需求动态扩展,并在不须要过多空间时自动收缩。方法区在实际内存空间中能够是不连续的。作用域

运行时常量池:

       运行时常量池(Runtime Constant Pool)是每个类或接口的常量池的运行时表示形式,它包括了若干种不一样的常量:从编译期可知的数值字面量到必须运行解析后才能得到的方法或字段引用。运行时常量池扮演了相似传统语言中符号表的角色,不过它存储数据范围比一般意义上的符号表要更为普遍。每个运行时常量池都分配在 Java 虚拟机的方法区之中,在类和接口被加载到虚拟机后,对应的运行时常量池就被建立出来。

        从堆和栈的功能和做用来通俗的比较,堆主要用来存放对象的,栈主要是用来执行程序的。堆内存用来存放由new建立的对象和数组,在堆中分配的内存,由JVM的自动垃圾回收器来管理。而栈的优点是,存取速度比堆要快,仅次于寄存器。栈数据能够共享。但缺点是,存在栈中的数据大小与生存期必须是肯定的,缺少灵活性。栈中主要存放一些基本类型的变量(,int, short, long, byte, float, double, boolean, char)和对象句柄。 

异常状况:

    若是线程请求分配的栈容量超过 Java 虚拟机栈容许的最大容量时,Java 虚拟机将会抛出一 个 StackOverflowError 异常。    

    若是 Java 虚拟机栈能够动态扩展,而且扩展的动做已经尝试过,可是目前没法申请到足够的内存去完成扩展,或者在创建新的线程时没有足够的内存去建立对应的虚拟机栈,那Java 虚拟机将会抛出一个 OutOfMemoryError 异常。

    若是实际所需的堆超过了自动内存管理系统能提供的最大容量,那Java 虚拟机将会抛出一个 OutOfMemoryError 异常。

    若是方法区的内存空间不能知足内存分配请求,那 Java 虚拟机将抛出一个OutOfMemoryError 异常。

    当建立类或接口的时候,若是构造运行时常量池所须要的内存空间超过了方法区所能提供的最大值,那 Java 虚拟机将会抛出一个OutOfMemoryError 异常。

        最后,我感受知识越学越深,理解一个概念的同时,要知道好几个概念才能明白这个概念。也许这就是驱动本身学习的一个方法吧!

相关文章
相关标签/搜索