美文网首页
JAVA内存区域与内存溢出异常

JAVA内存区域与内存溢出异常

作者: 一凡呀 | 来源:发表于2018-01-27 08:44 被阅读0次

    运行时数据区

    1.对于java程序猿来说,在虚拟机自动内存管理机制的帮助下,不需要对每一个new的操作去写配对的delete/free代码。
    2.JAVA虚拟机在执行java程序的过程中会把他所管理的内存划分为若干个不同的区域,包括程序计数器,虚拟机栈,本地方法栈,堆,方法区。


    image.png

    3.程序计数器:是一块较小的内存空间,可以看成是当前线程执行的字节码的行号指示器
    。在任何一个确定的时刻,一个处理去都只会执行一条线程中的指令,每个线程都想需要独立的程序技术去。程序计数器是唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。

    java虚拟机栈

    1.java虚拟机栈描述的是java方法执行的内存模型,,每个方法在执行的同时会创建一个栈帧,用于存储局部变量表,操作数栈,动态链接,方法接口等,每一个方法从调用至执行完成的过程,就对应着一个栈帧在虚拟机中从入栈到出栈的过程
    2.两种异常情况,如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError;如果虚拟机栈可以动态扩展,如果无法申请到足够的内存,就会抛出OutOfMemoryError

    本地方法栈

    1.和虚拟机栈类似,只不过虚拟机栈为虚拟机执行java方法服务(也就是字节码),而本地方法栈为虚拟机使用到的Native方法服务
    2.异常类型和虚拟机栈一样

    java堆

    1.Java堆是java虚拟机所管理的内存中最大的一块,是线程共享的。此内存区域的唯一目的就是存放对象实例,几乎所有对象实例都在这里分配。所有对象的示例以及数组都要在堆上分配。
    2.Java堆是辣鸡手机管理的主要区域,收集器基本采用分代收集法。从内存分配角度来看,线程共享的java堆中可以划分出多个线程私有的分配缓冲区
    3.java堆可以处在物理上不连续的内存空间,只要逻辑上连续就可以。
    4.如果在堆中没有内存完成分配,并且堆也无法再扩展了,会抛出OutOfMemoryError异常

    方法区

    1.方法区与java堆一样,也是线程共享的,用于存储虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等
    2.和java堆一样可以不需要连续的内存和可以选择固定大小或者可扩展外,还可以选择不是先垃圾收集,相对而言,垃圾收集在方法区比较少出现。这区域的内存回收目标主要针对常量池的回收和对类型的卸载
    3.内存分配需求满足表了时,会抛出OutOfMemoryError异常

    运行时常量池

    1.是方法区的一部分,class文件红除了有类的版本字段方法接口信息外,还有一项是常量池,用来存放编译期间生成的各种字面量和符号引用,类加载后,进入方法区的运行时常量池
    2.当常量池无法申请到内存时,会抛出OutOfMemoryError异常

    直接内存

    1.不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域。也可以导致OutOfMemoryError异常

    对象的创建(HotSpot虚拟机)

    1.虚拟机遇到一条new指令,首先将去检查这个指令的参数能否在常量池中定位到这个类的符号引用,并且检查这个符号引用代表的类是否已被加载,解析和初始化过,如果没有,则必须限制性相应的类加载过程
    2.类加载检查通过后,虚拟机将为新生对象分配内存,对象所需内存大小在类加载完成后便可以完全知道。为对象分配内存空间相当于把一块确定大小的内存从java堆中划分出来。
    3.假设java堆是绝对规整的,所有用过的内存都放在一遍,空闲的内存放在另一边,中间放着一个指针作为分界点的指示器,那么分配内存就是把指针向空闲空间挪动一段与对象大小想想等的距离,这种分配方法叫做指针碰撞
    4.如果不是规整的,已用和空闲的内存互相交错,需要维护一个表,记录那些内存块可用,分配内存时从表中找空闲内存,这种分配方法交空闲列表。选择哪种分配方法由java堆是否规整决定,而规整又是由所采用的来几首机器是否带有压缩整理功能决定。
    5.对象在虚拟机中创建是一个非常频繁的行为,在并发的情况下不是线程安全的,解决方法:一种是对分配控件的动作进行同步处理,另一种是吧内存分配的动作按照线程划分在不同的空间中,即每个线程在堆中预先分配一小块内存,称为本地线程分配缓冲。
    6.内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头),这一步操作保证了对象实例字段在java代码中不赋初始值就可以直接使用
    7.对象的内存布局可以划分为三个区域
    对象头:1.存储对象自身运行时数据 2.类型指针,对象指向它的类元数据的指针 如果对象是一个数组,对象头中还必须有一块用于保存对象长度的数据
    实例数据:对象真正存储的信息
    对齐填充:不是必然存在,起占位符作用

    对象的访问定位

    1.java程序通过栈上的reference数据来操作具体对象,对象访问方式有两种
    句柄:java堆会划分出一块内存作为句柄池,reference中存储的是对象的句柄地址,而句柄地址中包含了对象的实例数据与类型数据的地址信息,优点 存储稳定的句柄,对象被移动只需要改变句柄中实例数据指针,而reference不需要修改
    直接指针:reference中存储的直接就是对象的地址,优点速度快

    相关文章

      网友评论

          本文标题:JAVA内存区域与内存溢出异常

          本文链接:https://www.haomeiwen.com/subject/spagaxtx.html