美文网首页
Java内存分配与内存溢出

Java内存分配与内存溢出

作者: T_log | 来源:发表于2018-07-06 16:08 被阅读3次

    java 与C++之间有一堵内存分配和垃圾收集技术所围成的“高墙”,墙外面的人想进去,墙里面的人想出来。


    企业微信截图_259be09e-cb21-476d-b351-2c2c8144bc3e.png

    运行时数据区域

    1. 程序计数器 (Program Counter Register)是一块较小的内存区域,可以看成当前线程所执行的字节码的行号指示器。属于线程私有的内存区域。在虚拟机概念模型中,字节码解释器就是通过这个行号指示器的值,来选取下一条需要执行的字节码指令。
      由于Java虚拟机的多线程是通过线程轮流切换并分配处理器时间的方式实现的,所以在任何一个确定的时刻,一个cpu只会处理一条线程中的指令。那当恢复其他线程的运行时,就是通过这个程序计数器来恢复到上一次执行到的
      位置,因此,程序计数器是线程私有的,每个线程都对应着一个独立的程序计数器。
      在JVM执行Java程序时,程序计数器记录的是虚拟机字节码指令的地址。
    2. Java虚拟机栈(java Virtual Machine Stacks),和程序计数器一样,也属于线程私有的内存区域。生命周期和线程相同。虚拟机栈描述的是方法执行的内存模型;每个方法在执行的同时,会创建一个栈帧(Stacj Frame),用于存储
      局部变量表、操作数栈、动态链接、方法出口灯信息,每个方法从调用开始,到执行完成,都会伴随着一个栈帧在虚拟机栈中的入栈和出栈的执行过程。
      局部变量表: 存放了编译期可知的各种基本数据类型(boolean,byte,char,short,int,float,long,double)、对象引用类型referenct,局部变量表所需的内存空间在编译期间就已经完成分配,当进入一个方法时,这个方法需要在栈帧中分配多大的局部变量空间是完全确定的。方法运行期间不会改变布局变量表的大小。
      在Java虚拟机规范中,对Java虚拟机栈规定了两种异常情况
      如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常
      如果虚拟机栈可以动态扩展,如果扩展时,无法申请到足够的内存,将会抛出OutOfMemoryError异常
    1. 本地方法栈(Native Method Stack)与虚拟机所发挥的作用相似。区别在于,虚拟机栈为虚拟机执行Java方法(字节码)服务,而本地方法栈为虚拟机使用到的Native方法服务
    2. Java堆(Heap)是Java虚拟机管理的内存中最大的一块,Java堆是被所有线程共享的一块内存区域。随虚拟机的启动而创建,Java堆唯一的目的就是存放对象实例。几乎所有的对象实例都存放在Java堆中。在Java虚拟机规范中的描述是:
      所有的对象实例和数组都要在堆上分配内存。但是随着(JIT JUST IN TIME)的发展和逃逸分析技术的逐渐成熟,栈上分配,标量替换优化技术将会导致一些微妙的变化,所有的对象都分配在Java堆上,也并不是那么的绝对了。
      Java堆也是GC回收垃圾的主要内存区域。基于收集器的分代收集算法,Java堆可以分为新生代和老年代,新生代还可以分为:Eden空间、From Survior空间、To Survior空间,其实还有更细的划分方式,不管如何划分,都是为了更好的回收内存空间而已
      5.方法区(Method Area)与Java堆一样,都是线程共享的内存区域。主要用来存储被Java虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
      6.运行时常量池(Runtime Constant Pool),其实是方法区的一部分。Class文件中除了有类的版本信息、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译器生成的各种字面量和符号引用,这部分内容将会在类加载后进入方法区的运行时常量池中存放。运行时常量池除了保存Class文件中描述的符号引用外,还会把翻译出来的直接引用也存储在运行时常量池中。

    符号引用 :符号引用以一组符号来描述所引用的目标。符号引用可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可,符号引用和虚拟机的布局无关。个人理解为:在编译的时候一个每个java类都会被编译成一个class文件,但在编译的时候虚拟机并不知道所引用类的地址,多以就用符号引用来代替,而在这个解析阶段就是为了把这个符号引用转化成为真正的地址的阶段。
    直接引用可以是:
    1:直接指向目标的指针。(个人理解为:指向对象,类变量和类方法的指针)
    2:相对偏移量。 (指向实例的变量,方法的指针)
    3:一个间接定位到对象的句柄。

    1. 直接内存(Direct Memory)并非Java虚拟机规范中定义的内存区域

    参考
    周志明 《深入理解Java虚拟机》
    https://blog.csdn.net/qq_34402394/article/details/72793119
    https://blog.csdn.net/qq_22884121/article/details/52700806

    相关文章

      网友评论

          本文标题:Java内存分配与内存溢出

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