JVM区域划分

news2024/11/30 0:31:48

概述

JVM在运行代码时,他使用多块内存空间,不同的内存空间用来放不同的数据,然后配合代码流程,让系统运行起来。

存放类加载信息

举个最简单的例子,比如现在知道了JVM会加载类到内存里来供后续运行,所以JVM里就必须有一块内存区域,用来存放我们写的那些类。
这个区域在JDK 1.8以前的版本里叫方法区,代表JVM中的一块区域。主要是放从“.class”文件里加载进来的类,还会有一些类似常量池的东西放在这个区域里。但是在JDK 1.8以后,这块区域的名字改了,叫做“Metaspace”,可以认为是“元数据空间”这样的意思。当然这里主要还是存放我们自己写的各种类相关的信息。

public class Client {
    public static void main(String[] args) {
        //使用支付宝付款
        Shopping shop = new Shopping(new Alipay());
        shop.payMoney();
    }
}

public class Shopping
{
    private PayMethod payMethod;
    public Shopping(PayMethod payMethod)
    {
        this.payMethod = payMethod;
    }
    //付钱,支付用什么方式付钱,客户自己选择
    public void payMoney()
    {
        String name = payMethod.getClass().getName();
        System.out.println("我在购物,现在要付钱了");
        payMethod.payMoney();
    }
}

public class Alipay implements PayMethod
{
    @Override
    public void payMoney()
    {
        System.out.println("我在使用支付宝支付");
    }
}

在这里插入图片描述

![image.png](https://img-blog.csdnimg.cn/img_convert/2f72a7cd4a9be28a3a995c51a0cbdf5a.png#averageHue=#f7f7f7&crop=0&crop=0&crop=1&crop=1&height=377&id=PokIW&margin=[object Object]&name=image.png&originHeight=753&originWidth=961&originalType=binary&ratio=1&rotation=0&showTitle=false&size=48746&status=done&style=none&title=&width=480.5)
代码运行起来时,需要执行代码中的一个一个的方法,运行方法的时候,方法里面有很多变量之类的东西,需要放在某个内存区域里,如果代码里创建一些对象,这些对象也需要内存空间来存放。

程序计数器

我们写好的Java代码会被翻译成字节码,对应各种字节码指令, 首先Java代码被编译成字节码指令,然后字节码指令一定会被一条一条执行,这样才能实现代码执行的效果。所以当JVM加载类信息到内存之后,实际就会使用自己的字节码执行引擎,去执行代码编译出来的代码指令。
在这里插入图片描述

在执行字节码指令的时候,JVM里就需要一个特殊的内存区域了,那就是“程序计数器”
这个程序计数器就是用来记录当前执行的字节码指令的位置的,也就是记录目前执行到了哪一条字节码指令。
JVM是支持多个线程的,所以其实代码可能会开启多个线程并发执行不同的代码,所以就会有多个线程来并发的执行不同的代码指令因此每个线程都会有自己的一个程序计数器,专门记录当前这个线程目前执行到了哪一条字节码指令了。
在这里插入图片描述

Java虚拟机栈

Java代码在执行的时候,一定是线程来执行某个方法中的代码,哪怕就是下面的代码,也会有一个main线程来执行main()方法里的代码,在main线程执行main()方法的代码指令的时候,就会通过main线程对应的程序计数器记录自己执行的指令位置。

public class Client {
    public static void main(String[] args) {
        //使用支付宝付款
        Shopping shop = new Shopping(new Alipay());
        shop.payMoney();
    }
}

在方法里,我们经常会定义一些方法内的局部变量,比如在上面的main()方法里,其实就有一个“shop”局部变量,他是引用一个Shopping实例对象的,关于这个对象先别去管他,先来看方法和局部变量。
因此,JVM必须有一块区域是来保存每个方法内的局部变量等数据的,这个区域就是Java虚拟机栈。每个线程都有自己的Java虚拟机栈,比如这里的main线程就会有自己的一个Java虚拟机栈,用来存放自己执行的那些方法的局部变量。如果线程执行了一个方法,就会对这个方法调用创建对应的一个栈帧。
栈帧里就有这个方法的局部变量表 、操作数栈、动态链接、方法出口等东西。先关注局部变量。
比如main线程执行了main()方法,那么就会给这个main()方法创建一个栈帧,压入main线程的Java虚拟机栈同时在main()方法的栈帧里,会存放对应的“shop”局部变量。然后假设main线程继续执行Shopping对象里的方法,比如下面这样,就在“payMoney”方法里定义了一个局部变量:“name
在这里插入图片描述

如果“payMoney”方法执行完毕了,就会把“payMoney”方法也从Java虚拟机栈里出栈。
上述就是JVM中的“Java虚拟机栈”这个组件的作用**:调用执行任何方法时,都会给方法创建栈帧然后入栈。**在栈帧里存放了这个方法对应的局部变量之类的数据,包括这个方法执行的其他相关的信息,方法执行完毕之后就出栈。
在这里插入图片描述

Java堆内存

Java堆内存,这里就是存放我们在代码中创建的各种对象的。
比如下面的代码:

public class Client {
    public static void main(String[] args) {
        //使用支付宝付款
        Shopping shop = new Shopping(new Alipay());
        shop.payMoney();
    }
}

上面的“new Shopping()”这个代码就是创建了一个Shopping类的对象实例,这个对象实例里面会包含一些数据,如下面的代码所示。

public class Shopping {
    private PayMethod payMethod;
    public Shopping(PayMethod payMethod) {
        this.payMethod = payMethod;
    }
    //付钱,支付用什么方式付钱,客户自己选择
    public void payMoney() {
        String name = payMethod.getClass().getName();
        System.out.println("我在购物,现在要付钱了");
        payMethod.payMoney();
    }
}

这个“Shopping”类里的“payMethod”就是属于这个对象实例的一个数据。类似Shopping这样的对象实例,就会存放在Java堆内存里。
Java堆内存区域里会放入类似Shopping的对象,然后我们因为在main方法里创建了Shopping对象的,那么在线程执行main方法代码的时候,就会在main方法对应的栈帧的局部变量表里,让一个引用类型的“shop”局部变量来存放Shopping对象的地址。相当于你可以认为局部变量表里的“shop”指向了Java堆内存里的Shopping对象。
在这里插入图片描述

核心内存区域的全流程串讲

在这里插入图片描述
io=1&rotation=0&showTitle=false&size=98630&status=done&style=none&title=&width=651.5)

  1. JVM进程启动,就会先加载Client类到内存里。然后有一个main线程,开始执行Client中的main()方法。
  2. main线程是关联了一个程序计数器的,那么他执行到哪一行指令,就会记录在这里,main线程在执行main()方法的时候,会在main线程关联的Java虚拟机栈里,压入一个main()方法的栈帧。
  3. 接着会发现需要创建一个Shopping类的实例对象,此时会加载Shopping类到内存里来。
  4. 然后会创建一个Shopping的对象实例分配在Java堆内存里,并且在main()方法的栈帧里的局部变量表引入一个“shop”变量,让他引用Shopping对象在Java堆内存中的地址。
  5. 接着,main线程开始执行Shopping对象中的方法,会依次把自己执行到的方法对应的栈帧压入自己的Java虚拟机栈,执行完方法之后再把方法对应的栈帧从Java虚拟机栈里出栈

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java后端web前端10套项目开发案例源码,毕设,期末作业

项目包括 基础的html,css,js,jquery期末作业项目,毕设 1.古风诗意主题的背单词项目 2.模仿考虫软件实现的考拉背单词网页 3.模仿不背单词软件实现的背单词项目 html,css,js,jquery,瀑布流,懒加载的前端毕设 仿京东网站实现的前端平台 java基础作业 1.纯后端学生管…

初识Nodejs -- nodejs简介

视频链接:黑马程序员Node.js全套入门教程 文章目录1. 初识Nodejs1.1 思考为什么JavaScript可以在浏览器中被执行为什么JavaScript可以操作DOM和BOM?浏览器中的JavaScript运行环境1.2 Nodejs简介1.2.1 Nodejs中的JavaScript运行环境1.2.2 Node.js可以做什…

元数据管理-解决方案调研三:元数据管理解决方案——开源解决方案

开源解决方案 3.1、Apache Atlas Atlas 是一组可扩展和可扩展的核心基础治理服务——使企业能够有效和高效地满足其在 Hadoop 中的合规性要求,并允许与整个企业数据生态系统集成。 Apache Atlas 为组织提供开放的元数据管理和治理功能,以构建其数据资产…

没有公网IP,怎么远程访问ERP/NAS?

当前,国内疫情形势不容乐观,企业的经营发展再一次面临巨大挑战。虽然“远程办公”早已不是新鲜词,但依然有大量企业没有做好随时切换到远程办公的准备。如遇疫情风险,企业运营很容易陷入瘫痪。 企业一般在内网部署服务器、视频监…

2分钟看懂OA与ERP

ERP (Enterprise Resource Planning)即企业资源计划,最早是一种供应链的管理思想。它汇合了商贸代理行业的各项特点,旨在协调企业各管理部门围绕市场导向,更加灵活或柔性地开展业务活动,实时地响应市场需求。 从功能来看&#xf…

AVL树左旋转算法思路与图解

AVL树左旋转算法思路与图解 对于数列{4, 3, 6, 5, 7, 8}, 当我们插入8的时候, rightHeight() - leftHeight() > 1成立(也就是当前AVL树中的根节点的BF(平衡因子)> 1了), 此时这个AVL树已经不再是平衡的了, 也就是已经不是一个AVL树了, 所以我们要经过处理之后让其重新平…

【C】输入一行字符,分别统计出其中英文字母、数字、空格和其他字符的个数

C语言没有字符串形式&#xff0c;所以可以用 char[] 数组来代替&#xff0c;但需要指定分配空间&#xff0c;所以可以采用单字符读取的形式&#xff1a; #include<stdio.h> int main(){char ch;int space0,number0,character0,other0;chgetchar(); …

WSO2安装使用的全过程详解

WSO2安装使用的全过程详解1. Install1.1 Docker Install 1.2 Uninstall2. User Guide3. Big Data -- Postgres4. Awakening1. Install 1.1 Docker Install 显示镜像 docker images/docker image ls拉去镜像/版本 docker pull wso2/wso2am 1.2 Uninstall 查看正在运行的容器 d…

流体动力润滑(轴承油膜承载机理)

目录 1.流体动力润滑 2.流体动力润滑的应用&#xff1a;楔形效应承载机理 3.承载量的计算 4.轴承动压油膜 1.流体动力润滑 定义&#xff1a;两个相对运动物体的摩擦表面&#xff0c;用于借助相对速度而产生的黏性流体膜将两摩擦面完全隔离开&#xff0c;由流体膜产生的压力…

那些下载不了的视频,Python只用1行代码就能直接下载

前言 现在有很多网站都并不支持直接下载的&#xff0c;例如我们常去的B站里面的视频&#xff0c;在页面是没有下载按钮的&#xff0c;还有的视频需要我们下载客户端才能下载…虽然这并不能拦住多少人&#xff0c;有些聪明的小伙伴就会去下载一些第三方软件去下载&#xff0c;比…

apache-atlas-hbase-bridge-源码分析

元数据类型 Hbase元数据类型, 包括命令空间、表、列族、列 public enum HBaseDataTypes {// ClassesHBASE_NAMESPACE,HBASE_TABLE,HBASE_COLUMN_FAMILY,HBASE_COLUMN;public String getName() {return name().toLowerCase();} }Hbase元数据采集实现 1&#xff09;批量采集HBa…

MyBatis基于XML的使用——缓存

1、介绍 MyBatis 内置了一个强大的事务性查询缓存机制&#xff0c;它可以非常方便地 配置和定制。 为了使它更加强大而且易于配置&#xff0c;我们对 MyBatis 3 中的缓存实现进行了许多改进。 默认情况下&#xff0c;只启用了本地的会话缓存&#xff0c;它仅仅对一个会话中的数…

【Java】异常处理

异常本质上是程序上的错误&#xff0c;包括程序逻辑错误和系统错误。比如使用空的引用、数组下标越界、内存溢出错误等. 错误在我们编写程序的过程中会经常发生&#xff0c;包括编译期间和运行期间的错误&#xff0c;在编译期间出现的错误有编译器帮助我们一起修正&#xff0c;…

使用java代码向mysql数据库插入100万条数据

使用java代码向mysql数据库插入100万条数据 使用springboot集成Mysql数据库&#xff0c;并使用java代码循环向msql数据库插入100万条数据&#xff0c;并测试插入时间 目录结构使用java代码向mysql数据库插入100万条数据一、使用工具二、项目结构图创建springboot项目启动类创建…

高并发-防止雪崩与穿透

一、DB查询前加锁 /** * 本地堆内缓存&#xff0c;优先级最高 */ ON_HEAP(1), /** * 本地堆外缓存&#xff0c;不影响GC&#xff0c;可以管理比堆内缓存更多的数据 * 数据get/set涉及序列化&#xff0c;性能次于本地堆内缓存 */ OFF_HE…

手撕红黑树

目录 一、概念 二、红黑树的插入操作 第一步: 按照二叉搜索树的规则插入新节点 第二步: 插入后检测性质是否造到破坏&#xff0c;若遭到破坏则进行调整 情况一: cur为红&#xff0c;parent为红&#xff0c;grandfather为黑&#xff0c;uncle存在且为红 情况二: cur为红&a…

JLink 添加新设备用于下载/调试固件

新驱动的安装目录结构如下&#xff1a; 可以看出新版本的 JLink 驱动中已经没有 Devices 目录和 JLinkDevices.xml 文件了&#xff0c;即旧的方法已经不能在新的驱动中使用了。 如果需要继续使用旧的方式添加新设备&#xff0c;则需要下载 JLink_V770d 之前的版本。 在新驱动…

若依框架解读(微服务版)—— 4.认证,登出(Gateway网关)

认证 我们可以查看token值 我们进入授权中心&#xff0c;这里其他的解析解析token的步骤与上一篇文章中的生成token是逆操作&#xff0c;也比较简单。我们进入ignoreWhite.getWhites()方法 此处的两个注解是获取nacos当中的白名单&#xff0c;我们打开nacos&#xff0c;进入网关…

Shell程序退出状态码的命令详解

在本篇文章当中主要给大家介绍了一些常见的程序退出的状态码&#xff01;并且给出一下例子帮助大家仔细理解&#xff0c;并且使用C语言和python语言实现获取子进程退出时候的退出状态码。 程序退出状态码 前言 在本篇文章当中主要给大家介绍一个shell的小知识——状态码。这是…

Object.defineProperty用法

Object.defineProperty() 定义新属性和修改原有的属性 Object.defineProperty( obj&#xff0c;prop,descriptor) 翻译&#xff1a;对象.定义属性&#xff08;对象&#xff0c;属性名必须是字符写法&#xff0c;{ value:所有 }&#xff09; 创建一个对象&#xff1a; var o…