一、三者联系
1、堆:解决数据的存储问题( 即 数据怎么放,放到哪 )。
2、栈:解决程序运行的问题( 即 程序如何执行,或者说如何处理数据 )。
3、方法区:辅助堆栈的一块永久区,解决堆栈信息的产生,是先决条件。
我们创建一个对象,User:那么 User类的一些信息 ( 类信息、静态信息 ) 都存在于方法区中,我们可以根据这些信息来创建对应的对象。方法区中相当于存放着创建对象的模板。
二、堆
1、根据垃圾回收机制不同, 堆有可能拥有不同的结构,最常见的就是将整个堆分为新生代和老年代。其中新生代存放新生的对象或者年龄不大的对象,老年代则存放老年对象。
2、新生代分为 eden(伊甸园) 区、s0 区、s1 区, s0 和 s1 也被成为 from 和 to 区域,他们是两个大小相等并且可以互换角色的空间内存。
3、绝大多数情况下,对象首先分配在 eden 区,在一次新生代回收后,如果对象还存活,则会进入 s0 或 s1,之后每经过一次新生代回收,如果对象还存活则它的年龄加1,当对象达到一定年龄后,则进入老年代
( 默认经过 15 次GC 后进入老年代 )。
4、s0 区和 s1 区之间采用的是复制算法
复制算法:其核心思想就是将内存空间分为两块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中存留的对象复制到未被使用的内存中去,之后去清除之前正在使用的内存块中所有的对象。反复交换两个内存的角色,完成垃圾回收。
三、栈
栈是一块私有的内存空间,一个栈,一般由三部分组成:局部变量表,操作数栈,和帧数区域。
1、局部变量表:用于报错函数的参数及局部变量
2、操作数栈:主要保存计算过程的中间结果,同时作为计算过程中变量临时的存储空间
3、帧数区域:出了局部变量表和操作数栈以外,栈还需要一些数据来支持常量池的解析,这里帧数区域保存着访问常量池的指针,方便程序访问常量池,另外,当函数返回或者出现异常时,虚拟机必须有一个异常处理表,方便
发送异常的时候找到异常的代码,因此异常处理表也是帧数区域的一部分。
四、方法区
java方法区和堆一样,方法区是一块所有线程共享的区域,他保存系统的类的信息,比如类的字段、方法、常量池等。方法区的大小决定了系统可以保存多少个类,如果系统定义太多的类,会导致方法区溢出。虚拟机同样会抛出
内存溢出的错误。方法区可以理解为永久区。