JVM(三)---堆、栈、方法区

在这里插入图片描述

上一篇:JVM(二)—双亲委派机制

堆(线程共享):

  虚拟机在启动的时候创建堆,用于存放对象的实例。几乎所有的对象(包含常量池)都在堆上分配内存。当对象无法在该区分配内存的时候,将会报OutOfMemoryError,是jvm中主要的GC区域。

堆区是jvm中进行垃圾回收的主要区域

GC垃圾回收机制

在这里插入图片描述
  对象实例从新生代永久代的过程就像是古代士兵打仗升级一样,那种用的不多,作用很小的对象经过不断的GC,不断地被淘汰,剩下来的升官进入老年代,最后再进入永久代

  新生代的对象相当于普通士兵,不断的上战场,不断被GC,当他升级当官了之后进入老年代可能就会指挥战斗,被GC的频率逐渐减小……

  到了永久区,就不存在GC了,绝大部分的对象在新生代就被回收了,进入老年代的对象都是极少。

  堆的内存大小并不是固定的,我们可以通过设置参数来控制堆内存的大小

  设置堆内存大小

栈(线程私有):

  java线程执行的内存模型,一个线程对应一个栈,每个方法在执行的时候都会创建出一个栈帧用于存储局部变量表,操作数栈。动态连接,方法出口等信息。

在这里插入图片描述
  栈是用来主管程序运行的,我们经常会听到说压栈、弹栈,在一个类中,如果有main()方法,首先会将main()方法压到栈中,然后再是其他的方法,如上图中的hello()list(),当list()方法执行完毕之后,该方法从栈里弹出去(弹栈),遵循先进后出原则。当main()方法执行完毕,程序结束。

  栈的生命周期与线程的生命周期同步,线程执行完毕,栈内存释放。

  由于栈中方法一执行结束就弹出栈,所以不存在垃圾回收

StackOverflowError(栈溢出)?

  整个简单的代码实现一下堆栈溢出:

public class TestController {

	public static void main(String[] args) {
		hello();
	}

	private static void hello() {
		list();
	}

	private static void list() {
		hello();
	}
}

在这里插入图片描述
  知道压栈弹栈之后,分析此错误产生的原因就是list()方法和hello()方法互相循环调用,导致栈溢出:
在这里插入图片描述

方法区(线程共享):

  类的所有字段和方法字节码,以及一些特殊构造方法,如构造函数,接口代码也在此定义,简单说,所有定义的方法信息都存放在该区域。静态变量(static)、常量(final)、类信息(class)、运行时常量池都是在方法区中。虽然java虚拟机规范将方法区描述为一个堆的逻辑部分,但是他却有一个别名(Non-heap(非堆)),目的应该是与java堆区分开来。
在这里插入图片描述

常量池存放在哪里?:

  JDK1.6之前,常量池位于JVM的方法区

  JDK1.7将常量池转移到了堆中

  JDK1.8之后,永久代被取缔,取而代之的是元空间,所以此时常量池在元空间。

下一篇:GC垃圾回收机制----GC回收算法(GC机制必会知识点)

发布了79 篇原创文章 · 获赞 42 · 访问量 7901

猜你喜欢

转载自blog.csdn.net/qq_43655835/article/details/103953733
今日推荐