当前位置:   article > 正文

JVM堆和方法区底层结构及原理_jvm堆底层数据结构

jvm堆底层数据结构

 PC寄存器、虚拟机栈、本地方法栈详见博文: JVM运行时数据区结构及原理

目录

一、堆

 二、方法区


一个Java程序运行起来就是一个进程,一个进程就对应一个JVM实例,一个JVM实例中有一个运行时数据区(Runtime Data Area),一个运行时数据区对应一个堆和方法区,而一个进程又可以有多个线程,因此,堆和方法区是多个线程共享的,存在线程安全问题

一、堆

【概述】

Java堆区在JVM启动的时候即被创建,其空间大小也就被确定了,几乎所有的对象实例以及数组都在运行时分配到堆上,所以它是JVM管理的最大的一块、也是最重要的一块内存空间。在方法结束后,堆中的对象不回马上被移除,仅仅在垃圾收集的时候才被移除,是GC(Garbage Collection,垃圾收集器)执行垃圾回收的重点区域。一个JVM实例只存在一个堆内存,堆也是Java内存管理的核心区域。

而对象实例和数组可能永远不会存储在栈上,因为栈帧中保存的是引用,这个引用指向对象实例或者数组在堆中的位置。

 堆可以处于物理上不连续的内存空间,但在逻辑上它应该被视为连续的。

【堆的结构】

在JDK1.8版本废弃了永久代,替代的是元空间(MetaSpace),元空间与永久代上类似,都是方法区的实现,他们最大区别是:元空间并不在JVM中,而是使用本地内存。S0区和S1区在同一时间只能使用一个。

【堆空间大小的设置和查看】

默认情况下:

  • 初始内存大小:物理电脑内存大小 / 64
  • 最大内存大小:物理电脑内存大小 / 4  

-Xms:可设置堆的初始空间,等价于-XX:InitialHeapSize

-Xmx:可设置堆的最大空间,等价于-XX:MaxHeapSize

-XX:+PrintGCDetail:可查看堆空间中设置的参数

-Xmn:可设置年轻代的空间大小

【年轻代与老年代】

在HotSpot中,Eden(伊甸园)空间和另外两个Survivor空间缺省所占的比例是8:1:1,当然开发人员可以通过选项"-XX:SurvivorRatio"调整这个比例空间。 实际情况中,当我们查看内存分配是时发现并不是8:1:1,是因为系统为我们默认定义了自适应内存分配策略,我们可以通过"-XX:-UseAdaptiveSizePolicy"关闭自适应的内存分配策略。

几乎所有的Java对象都是在Eden区被new出来。而绝大部分的Java对象的销毁都是在新生代进行的。
 

 【图解对象分配的一般过程】

  

 3~5步骤相当于在S0区和S1区“来回倒腾”,且两者不能同时存有数据,同一时刻必有一个为空,当其中存在倒腾次数大于设置的阈值的对象时,就把该对象晋升为养老区。

 关于垃圾回收:频繁在新生区回收,很少在养老区回收,几乎不在永久区/元空间回收。

【对象分配的特殊情况】

在对象分配时会出现Eden区在Young GC后仍然放不下、以及S0、S1区倒腾时并未达到可晋升养老区的阈值时却放不下的情况,此时我们会将其直接放入养老区。若养老区放不下则进行对养老区Full GC(或Major GC)垃圾回收,如果还是放不下就报OOM错误。

【Minor GC、Major GC和Full GC】

 JVM在进行GC时,并非每次都对新生代、老年代、方法区一起回收,大部分时候回收的都是指新生代。针对HotSpot VM 的实现,它里面的GC按照回收区域又分为两大种类型:一种是部分收集(Partial GC),一种是整堆收集(Full GC)。

  • 部分收集(Partial GC):
    • 新生代收集(Minor GC / Young GC):只是新生代的垃圾收集。
    • 老年代收集(Major GC / Old GC):只是老年代的垃圾收集。
    • 混合收集(Mixed GC):收集整个新生代以及老年代的垃圾收集。
  • 整堆收集(Full GC):收集整个Java堆和方法区的垃圾收集。

注意:目前只有CMS GC会有单独收集老年代的行为,只有G1 GC会有混合收集的行为。
           很多时候,Major GC会和Full GC混淆使用,需要具体分辨是老年代回收还是整堆回收。

 

 

提问:我们为什么需要对Java堆分代?不分代就不能正常工作了吗?

答:其实不分代完全可以正常工作,分代的唯一理由就是优化GC性能。经研究。不同对象的生命周期不同,70% - 99% 的对象是临时对象。如果没有分代,那所有的对象都在一块,就如同把一个学校的人都关在一个教室,GC的时候要找到哪些对象没用,这样就会对堆的所有区域进行扫描,浪费时间。而很多对象都是朝生息死的,如果分代的话。把新创建的对象放到某一地方,当GC的时候先把这块存储“朝生息死”对象的区域进行回收,这样就会腾出很大的空间出来。

【为对象分配内存:TLAB】

在介绍TLAB之前,我们先谈一谈为什么要有TLAB?

        因为堆区是线程共享的,任何线程都可以访问到堆中的共享数据,由于对象实例的创建在JVM中非常频繁,因此在并发环境下从堆区中划分内存空间是线程不安全的。为避免多个线程操作同一地址,我们可以使用加锁等机制,但会影响分配的速度,此时TLAB就可以很好地解决这一问题。

什么是TLAB?

        TLAB(Thread Local Allocation Buffer),线程本地分配缓冲区。从内存模型而不是垃圾收集的角度,堆Eden区域继续进行划分,JVM为每个线程分配了一个私有缓存区域,它包含在Eden空间内。当多个线程同时分配内存时,使用TLAB可以避免一系列的非线程安全问题(多个线程同时对同一内存操作的现象),同时还能够提升内存分配的吞吐量,因此我们可以将这种内存分配方式成为快速分配策略

 

【小结及参数设置】

小结:

 堆空间常见参数设置:

java (oracle.com)官网查看地址(Ctrl F可搜索):java (oracle.com)

-XX:+PrintFlagsInitial:查看所有的参数的默认初始值

-XX:+PrintFlagsFinal:产看所有的参数的最终值(可能会存在修改,不再是初始值)

-Xms:初始堆空间内存(默认为物理内存的1/64)

-Xmx:最大堆空间内存(默认为物理内存的1/4)

-Xmn:设置新生代的大小(初始值及最大值)

-XX:NewRatio:配置新生代与老年代在堆结构的占比

-XX:SurvivorRatio:设置新生代中Eden和S0/S1空间的比例

-XX:MaxTenuringThreshold:设置新生代垃圾的最大年龄

-XX:+PrintGCDetails:输出详细的GC处理日志

-XX:HandlePromotionFailure:是否设置空间分配担保

在命令行中,具体查看某个参数的指令:
        jps:查看当前运行中的进程
        jinfo  -flag  SurvivorRatio  进程id

 【扩展】

提问:堆是分配对象存储的唯一选择吗?

        随着JIT编译器的发展与逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙的变化,所有的对象都分配到堆上也渐渐变得不那么“绝对”了。在Java虚拟机中,对象是在Java堆中分配内存的,这是一个普通的常识。但是,有一种特殊情况,那就是如果经过逃逸分析(Escape Analysis)后发现,一个对象并没有逃逸除方法的话,那么就可能被优化成栈上分配。这样就无需在堆上分配内存,也无需进行垃圾回收了。这也是最常见的堆外存储技术。

 参数-server:启动Server模式,因为只有在Server模式下,才可以启用逃逸分析。

【逃逸分析:代码优化】

 二、方法区

【概述】

《Java虚拟机规范》中说明:“尽管所有的方法区在逻辑上是属于堆的一部分,但一些简单的实现可能不会选择去进行垃圾收集或者进行压缩”。但对于HotSpot JVM而言,方法区还有一个别名叫做Non-Heap(非堆),目的就是要和堆分开。所以,方法区可以看作是独立于Java堆的内存空间

 

【栈、堆、方法区关系】

 【设置方法区大小与OOM】

 

 

【方法区的内部结构】

 方法区主要用于存储已被虚拟机加载的类型信息,常量、静态变量、即时编译器编译后的代码缓存等。

 【运行时常量池】

 一个Java源文件的类、接口,编译后产生一个字节码文件。而Java中的字节码需要数据支持,通常这种数据会很大以至于不能直接存到字节码里,换另一种方式,可以存到常量池,这个字节码包含了指向常量池的引用。在动态链接的时候会用到运行时常量池。

我们可以把常量池看作是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等类型。

 

 【方法区的演进】

 

 

 注意:new出来的对象实例都是存放在堆中的,而JDK6及之前的静态变量存放在方法区指的是指向对象的引用。即,只要是创建的对象实体都放在堆中,变化的是实体对应的变量存放位置不同。

【方法区的垃圾回收】

一般来说这个区域的回收比较难令人满意,尤其是类型的卸载,条件相当苛刻。但是这部分区域的回收有时又确实是必要的。

方法区的垃圾收集主要回收两部分内容:常量池中废弃的常量不再使用的类型。 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/352966
推荐阅读
相关标签
  

闽ICP备14008679号