Java中的内存划分

Java程序在运行时,需要在内存中分配空间。为了提高效率,就对数据进行了不同空间的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
      程序计数器:保证线程切换后能恢复到原来的执行位置
      虚拟机栈:(栈内存)为虚拟机执行java方法服务:方法被调用时创建栈帧->局部变量表->局部变量、对象引用
      本地方法栈:为虚拟机执行使用到的native方法服务
      堆内存:存放所有new出来的东西
      方法区:存储被虚拟机加载的类信息、常量、静态常量、静态方法等。

GC对它们的回收:
    内存取余中的程序计数器、虚拟机栈、本地方法栈这3个取余随着线程而生,线程而灭;栈中的栈帧随着方法的进入和退出而有条不紊地执行者出栈和入栈的操作,每个栈帧中分配多少内存基本是在类结构确定下来时就一直的。在这几个区域不需要过多考虑回收的问题,因为方法结束或者线程结束时,内存自然跟着回收了。

GC回收的主要对象:
   1.程序计数器(线程私有)
     每个线程拥有一个程序计数器,在线程创建时创建,指向下一条指令的地址,执行本地方法时,其值为undefined
为了线程切换后能够恢复到正确的执行位置,每条线程都有一个独立的程序计数器。
   2.java虚拟机栈(线程私有)
     每个方法被调用时都会创建一个栈帧,用于存储局部变量表、操作站、动态链接、方法出口等信息。局部变量表存放的是:编译器克制的基本数据类型、对象引用类型。
    每个方法被调用到执行完成的过程,就对应着一个栈帧在虚拟机中从入栈到出栈的过程。
     在Java虚拟机规范中,对这个区域规定了两种异常情况:
    (1)如果线程请求的栈深度太深,超出了虚拟机所允许的深度,就会出现stackOverFlowError(比如无限递归。因为每一层栈帧都占用一定空间,而Xss规定了栈的最大空间,超出这个值就会报错)
    (2)虚拟机栈可以动态扩展,如果扩展到无法申请足够的内存空间,会出现OOM
   3.本地方法栈
     (1)本地方法栈与java虚拟机栈作用非常相似,奇缺别是:java虚拟机栈是为虚拟机执行java方法服务的,而本地方法栈则为虚拟机使用到的Native方法服务
   4.java堆:即堆内存(线程共享)
     (1)堆是java虚拟机所管理的内存区域中的最大的一块,java堆是被所有线程共享的内存区域,在java虚拟机启动时创建,堆内存的唯一目的就是存放对象实例几乎所有的对象实例都在堆内存分配。
     (2)堆是GC管理的主要区域 从垃圾回收的角度, 由于现在的垃圾收集器都是采用的 分代收集 算法,因此java堆还可以初步细分为 新生代和老年代 。 
    (3)Java虚拟机规定,堆可以处于物理上不连续的内存空间中,只要逻辑上连续的即可。在实现上既可以是固定的,也可以是可动态扩展的。如果在堆内存没有完成实例分配,并且堆大小也无法扩展,就会抛出OutOfMemoryError异常。

     5、方法区:(线程共享) 
    (1)用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。 
     (2)Sun HotSpot虚拟机把方法区叫做永久代(Permanent Generation),方法区中最终要的部分是运行时常量池。

    6、运行时常量池: 
(1)运行时常量池是方法区的一部分,自然受到方法区内存的限制,当常量池无法再申请到内存时就会抛出OutOfMemoryError异常。

你可能感兴趣的:(JVM)