方法区、堆和栈

方法区

方法区是各个线程共享的内存区域,用于存储被虚拟机加载的类信息,常量,静态常量,即时编译器编译后的代码,运行时常量池。在HotSpot上也被称为“永久代”。

这一区域主要的知识点是类加载的过程,这一过程分为五个阶段,分别是加载,验证,准备,解析,初始化。

方法区

  1. 方法区是被所有线程共享的,所有字段和方法字节码以及一些特殊方法,如构造函数、接口代码也在此定义。所有定义的方法信息都保存在该区域,此区域属于共享区间。
  2. 静态变量(static)、常量(final)、类信息(class)以及运行时的常量池存在于方法区,但实例变量存在于堆内存中。

native

  1. native method本地方法:凡是带了native关键字,说明Java的作用范围达不到了。回去调用底层C语言的库
  2. 会进入本地方法栈
  3. 调用本地方法本地接口 JNI

堆区

1、一个JVM只有一个堆,堆内存的大小可以调节

2、堆中放的是什么?

  • 方法
  • 常量
  • 变量
  • 引用类型的真实对象

3、堆内存中细分三个区域:

  1. 新生区(伊甸园区)——分为两部分

    • 伊甸园区(满了会进行一次轻GC清理空间)
    • 幸存者区(0,1)
  2. 养老区、

    • 新生区幸存后会进入养老区,如果在新生区没有幸存,肯定进不了养老区
  3. 永久区(元空间)——jdk8后改名为元空间

4、GC垃圾回收主要在伊甸园区和养老区

  • 轻量级(GC)
  • 重量级(Full GC)

5、OOM

  1. 堆内存满了,产生错误 java.lang.OutOfMemoryErrpr:Java heap space
  2. 由于99%的对象都是临时对象,所以OOM错误发生的机率非常低当堆内存满了会进行垃圾回收等操作,

6、所有引用类型的真实对象保存在堆中,此外常量池的地址也保存在堆中
7、堆满了:OutOfMemoryError。原因是“养老区已满”,堆空间溢出

如果老年代满了,会报OOM错误。堆内存即溢出,具体的例子有当加载大量第三方jar包时、tomcat部署了太多应用时,动态生成的反射类太多时

永久区

永久区即元空间,元空间里包含方法区常量池又在方法区中。元空间用来存放JDK自身携带的Class对象,也就是JDK运行所必要的对象信息。存储的是Java运行时的一些环节或类信息,元空间不存在垃圾回收,关闭JVM就会释放这个区域的内存.

元空间和堆的关系:逻辑上元空间属于堆,但实现上堆中并不包括元空间。

永久区名称演变

jdk1.6之前:永久区如图所示,常量池在方法区中

jdk1.7:永久区退化了,常量池直接扔到堆中

jdk1.8:永久区改名为元空间,常量池在其中

永久区和元空间最大的区别是:永久区位于JVM的内存中,而元空间(即jdk1.8后)位于物理机的内存中

栈是一种数据结构,具有先进先出的特点。栈内存主管程序的运行,生命周期和线程同步。栈管运行,堆管存储线程结束,栈内存也就释放,因此栈不存在垃圾回收问题

8大基本类型+对象引用变量+实例方法运行在栈中

栈满了:StackOverFlowError。原因是栈内存空间不断的添加栈帧,导致栈内存被撑爆

# JavaJVM拓展

评论

暂无

添加新评论