Java核心篇之JVM探秘:内存模型与管理初探

系列文章目录

第一章 Java核心篇之JVM探秘:内存模型与管理初探

第二章 Java核心篇之JVM探秘:对象创建与内存分配机制

第三章 Java核心篇之JVM探秘:垃圾回收算法与垃圾收集器

第四章 Java核心篇之JVM调优实战:Arthas工具使用及GC日志分析


目录

前言

一、JVM整体结构图

二、JVM内存区域概述 

三、JVM内存参数设置

XX:PermSize 

-XX:MaxMetaspaceSize和-XX:MetaspaceSize 

三、垃圾回收(Garbage Collection)

分代收集理论:

垃圾回收算法:

四、内存溢出与内存泄漏

内存溢出:

内存泄漏:

总结


前言

        在Java的世界里,JVM(Java Virtual Machine)扮演着至关重要的角色。它不仅提供了运行Java程序的环境,还负责管理内存,确保程序的高效和安全执行。本文将深入探讨JVM内存模型,理解其内部结构与工作原理,帮助开发者更好地优化代码,避免常见的内存问题。


一、JVM整体结构图

二、JVM内存区域概述 

  • 程序计数器(Program Counter Register)

每个线程都有一个独立的程序计数器,用于指示当前线程所执行的字节码指令的位置。当线程被中断或恢复时,程序计数器可以帮助JVM找到上一次执行的位置。

  • 虚拟机栈(Virtual Machine Stack)

也是线程私有的,用于存储局部变量、操作数栈、动态链接和方法出口等信息。每个方法调用都会创建一个新的栈帧,方法退出后,相应的栈帧也会被销毁。

  • 本地方法栈(Native Method Stack)

与虚拟机栈类似,但用于支持本地(非Java)方法的调用。在现代JVM中,它往往与虚拟机栈合并,使用相同的实现方式。

  • Java堆(Heap)

所有线程共享的内存区域,用于存储对象实例和数组。这是垃圾收集的主要区域。Java堆是JVM管理的内存中最大的一块,它的大小可以通过参数进行配置。

  • 方法区(Method Area)

也称为“非堆”,用于存储类信息、常量、静态变量、即时编译后的代码等数据。它与Java堆一样,由所有线程共享。

  • 直接内存(Direct Memory)

不属于JVM内存的一部分,但是通过java.nio.ByteBuffer.allocateDirect()等API分配的内存。直接内存的使用需要特别注意,因为不受JVM的常规内存管理机制控制。

  • 局部变量表(Local Variable Table):

局部变量表用于存储方法参数和方法内部定义的局部变量。局部变量包括基本类型的变量、对象引用和返回地址等。

每个局部变量占据一个或多个“slot”(槽),一个slot可以存放一个32位数据类型,如intfloat或对象引用;64位数据类型,如longdouble,则占用两个slot。

变量的生存周期是从方法被调用开始直到方法结束,此时局部变量表的内容会被销毁。

  • 操作数栈(Operand Stack):

操作数栈是一个后进先出(LIFO)的数据结构,用于存放中间运算结果,同时也作为方法调用和返回的参数传递的场所。

当执行任何计算表达式时,操作数栈用来存放运算符的左右操作数,以及存放运算结果。

方法调用时,参数会被压入操作数栈,方法返回时,返回值会被放入操作数栈,然后传递给调用者。

  • 动态链接(Dynamic Linking):

动态链接是指将方法调用解析为方法在内存中的直接引用。在JVM中,当一个方法调用另一个方法时,它需要知道目标方法的确切位置,即其在内存中的入口点。

这个过程在运行时完成,允许方法在不同的类加载器之间动态查找和链接。

  • 方法出口(Method Exit):

方法出口指的是方法执行完毕后,如何清理现场并返回调用者的过程。这包括恢复上层方法的局部变量表和操作数栈,将返回值(如果有的话)压入调用者的操作数栈中,以及恢复方法调用之前的程序计数器值,以便继续执行调用者的方法。

三、JVM内存参数设置

Spring Boot程序的JVM参数设置格式(Tomcat启动直接加到bin目录下的catalina文件中即可)

java ‐Xms2048M ‐Xmx2048M ‐Xmn1024M ‐Xss512K ‐XX:MetaspaceSize=256M ‐XX:MaxMetaspaceSize=256M ‐jar xxx.jar

XX:PermSize 

在JDK 8之前,类的元数据(包括类信息、常量池、字段信息、方法信息等)是存储在永久代(Permanent Generation)中的。XX:PermSize 参数用于设置永久代的初始大小,而 -XX:MaxPermSize 则用于设置永久代的最大大小。如果永久代的空间不足,JVM 将会抛出 OutOfMemoryError: PermGen space 的错误。

-XX:MaxMetaspaceSize和-XX:MetaspaceSize 

从JDK 8开始,永久代被移除,类元数据被移到了一个名为“Metaspace”的本机内存区域中。这意味着类元数据的管理不再受限于堆内存的限制,而是受限于系统可用的物理内存。

  • -XX:MaxMetaspaceSize:用于设置Metaspace的最大大小。默认情况下,Metaspace可以使用系统的大部分物理内存,但这可能会导致其他应用程序的内存不足。因此,在多应用服务器环境中,通常需要显式地限制Metaspace的大小。

  • -XX:MetaspaceSize:用于设置Metaspace的起始大小。当Metaspace的使用量超过这个值时,JVM会尝试增加Metaspace的大小,直到达到-XX:MaxMetaspaceSize指定的上限。

三、垃圾回收(Garbage Collection)

        垃圾回收是JVM内存管理的核心机制之一。JVM通过自动检测不再被引用的对象,并回收这些对象占用的内存,从而避免了手动内存管理带来的问题,如内存泄漏和野指针。

分代收集理论

  • Java堆通常分为新生代(Young Generation)和老年代(Old Generation)。新生代又细分为Eden空间和两个Survivor空间(S0和S1)。对象首先在Eden空间创建,经过几次GC后,存活的对象会被移动到Survivor空间,最终可能晋升到老年代。

垃圾回收算法

  • 包括标记-清除(Mark-Sweep)、复制(Copying)、标记-压缩(Mark-Compact)和分代收集等算法。每种算法都有其优缺点,适用于不同的场景。

四、内存溢出与内存泄漏

尽管JVM提供了自动内存管理,但在实际开发中,仍需警惕内存溢出和内存泄漏的问题。

内存溢出

  • 当JVM无法申请到足够的内存空间时,会抛出OutOfMemoryError异常。这可能是由于堆大小设置不当、内存泄露或大对象过多导致的。

内存泄漏

  • 即应用程序中存在不再使用的对象,但由于某些原因(如循环引用)它们仍然被引用,导致垃圾收集器无法回收它们,从而浪费内存资源。

总结

        深入理解JVM内存模型对于Java开发者至关重要。它不仅有助于编写更高效的代码,还能有效预防和解决内存相关的问题。随着Java应用的复杂度不断增加,对JVM内存管理的掌握将成为开发者技能树上的重要一环。

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

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

相关文章

基于Java中的SSM框架实现暖心家装平台系统项目【项目源码+论文说明】

基于Java中的SSM框架实现暖心家装平台系统演示 摘要 自从互联网技术得到大规模的应用以后,传统家装企业面临全新的竞争激烈的市场环境。要想占得当前家装营销与管理的先机,除了要加强内部管理,提高企业内部运营效率,更要积极推进…

google 浏览器插件开发简单学习案例:计算器

1、首先,我们需要创建扩展的文件结构 2、创建 manifest.json 文件 是Chrome插件的配置文件,定义了插件的基本信息和资源。 {"manifest_version": 3,"name": "Simple Calculator","version": "1.0"…

[K8S]一、Flink on K8S

Kubernetes | Apache Flink 先编辑好这5个配置文件,然后再直接执行 kubectl create -f ./ kubectl get all kubectl get nodes kubectl get pods kubectl get pod -o wide kubectl get cm -- 获取所有的configmap 配置文件 kubectl logs pod_name -- 查看…

链接追踪系列-00.es设置日志保存7天-番外篇

索引生命周期策略 ELK日志我们一般都是按天存储,例如索引名为"zipkin-span-2023-03-24",因为日志量所占的存储是非常大的,我们不能一直保存,而是要定期清理旧的,这里就以保留7天日志为例。 自动清理7天以前…

Java二十三种设计模式-工厂方法模式(2/23)

工厂方法模式:设计模式中的瑞士军刀 引言 在软件开发中,工厂方法模式是一种常用的创建型设计模式,它用于处理对象的创建,将对象的实例化推迟到子类中进行。这种模式不仅简化了对象的创建过程,还提高了代码的可维护性…

如何预防最新的baxia变种勒索病毒感染您的计算机?

引言 在当今数字化时代,网络安全威胁层出不穷,其中勒索病毒已成为企业和个人面临的重大挑战之一。近期,.baxia勒索病毒以其高隐蔽性和破坏性引起了广泛关注。本文将详细介绍.baxia勒索病毒的特点、传播方式,并给出相应的应对策略…

QT VTK 简单测试工程

目录 1 目录结构 2 文件源码 3 运行结果 4 报错及处理 使用编译好的VTK库进行测试 1 目录结构 2 文件源码 Pro文件 QT core guigreaterThan(QT_MAJOR_VERSION, 4): QT widgetsCONFIG c17# You can make your code fail to compile if it uses deprecated APIs. #…

今天我们来聊Java IO模型,BIO、NIO、AIO三种常见IO模型

一、写在开头 很久没更新喽,最近build哥一直在忙着工作,忙着写小说,都忘记学习自己的本职了,哈哈,不过现在正式回归! 我们继续学习Java的IO相关内容,之前我们了解到,所谓的IO&#…

工作笔记 5 Post请求 密码加密器PasswordEncoder 小程序登录

1.微信小程序登录 1.1小程序登录流程图 1.2使用sa-token完成登录 参考csdn这位老哥的http://t.csdnimg.cn/oRgvI sa-token是一款轻量级的安全框架 1.2.1首先引入sa-token依赖 <dependency><groupId>cn.dev33</groupId><artifactId>sa-token-spring…

java日常开发中常用的集合工具类方法归总(java8 stream)

1、创建map集合的方式 方式1&#xff1a; Map<String, Object> map new HashMap<>(); map.put("a", "test"); map.put("b", "since"); 方式2&#xff1a; Map<String, Object> map2 new HashMap<>() {{…

【云原生】Prometheus整合Alertmanager告警规则使用详解

目录 一、前言 二、Altermanager概述 2.1 什么是Altermanager 2.2 Altermanager使用场景 三、Altermanager架构与原理 3.1 Altermanager使用步骤 3.2 Altermanager工作机制 3.3 Altermanager在Prometheus中的位置 四、Altermanager部署与接入Prometheus 4.1 Altermana…

ConfigMap-secrets-静态pod

一.ConfigMap 1.概述 ConfigMap资源&#xff0c;简称CM资源&#xff0c;它生成的键值对数据&#xff0c;存储在ETCD数据库中 应用场景&#xff1a;主要是对应用程序的配置 pod通过env变量引入ConfigMap&#xff0c;或者通过数据卷挂载volume的方式引入ConfigMap资源 官方解释…

UniVue@v1.4.0版本发布:运行时调试器RuntimeDebuger

GitHub仓库 发布版本仓库&#xff1a;https://github.com/Avalon712/UniVue 开发版本仓库&#xff1a;https://github.com/Avalon712/UniVue-Develop UniVue拓展框架UniVue源生成器仓库&#xff1a;https://github.com/Avalon712/UniVue-SourceGenerator 更新说明 在没有调…

【Python】Windows系统 pip 换源方法(永久 / 临时)

pip 换源 首先国内较好的镜像地址有&#xff1a; 清华&#xff1a;https://pypi.tuna.tsinghua.edu.cn/simple 阿里云&#xff1a;http://mirrors.aliyun.com/pypi/simple 豆瓣&#xff1a;http://pypi.douban.com/simple 腾讯&#xff1a;http://mirrors.cloud.tencent.com/…

Mysql数据表的约束(下)

3.默认值约束(default) 与非空约束的命令一致,因为都属于列级约束,因此只需将not null改为default 默认值即可 删除默认值约束: 4.主键约束(primary key) 表示给一张表格设置了一个唯一标识,为了更快的去通过唯一的数据去准确的查找到每一条记录,一半咱们在创建表…

【Linux】基于环形队列RingQueue的生产消费者模型

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 环形队列的概念及定义 POSIX信号量 RingQueue的实现方式 RingQueue.hpp的构建 Thread.hpp Main.cc主函数的编写 Task.hpp function包装器的使用 总结 前言…

关于Kafka Topic分区和Replication分配的策略

文章目录 1. Topic多分区2. 理想的策略3. 实际的策略4. 如何自定义策略 1. Topic多分区 如图&#xff0c;是一个多分区Topic在Kafka集群中可能得分配情况。 P0-RL代表分区0&#xff0c;Leader副本。 这个Topic是3分区2副本的配置。分区尽量均匀分在不同的Broker上&#xff0c…

第3章 创建最小(Minimal APIs)API应用程序

第1章 框架学习的基石与实战策略 第2章 大话ASP.NET Core 入门 第3章 创建最小&#xff08;Minimal APIs&#xff09;API应用程序 1.最小API概述 在ASP.NET Core的广阔天地里&#xff0c;"最小API应用程序"如同一把轻巧而强大的瑞士军刀&#xff0c;专为迅速构建…

idea中打开静态网页端口是63342而不是8080

问题&#xff1a; 安装了tomcat 并且也配置了环境&#xff0c;但是在tomcat下运行&#xff0c;总是在63342下面显示。这也就意味着&#xff0c;并没有运行到tomcat环境下。 找了好几个教程&#xff08;中间还去学习了maven&#xff0c;因为跟的教程里面&#xff0c;没有maven,但…

【 香橙派 AIpro评测】烧系统运行部署LLMS大模型体验Jupyter Lab AI 应用样例(新手入门)

文章目录 一、引言⭐1.1下载镜像烧系统⭐1.2开发板初始化系统配置远程登陆&#x1f496; 远程ssh&#x1f496;查看ubuntu桌面&#x1f496; 远程向日葵 二、部署LLMS大模型2.1 快速启动&#x1f496;拉取代码&#x1f496;下载mode数据&#x1f496;启动模型对话 三、体验 内置…