栈JVM Stack 和 堆Java Heap的简介

90 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

编译器可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(引用指针,并非对象本身),

栈是java 方法执行的内存模型:

  每个方法被执行的时候 都会创建一个“栈帧”用于存储局部变量表(包括参数)、操作栈、方法出口等信息。每个方法被调用到执行完的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。栈的生命期是跟随线程的生命期,线程创建时创建,线程结束栈内存也就释放,是线程私有的。所有的对象实例以及数组都要在堆上分配,此内存区域的唯一目的就是存放对象实例

堆是Java 虚拟机所管理的内存中最大的一块。Java 堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。

堆是理解Java GC机制最重要的区域,没有之一

  结构:新生代(Eden区+2个Survivor区)  老年代   永久代(HotSpot有)

  新生代:新创建的对象——>Eden区

  GC之后,存活的对象由Eden区 Survivor区0进入Survivor区1  

  再次GC,存活的对象由Eden区 Survivor区1进入Survivor区0

  老年代:对象如果在新生代存活了足够长的时间而没有被清理掉(即在几次Young GC后存活了下来),则会被复制到老年代

  如果新创建对象比较大(比如长字符串或大数组),新生代空间不足,则大对象会直接分配到老年代上(大对象可能触发提前GC,应少用,更应避免使用短命的大对象)

  老年代的空间一般比新生代大,能存放更多的对象,在老年代上发生的GC次数也比年轻代少

永久代:可以简单理解为方法区(本质上两者并不等价)

Jdk1.6及之前:常量池分配在永久代

Jdk1.7:有,但已经逐步“去永久代”

Jdk1.8及之后:没有永久代(java.lang.OutOfMemoryError: PermGen space,这种错误将不会出现在JDK1.8中)