Java虚拟机:JVM 主要组成部分与内存区域

2023-05-16

一、JVM 主要组成部分:

        JVM的主要包含两个组件和两个子系统,分别为:

  • (1)Native Interface(本地库接口):与native lib(本地方法库)交互,融合其他编程语言为Java所用,是与其它编程语言交互的接口
  • (2)Runtime data area(运行时数据区):即常说的JVM内存
  • (3)Class loader(类加载子系统):根据全限定类名装载class文件到运行时数据区的方法区中
  • (4)Execution engine(执行引擎子系统):也叫解释器,负责解释class指令,再提交给操作系统执行

        通过上面的图,我们可以大致知道Java代码是如何运行的:首先通过编译器将Java源代码转换成字节码,接着类加载系统把字节码加载到运行时数据区的方法区内,再使用执行引擎将字节码翻译成底层系统指令,最后交由 CPU 去执行,而这个过程中可能需要调用其他语言的本地库接口来实现整个程序的功能。

字节码只是 一套 JVM 指令集规范,并不能直接交给底层操作系统去执行,因此需要通过执行引擎将字节码翻译成底层系统指令

二、JVM 内存:

        JVM 在执行 Java 程序时,会将内存划分为若干个不同的数据区域,不同的区域用途不同,创建和销毁时间也不相同。但在 JDK1.8 版本之后对运行时数据区域做了些修改,下面我们分别来看看修改前后的内存区域是怎么样的。

1、JDK1.8之前的JVM内存区域:

2、JDK8之后的JVM内存区域

3、各区域的的作用:

(1)程序计数器:

        当前线程执行的字节码的行号指示器,记录当前线程执行到程序的哪个位置,通过改变计数器的值,可以选取下一条需要执行的字节码指令。该区域是线程私有,且是唯一一个不会发生OOM的区域。

(2)虚拟机栈:

        描述 Java 方法执行的内存模型,方法执行时都会创建一个栈帧,每个方法从调用到执行完成,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。用于存储局部变量表、操作数栈、动态链接、方法出口等信息。该区域线程私有,生命周期与线程的生命周期相同。

(3)本地方法栈:

        本地方法栈和虚拟机栈的作用相似,区别是本地方法栈为Native方法服务,而虚拟机栈为Java方法服务,该区域也是线程私有。

(4)Java堆:

        用于存储对象实例,是占用内存最大的区域,可划分为新生代和老年代,新生代又可细分为 Eden区、From Survivor区、To Survivor区。

在 HotSpot 中,对象在堆内存布局分成三部分:对象头,实例数据,对齐填充。

① 对象头:包括两部分的信息:

  • 运行时数据:存储对象自身的运行数据,如哈希码,GC代年龄,锁状态、线程持有的锁、偏向线程ID等。
  • 类型指针:即对象指向它的类型数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。如果对象是一个Java数组,那对象头中还必须有一块用于记录数组长度的数据。

② 实例数据:是对象真正存储的有效信息,是在程序代码中所定义的各种类型的字段内容,相同宽度的字段会被分配到一起。

③ 对齐填充:并不是必然存在的,仅起着占位符的作用。

(5)方法区:

        该区域被所有线程共享,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码(即class文件)等数据,同时,方法区中有一个运行时常量池,用于存放静态编译产生的字面量和符号引用。该区域不需要连续的内存,并且可以动态扩展,动态扩展失败会抛出 OOM 异常,对该区域进行垃圾回收的主要目标是对常量池的回收和对类型的卸载,但是一般比较难实现。

        方法区是一个 JVM 规范,永久代与元空间都是其一种实现方式。JDK8 之前,Hotspot 中方法区的实现是永久代(Perm),JDK8 开始使用元空间(Metaspace),以前永久代的静态变量和常量池移至堆内存,其他内容移至元空间,元空间直接在本地内存分配。

        那为什么要使用元空间取代永久代的实现?主要是为了方便管理方法区:

① 永久代与堆所使用的物理内存是连续的。对于永久代,由于类和方法等信息比较难确定大小,所以指定永久代的大小比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出,并且每次 Full GC 之后永久代的大小都会改变,如果动态生成很多 class 的话,就很可能出现 OOM,毕竟永久代的空间配置有限。

② JDK8之后,方法区存在于元空间,物理内存不再与堆内存连续,而是直接存在于本地内存中,理论上机器内存有多大,元空间就有多大。

③ 字符串存在永久代中,容易出现性能问题和内存溢出。

④ 永久代会为 GC 带来不必要的复杂度,回收效率偏低,因为方法区中类静态属性引用的对象、常量引用的对象都是 GC Roots 对象


参考文章:https://www.cnblogs.com/czwbig/p/11127124.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java虚拟机:JVM 主要组成部分与内存区域 的相关文章

  • Java的JConsole可以用来自动配置内存吗?

    我正在学习JavaJMX https docs oracle com javase tutorial jmx and JConsole http docs oracle com javase 7 docs technotes guides
  • 如何从 ArrayList 中删除空白项。不删除索引

    public class ArrayListTest public static void main String args ArrayList al new ArrayList al add al add name al add al a
  • Java 中的递归回溯解决填字游戏

    我需要在给定初始网格和单词的情况下解决填字游戏 单词可以多次使用或根本不使用 初始网格如下所示 这是一个单词列表示例 pain nice pal id 任务是填充占位符 水平或垂直长度 gt 1 像那样 p pain pal id i c
  • Spring MVC 配置启用

    我正在从头开始建立一个项目 目前我正在配置Spring MVC 4 1 5使用java配置 整个应用程序正在 tomcat gradle 插件上运行 有人可以解释一下为什么我需要对班级进行以下调用DefaultServletHandlerC
  • java中数字字符串间隔排序

    我正在与一些人一起上一个人课 其中有姓名 年龄范围等详细信息 年龄区间为 0 5 6 10 11 30 31 45 46 50 50 100 100 110 我正在上 Person 课name ageBand字符串间隔及其参数化构造函数 g
  • 包java.time不存在,jdk1.8

    嗯 我刚刚开始从事代号工作 我对 Java 有相当不错的经验 我的代码一切都很好 没有任何问题 但在编译时我得到了这个 error package java time does not exit import java time Local
  • 将分区扩展到另一级

    根据下图来自春季批量文档 http docs spring io spring batch reference html scalability html partitioning 主步骤被划分为六个从步骤 它们是主步骤的相同副本 我的问题
  • 实现一个java UDF并从pyspark调用它

    我需要创建一个在 pyspark python 中使用的 UDF 它使用 java 对象进行内部计算 如果它是一个简单的 python 我会做类似的事情 def f x return 7 fudf pyspark sql functions
  • 如何抑制有关已弃用 api 的 javac 警告?

    当我编译时 javac 输出 Note Some input files use or override a deprecated API Note Recompile with Xlint deprecation for details
  • 尽管设置为 1.7,IntelliJ IDEA 13 仍使用 Java 1.5

    尽管在所有项目设置中指定了 JDK 1 7 包括File gt Project Structure gt Project Project SDK 则产生以下错误IntelliJ 13当尝试编译一些使用菱形运算符的简单 Java 7 代码时
  • 什么时候使用弱引用? [复制]

    这个问题在这里已经有答案了 我了解什么是 Java WeakReference 我想知道的是它通常用于解决哪种具体问题 有没有包含它们的模式 WeakReference and SoftReference当您想保留某些东西以备再次需要时使用
  • 有人使用 Hibernate 使用 Elasticache 作为二级缓存吗?

    我发现一些线程说这是可行的 但没有找到具体的说明或配置信息 我也想从 Beanstalk 执行此操作 应用程序应该部署到 beanstalk 并使用将 hibernate 指向 elasticache 实例的配置 是的 我们能够使用二级缓存
  • JPA Criteria API 任意数量的联接/子查询

    我需要使用以下实体构建相交类型查询 为了清楚起见 减少了实体 Entity and other stuff public class Member Id private Long id private String name Entity
  • Java如何处理IF语句和效率

    我只是好奇 Java 实际是如何工作的if声明 注意 当我在下面说 组件 时 我指的是语句检查的各个部分 例如a b c 哪个在计算方面更有效 if a b c do stuff or if a if b if c do stuff 我之所
  • 如何将 HTML 转换为保留换行符的文本

    我如何将 HTML 转换为保留换行符的文本 由 br p div 等元素生成 可能使用NekoHTML http nekohtml sourceforge net 或任何足够好的 HTML 解析器 Example Hello br Worl
  • 如何反序列化数组 google-gson 内的数组

    我有这样的 JSON Answers Locale Ru Name Name1 Locale En Name Name2 Locale Ru Name Name3 Locale En Name Name4 正如你所看到的 我的数组里面有数组
  • FileNotFoundException(系统找不到指定的路径)

    我得到这个例外 java io FileNotFoundException C filename xml The system cannot find the path specified 使用此代码 FileWriter fileWrit
  • GWT 和身份验证

    保护 GWT Tomcat 应用程序执行身份验证和授权的最佳策略是什么 有两种基本策略 确保入口点安全 确保远程服务的安全 确保入口点安全 最简单的方法是使用常规 Web 应用程序安全工具限制对 GWT 生成的 html js 文件的访问
  • 使用java读取行并映射过滤数据[关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions publi
  • 像 Java 一样覆盖 Objective-C 类中的方法

    我经常使用此语句来扩展类 而不需要编写整个单独的文件 假设 ClassFromFramework 是库中包含的框架的一部分的类 public ClassFromFramework public String myMethod operati

随机推荐