栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JVM的组成(JDK8+HotSpot)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JVM的组成(JDK8+HotSpot)

一、概述

JVM 整体组成可分为以下四个部分:

运行时数据区为最主要部分

  1. 类加载器(ClassLoader)
  2. 运行时数据区(Runtime Data Area)
  3. 执行引擎(Execution Engine)
  4. 本地库接口(Native Interface)
二、类加载器 三、运行时数据区(Runtime Data Area,重点) 一.方法区(Method Area,线程共享,元空间)

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

方法去与Java堆一样,是各个线程共享的内存区域

方法区的大小和堆一样,可以选择固定的大小或者扩展

方法去的大小决定了系统可以保存多少各类,如果系统定义了太多的类,会导致方法去内存溢出。

查看JVM启动参数的值

java -XX:+PrintFlagsInitial 该命令可以查看所有JVM参数启动的初始值

可以通过以下的几个参数对metaspace进行控制:

-XX:metaspaceSize=N #这个参数是初始化的metaspace大小,该值越大触发metaspace GC的时机就越晚,默认值大概是20M。

-XX:MaxmetaspaceSize=N # 限制metaspace增长的上限,防止因为某些情况导致metaspace无限的使用本地内存,影响到其他程序,默认值大概是4个G。

-XX:MinmetaspaceFreeRatio=N #当进行过metaspace GC之后,会计算当前metaspace的空闲空间比,如果空闲比小于这个参数,那么虚拟机将增长metaspace的大小,默认值为40。

-XX:MaxmetasaceFreeRatio=N #当进行过metaspace GC之后, 会计算当前metaspace的空闲空间比,如果空闲比大于这个参数,那么虚拟机会释放metaspace的部分空间,默认值为70。

-XX:MaxmetaspaceExpansion=N # metaspace增长时的最大幅度,默认值为5452592B(大约为5MB)。

-XX:MinmetaspaceExpansion=N #metaspace增长时的最小幅度,默认值为340784B(大约330KB为)。
1、类型信息 2、域信息 3、方法信息 4、 二.堆空间(Java Heap,线程共享)

Java 堆是内存空间占据的最大一块区域了,Java 堆是用来存放对象实例及数组,也就是说我们代码中通过 new 关键字 new 出来的对象都存放在这里。所以这里也就成为了垃圾回收器的主要活动营地了,于是它就有了一个别名叫做 GC 堆,并且单个 JVM 进程有且仅有一个 Java 堆。
PS:根据Java虚拟机的发展,JIT编译器的发展和逃逸分析技术的逐渐成熟,现在存在着new出来的对象不存在于堆中的可能性。比如创建在方法内的对象,未在方法外调用,会被优化为创建在虚拟机栈中,而不是堆中

1、堆的结构

JVM 提供了参数 -Xmn 来设置年轻代内存的大小,但没有提供参数设置老年代的大小。但其实老年代的大小就等于堆大小减去年轻代大小。

-Xmn :设置年轻代堆的大小
2、年轻代(新生代) 1.Eden空间 2.From空间(survivor0) 3.To空间(survivor1) 3、老年代 4、堆空间中的GC过程

  1. 绝大多数的新New出来的对象都放在了Eden区域(伊甸园,新生地)
  2. Eden区域快满的时候进行一次清理(Minor GC,轻量级垃圾回收),不被引用的对象直接被清理掉,还在引用但是年龄较大的,挪到S0区域。
  3. Eden第二次快满的时候,清理操作,清除掉Eden中的未被引用的对象和S0中未被引用的对象,并将这些对象都挪到S1区域。(保证S0或者S1必然有一个为空,用来存储下一次接收的对象)
  4. Eden和S(0或者1)区域都快满的时候,会将新生代(Eden区域+S区域)挪到老年代的区域,
  5. 循环执行,直到老年代(Old)区域及新生代区域都快满的时候,会对内存区域进行一次大清洗(FullGC),为之后对象的创建,腾地方。

清理Eden区和Survivor区叫Minor GC;清理Old区叫Major GC;清理整个堆空间—包括年轻代和老年代叫Full GC。

内存不是越大越好,盲目增大堆内存可能会让吞吐量不增反减,堆内存大了,每次gc扫描对象也就越多也越需要花费时间,反而会适得其反。合理设置堆内存大小,根据实际业务调整,不宜过大,也不宜过小。

三.栈空间(Java Virtual Machine Stacks Area,线程隔离)

栈是运行时的单位,队是存储的单位。
栈解决程序的运行问题,即程序如何执行,或者说如何处理数据,堆解决的是数据存储问题,即数据在哪里放,怎么放。

1、Java虚拟机栈是什么?

Java虚拟机栈早期称之为Java栈,每个线程在创建的时候,都会创建一个虚拟机栈,其内部保存着一个个的栈帧,对应着每一次的Java方法调用。

2、虚拟机栈的生命周期

生命周期与线程一致

3、栈的结构

1.局部变量表(Local Variable Table)

局部变量表(Local Variables)是一组变量值的存储空间,用于存放方法参数和方法内部定义的局部变量。在Java程序被编译为Class文件时,就在方法的Code属性的max_locals数据项中确定了方法所需的分配的局部变量表的最大容量。

2.操作数栈(Operand Stack)

操作数栈(Operand Stack)也常被成为操作栈,是一个后入先出栈,用于保存计算过程中的中间结果,同时作为计算过程中变量临时的存储空间。其最大深度在编译时就被写到了Code属性的max_stacks中。

3.动态链接(Dynamic linking) 4.返回地址(Return Address) 5.栈帧数据(Stack Data) 3、作用

主管Java程序的运行,保存方法的局部变量,部分结果,并参与方法的调用和返回。

4、特点 5、虚拟机栈大小的调整 四.PC寄存器(程序计数器,Program Counter Register,线程隔离)

程序计数器是一块很小的内存空间,主要用来记录各个线程执行的字节码的地址,例如,分支、循环、跳转、异常、线程恢复等都依赖于计数器。由于 Java 是多线程语言,当执行的线程数量超过 CPU 核数时,线程之间会根据时间片轮询争夺 CPU 资源。如果一个线程的时间片用完了,或者是其它原因导致这个线程的 CPU 资源被提前抢夺,那么这个退出的线程就需要单独的一个程序计数器,来记录下一条运行的指令。

  • PC寄存器是Java虚拟机中唯一的没有内存溢出的区域。
  • PC寄存器是一块很小的内存空间,大小几乎可以忽略不计
  • PC寄存器的线程是私有的,每个线程都有自己的PC寄存器,其生命周期同线程的生命周期完全一致
  • 在执行Native方法(调用C语言方法)的时候,PC寄存器为未指定值(undefned)
1、案例


红圈内称之为指令地址(偏移地址),由PC寄存器进行记录,指的是该线程下一步的操作是什么。

2、PC寄存器常见问题:为什么需要PC寄存器?

CPU处理着多个线程,在不同的线程之间来回切换,切换之后就需要知道接下来从哪里继续执行,PC寄存器中的数据就是告诉CPU下一个指令执行的是哪个。

五.本地方法栈(Native Method Stack,线程隔离) 四、执行引擎(Execution Engine) 五、本地库接口
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/435072.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号