JVM基础(2)——JVM内存模型

一、简介

JVM会加载类到内存中,所以 JVM 中必然会有一块内存区域来存放我们写的那些类。Java中有类对象、普通对象、本地变量、方法信息等等各种对象信息,所以JVM会对内存区域进行划分:

JDK1.8及以后,上图中的方法区变成了Metaspace——元数据区。

我们本章的目的,就是介绍JVM中各块内存区域的功能,其中都是存放的哪些java对象信息。

二、方法区

方法区只存在于JDK1.8以前的版本,主要是存储从”.class“文件里加载进来的类,包括 类的名称 、 方法信息 、 字段信息 、 静态变量 、 常量 以及 编译器编译后的代码 等。从JDK1.8开始,这块区域的名字改成了元数据区(Metaspace),元数据区直接使用本地内存。

默认情况下,元数据区会根据使用情况动态调整,避免了在JDK1.8以前由于加载类过多从而出现 java.lang.OutOfMemoryError: PermGen。但也不能无限扩展,因此可以使用 -XX:MaxMetaspaceSize来控制最大内存。

以上一章的示例来看,Kafka.class和ReplicaManager.class加载到JVM后,会放到方法区中:

    public class Kafka {
        public static void main(String[] args) {
            ReplicaManager manager = new ReplicaManager();
        }
    }

方法区/元数据区是所有线程共享的:

三、程序计数器

程序计数器,用来记录当前线程正在执行的字节码指令。我们还是继续以上一章的代码作为示例来讲解:

    public class Kafka {
        public static void main(String[] args) {
            ReplicaManager manager = new ReplicaManager();
            manager.loadReplicaFromDisk();
        }
    }

首先,上面这段.java源程序会被编译成.class文件,.class中存放的是JVM可以读懂的字节码,比如下面这样

    public java.lang.String getName();
        descriptor: ()Ljava/lang/String;
        flags: ACC_PUBLIC
        Code:
            stack=1, locals=1, args_size=1
                0: aload_0
                1: get_field    #2
                4: areturn

当JVM加载类信息到内存之后,实际就会使用自己的 字节码执行引擎 ,去执行这些字节码指令,如下图:

程序计数器的作用就在这里,它会 记录当前执行的字节码指令的位置 ,如下图:

程序计数器是 线程私有 的,也就是说每个线程都有个自己的程序计数器,记录当前线程执行到了哪一条字节码指令:

四、Java虚拟机栈

Java虚拟机栈,其实是一种表示Java方法执行的数据结构。每个方法被执行的时候,都会创建一个栈帧(Stack Frame)用于存储 局部变量表 、 操作栈 、 动作链接 、 方法出口 等信息。每个方法从被调用到执行完成的过程,其实就是一个栈帧在虚拟机栈中从入栈到出栈的过程。

下面的这段程序,肯定有一个main线程来执行main()方法里面的代码,方法内部我们通常会定义一些局部变量,比如manager,JVM中必须有一块区域来保存方法中的这些数据,这个就是Java虚拟机栈,Java虚拟机栈是 线程私有 的。

    public class Kafka {
        public static void main(String[] args) {
            ReplicaManager manager = new ReplicaManager();
            manager.loadReplicaFromDisk();
        }
    }
    public class ReplicaManager {
        public static void loadReplicaFromDisk() {
            Boolean hashFinishedLoad = false;
        }
    }

比如main线程执行了main()方法,那么就会创建一个栈帧(里面存放manager局部变量),并将其压入main线程自己的Java虚拟机栈中,如下图:

然后main线程继续执行loadReplicaFromDisk方法,遇到方法内部的hashFinishedLoad局部变量,就会再创建一个栈帧,压入自己的虚拟机栈中:

上述就是JVM中的”Java虚拟机栈“这个组件的作用: 调用任何方法时,为方法创建栈帧然后入栈,栈帧里存放了这个方法对应的局部变量之类的数据(也包括方法执行的其它相关信息),方法执行完毕后就出栈。

五、Java堆内存

Java堆内存,这是JVM内存区域中最重要的一块区域,存放着各种Java对象,是线程共享区域。

下面代码中,new ReplicaManager()创建了一个对象实例,这个对象实例的相关信息就存放在Java堆内存中:

    public class Kafka {
        public static void main(String[] args) {
            ReplicaManager manager = new ReplicaManager();
            manager.loadReplicaFromDisk();
        }
    }

main线程在执行main()方法时,会为其创建一个栈帧并入栈,栈帧中的局部变量manager存放着ReplicaManager对象实例在Java堆内存中的地址:

六、本地方法栈

本地方法栈,其作用和Java虚拟机栈类似,区别在于本地方法栈是为虚拟机所使用到的 Native方法 服务,而Java虚拟机栈为虚拟机执行Java方法(也就是字节码)服务。本地方法栈也是线程私有的。

JDK中的很多底层API,比如IO、NIO、网络等,如果大家去看它的源码,会发现很多地方是调用的native修饰的方法,比如下面这样:

    public native int hashCode();

在调用native方法时,也会有线程对应的栈来保存native方法底层用到的局部变量表之类的信息,这就是本地方法栈的作用。

七、总结

本章,我们通过代码的执行流程讲解了JVM的内存模型,读者需要重点关注方法区、程序计数器、Java虚拟机栈、Java堆内存与程序执行逻辑的关系,其中Java堆内存是我们后面章节要关注的重点区域。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/309195.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java使用IText生产PDF时,中文标点符号出现在行首的问题处理

Java使用IText生成PDF时,中文标点符号出现在行首的问题处理 使用itext 5进行html转成pdf时,标点符号出现在某一行的开头 但这种情况下显然不符合中文书写的规则,主要问题出在itext中的DefaultSplitCharacter类,该方法主要用来判断…

基于ChatGPT4+Python近红外光谱数据分析及机器学习与深度学习建模

2022年11月30日,可能将成为一个改变人类历史的日子——美国人工智能开发机构OpenAI推出了聊天机器人ChatGPT3.5,将人工智能的发展推向了一个新的高度。2023年4月,更强版本的ChatGPT4.0上线,文本、语音、图像等多模态交互方式使其在…

C# Open Vocabulary Object Detection 部署开放域目标检测

目录 介绍 效果 模型信息 owlvit-image.onnx owlvit-post.onnx owlvit-text.onnx 项目 代码 Form1.cs OWLVIT.cs 下载 C# Open Vocabulary Object Detection 部署开放域目标检测 介绍 训练源码地址:https://github.com/google-research/scenic/tree/…

性格是如何形成的?能不能改变性格?

有一句话叫“性格决定命运”,广泛流传,也就是说 “命运”与“性格”是紧密相连的,可见“性格”对于一个人的重要性。 性格是怎么来的? 1、遗传基因 根据一些心理学家的最新研究,认为性格与人体内的基因有关系&#x…

浏览器缓存引发的odoo前端报错

前两天,跑了一个odoo16项目,莫名其妙的前端报错, moment.js 报的错, 这是一个时间库,不是我自己写的代码,我也没做过任何修改,搞不清楚为什么报错。以为是odoo的bug,所以从gitee下载…

【Python】编程练习的解密与实战(一)

​🌈个人主页:Sarapines Programmer🔥 系列专栏:《Python | 编程解码》⏰诗赋清音:云生高巅梦远游, 星光点缀碧海愁。 山川深邃情难晤, 剑气凌云志自修。 目录 🪐1. 初识Python &a…

RuntimeError: CUDA error: invalid device ordinal解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

C#基础-空处理

在c#中,值对象是没有办法赋值为null的。比如说,你想要定义一个布尔值,你的赋值数据要么得是true、要么就得是false,默认情况下我们永远没可能给这个布尔赋值为null,即使只是对这个变量进行声明而不初始化数据&#xff…

ChatGPT会给教育界带来怎样的冲击,又将与教育碰撞出怎样的火花?

11 月 7 日凌晨,美国人工智能公司 OpenAI 的开发者大会正式开启,创始人 Sam Altman 和其同事,发布了团队最新的成果GPT-4 Turbo,新一代的GPT不仅更快、有更长的上下文、而且更好的控制。而随之推出的「GPTs」——让人们能用自然语…

服务器执行rm命令时自动记录到审计日志中

目的 当在服务器上执行类似于 rm 命令时,自动记录该命令执行的时间,在哪里执行的,删除的什么文件,记录到审计日志中,能够查找到某些文件丢失原因 配置 # 需要root权限,sudo不行,这里假设执行…

Java:爬虫htmlunit实践

之前我们已经讲过使用htmlunit及基础,没有看过的可以参考Java:爬虫htmlunit-CSDN博客 我们今天就来实际操作一下,爬取指定网站的数据 1、首先我们要爬取一个网站数据的时候我们需要对其数据获取方式我们要进行分析,我们今天就拿双…

注册中心(Nacos)

简介 Dynamic Naming and Configuration Service的首字母简称,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。 Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管…

基于DNA的密码学和隐写术综述

摘要 本文全面调研了不同的脱氧核糖核酸(DNA)-基于密码学和隐写术技术。基于DNA的密码学是一个新兴领域,利用DNA分子的大规模并行性和巨大的存储容量来编码和解码信息。近年来,由于其相对传统密码学方法的潜在优势,如高存储容量、低错误率和对环境因素的抗性,该领域引起…

网络之路28:二层链路聚合

正文共:1666 字 14 图,预估阅读时间:2 分钟 目录 网络之路第一章:Windows系统中的网络 0、序言 1、Windows系统中的网络1.1、桌面中的网卡1.2、命令行中的网卡1.3、路由表1.4、家用路由器 网络之路第二章:认识企业设备…

Elasticsearch windows开箱即用【记录】

一、准备工作 安装ES之前要在本机安装好JDK,对应的兼容性见官网链接:https://www.elastic.co/cn/support/matrix ES官网链接:https://www.elastic.co/cn/, 我本机安装的是JDK8,测试使用的是7.3.0版本的ES和Kibana。 1、首先去…

Spring Boot 2.6 以上整合 Swagger + Knife4j 报错

Spring Boot 2.6 以上整合 Swagger Knife4j 报错 报错信息报错原因解决办法 报错信息 org.springframework.context.ApplicationContextException: Failed to start bean documentationPluginsBootstrapper; nested exception is java.lang.NullPointerException: Cannot inv…

premiere简约大气3D动画logo片头Pr模板Mogrt免费下载

Premiere简约大气3D动画logo片头pr模板mogrt下载,无需插件,高清分辨率,易于自定义,包括教程,不包括音频和图像。免费下载:https://prmuban.com/37065.html

centos下系统全局检测工具dstat使用

目录 一:没有需要安装 二:dstat命令参数 三、监测界面各参数含义(部分) 四、dstat的高级用法 一:没有需要安装 yum install dstat 二:dstat命令参数 有默认选项,执行dstat命令不加任何参数…

C语言初始化效率问题以及关键字解释

一、初始化效率 1、在静态变量的初始化中,我们可以把可执行程序文件想要初始化的值放在当程序执行时变量将会使用的位置。当可执行文件载入到内存时,这个已经保存了正确初始值的位置将赋值给那个变量,完成这个任务并不需要额外的时间&#xf…

自动化的运维管理:探究Kubernetes工作机制的奥秘

1 云计算时代的操作系统 Kubernetes 是一个生产级别的 容器编排平台 和 集群管理系统 ,能够 创建、调度容器,监控、管理服务器。 容器是什么?容器是软件,是应用,是进程。服务器是什么?服务器是硬件&#…