JVM知识总结(持续更新)

这里写目录标题

  • java内存区域
    • 程序计数器
    • 虚拟机栈
    • 本地方法栈
    • 方法区
      • 运行时常量池
  • 对象的创建

java内存区域

Java 虚拟机在执行 Java 程序的过程中会把它管理的内存划分成若干个不同的数据区域:

  • 程序计数器
  • 虚拟机栈
  • 本地方法栈
  • 方法区
    在这里插入图片描述

程序计数器

记录下一条需要执行的虚拟机字节码指令的地址:

  • 字节码解释器通过改变程序计数器来依次读取指令,从而实现代码的流程控制,如:顺序执行、选择、循环、异常处理。
  • 在多线程的情况下,程序计数器用于记录当前线程执行的位置,从而当线程被切换回来的时候能够知道该线程上次运行到哪儿了。

虚拟机栈

虚拟机栈是描述java方法执行的线程内存模型,是线程私有,生命周期同线程一样。

方法调用的数据需要通过栈进行传递,每一次方法调用都会有一个对应的栈帧被压入栈中,每一个方法调用结束后,都会有一个栈帧被弹出。

栈由一个个栈帧组成,而每个栈帧中都拥有:局部变量表、操作数栈、动态链接、方法返回地址。和数据结构上的栈类似,两者都是先进后出的数据结构,只支持出栈和入栈两种操作。
局部变量表 主要存放了编译期可知的各种数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference 类型,它不同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或其他与此对象相关的位置)
操作数栈主要作为方法调用的中转站使用,用于存放方法执行过程中产生的中间计算结果。另外,计算过程中产生的临时变量也会放在操作数栈中。
动态链接 主要服务一个方法需要调用其他方法的场景。当一个方法要调用其他方法,需要将常量池中指向方法的符号引用转化为其在内存地址中的直接引用。动态链接的作用就是为了将符号引用转换为调用方法的直接引用。

Java 方法有两种返回方式,一种是 return 语句正常返回,一种是抛出异常。不管哪种返回方式,都会导致栈帧被弹出。也就是说, 栈帧随着方法调用而创建,随着方法结束而销毁。无论方法正常完成还是异常完成都算作方法结束。

这个内存区域规定了两类异常状态:

  1. 一是StackOverFlowError 异常,这个在方法出现无无限递归是就会出现,原因是线程请求栈的深度超过当前 Java 虚拟机栈的最大深度
  2. 二是OutOfMemoryError异常,如果栈的内存大小可以动态扩展, 如果虚拟机在动态扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常

本地方法栈

和虚拟机栈作用类似,区别是虚拟机栈为虚拟机执行 Java 方法 (也就是字节码)服务,而本地方法栈则为虚拟机使用到的本地方法服务

虚拟机中所管理的内存最大的一块区域,作用是为java对象分配内存。

Java 堆是垃圾收集器管理的主要区域,因此也被称作 GC 堆(Garbage Collected Heap)。从垃圾回收的角度,由于现在收集器基本都采用分代垃圾收集算法,所以 Java 堆还可以细分为:新生代和老年代;再细致一点有:Eden、Survivor、Old 等空间。进一步划分的目的是更好地回收内存,或者更快地分配内存。这个后面讲垃圾回收时会细讲。

堆这里最容易出现的就是 OutOfMemoryError 错误,并且出现这种错误之后的表现形式还会有几种,比如:

  1. java.lang.OutOfMemoryError: GC Overhead Limit Exceeded:当 JVM 花太多时间执行垃圾回收并且只能回收很少的堆空间时,就会发生此错误。
  2. java.lang.OutOfMemoryError: Java heap space :假如在创建新的对象时, 堆内存中的空间不足以存放新创建的对象, 就会引发此错误

方法区

方法区和堆一样,是线程共享的内存区域,它用于存储被虚拟机加载的类信息、字段信息、方法信息、常量、静态变量、即时编译器编译后的代码缓存等数据。

永久代和元空间是实现方法区的两种方式, 从JDK6开始,HotSpot就开始放弃永久代,逐步采用本地内存(元空间)来实现方法区:

  1. 永久代有 -XX:MaxPermSize JVM 的上限,不设置也有默认大小,无法进行调整,而元空间使用的是本地内存,受本机可用内存的限制,虽然元空间仍旧可能溢出,但是比原来出现的几率会更小。

当元空间溢出时会得到如下错误:java.lang.OutOfMemoryError: MetaSpace

你可以使用 -XX:MaxMetaspaceSize 标志设置最大元空间大小,默认值为 unlimited,这意味着它只受系统内存的限制。-XX:MetaspaceSize 调整标志定义元空间的初始大小如果未指定此标志,则 Metaspace 将根据运行时的应用程序需求动态地重新调整大小。

  1. 元空间里面存放的是类的元数据,这样加载多少类的元数据就不由 MaxPermSize 控制了, 而由系统的实际可用空间来控制,这样能加载的类就更多了。

  2. 在 JDK8,完全放弃了永久代的概率,改用了使用本地内存的元空间来代替。

相对堆而言,垃圾收集行为在这个区域是比较少出现的,但并非数据进入方法区后就“永久存在”了。这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载,但条件比较苛刻,所以这个区域的回收效果比较难令人满意。

判断一个类是否无用:

  • 该类所有的实例都已经被回收,也就是Java堆中不存在该类及其任何派生子类的实例。
  • 加载该类的类加载器已经被回收,这个条件除非是经过精心设计的可替换类加载器的场景,如OSGi、JSP的重加载等,否则通常是很难达成的。
  • 该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

Java虚拟机被允许对满足上述三个条件的无用类进行回收,这里说的仅仅是“被允许”,而并不是和对象一样,没有引用了就必然会回收。

运行时常量池

方法区的一部分,Class 文件中除了有类的版本、字段、方法、接口等描述信息外,还有用于存放编译期生成的各种字面量(Literal)和符号引用(Symbolic Reference)的 常量池表(Constant Pool Table) ,这部分内容将在类加载后存放在方法区的运行时常量池

字符串常量池 是 JVM 为了提升性能和减少内存消耗针对字符串(String 类)专门开辟的一块区域,主要目的是为了避免字符串的重复创建。

JDK1.7 之前,字符串常量池存放在永久代。JDK1.7 字符串常量池和静态变量从永久代移动了 Java 堆中。这是因为永久代(方法区实现)的 GC 回收效率太低,只有在整堆收集 (Full GC)的时候才会被执行 GC。Java 程序中通常会有大量的被创建的字符串等待回收,将字符串常量池放到堆中,能够更高效及时地回收字符串内存。

运行时常量池、方法区、字符串常量池这些都是不随虚拟机实现而改变的逻辑概念,是公共且抽象的,Metaspace、Heap 是与具体某种虚拟机实现相关的物理概念,是私有且具体的。

对象的创建

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

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

相关文章

【ArcGIS遇上Python】ArcGIS Python批量筛选多个shp中指定字段值的图斑(以土地利用数据为例)

文章目录 一、案例分析二、提取效果二、代码运行效果三、Python代码四、数据及代码下载一、案例分析 以土地利用数据为例,提取多个shp数据中的旱地。 二、提取效果 原始土地利用数据: 属性表: 提取的旱地:(以图层名称+地类名称命名)

汽车有FOTA升级,FOTA与OTA有什么差异? 做FOTA,有那些注意事项?

FOTA(Firmware Over-The-Air)和OTA(Over-The-Air)是现代汽车和其他设备远程升级技术的重要组成部分。它们之间的差异主要在于升级的内容和应用的范围: FOTA (Firmware Over-The-Air): FOTA 特指固件的无线更新。在汽车…

HarmonyOS应用开发者高级认证题库

开发者能力认证 一、判断题 在column和Row容器组件中,aligntems用于设置子组件在主轴方向上的对齐格式,justifycontent用于设置子组件在交叉轴方向上的对齐格式(错误)所有使用Component修饰的自定义组件都支持onPageShow&#x…

基于python舆情分析可视化系统+情感分析+爬虫+机器学习(源码)✅

大数据毕业设计:Python招聘数据采集分析可视化系统✅ 毕业设计:2023-2024年计算机专业毕业设计选题汇总(建议收藏) 毕业设计:2023-2024年最新最全计算机专业毕设选题推荐汇总 🍅感兴趣的可以先收藏起来&…

【温故而知新】HTML元素/属性/标题/注释/段落/文本格式/头部/主体

文章目录 一、概念二、元素三、属性四、标题五、注释六、段落七、文本格式八、头部九、主体 一、概念 HTML(HyperText Markup Language,超文本标记语言)是用于创建网页的标准标记语言。它被用来描述网页的结构和内容,并且是网页浏…

Vue学习笔记6--配置代理

一、axios Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests。 二、配置代理 1. 方法一 在…

Python 自学(八) 之模块

目录 1. import语句导入模块 P206 2. from ... import 语句导入模块 P207 3. 模块的搜索目录 sys.path P209 4. 以主程序的形式执行 __name__ P212 5. python中的包 P213 1. import语句导入模块 P206 同一目录下&…

K8S滚动更新守护进程集

Updating a DaemonSet 更新守护进程集 DaemonSets are great for deploying services across an entire cluster, but what about upgrades? Prior to Kubernetes 1.6, the only way to update Pods managed by a DaemonSet was to update the DaemonSet and then manually d…

响应式Web开发项目教程(HTML5+CSS3+Bootstrap)第2版 第1章 HTML5+CSS3初体验 项目1-1 三栏布局页面

项目展示 三栏布局是一种常用的网页布局结构。 除了头部区域、底部区域外,中间的区域(主体区域)划分成了三个栏目,分别是左侧边栏、内容区域和右侧边栏,这三个栏目就构成了三栏布局。当浏览器的宽度发声变化时&#x…

【java八股文】之JVM基础篇

【java八股文】之JVM基础篇-CSDN博客 【java八股文】之MYSQL基础篇-CSDN博客 【java八股文】之Redis基础篇-CSDN博客 【java八股文】之Spring系列篇-CSDN博客 【java八股文】之分布式系列篇-CSDN博客 【java八股文】之多线程篇-CSDN博客 【java八股文】之JVM基础篇-CSDN博…

设计模式-委托模式

设计模式专栏 模式介绍模式特点应用场景委托模式在GUI编程场景的应用代码示例Java实现委托模式Python实现委托模式 委托模式在spring中的应用 模式介绍 委托模式是一种软件设计模式,其中一个对象(委托对象)将某些操作委托给另一个对象&#…

css深度选择器 /deep/

一、/deep/的含义和使用 /deep/ 是一种 CSS 深度选择器,也被称为深度组合器或者阴影穿透组合器,主要用在 Web 组件样式封装中。 在 Vue.js 或者 Angular 中,使用了样式封装技术使得组件的样式不会影响到全局,也就是说组件内部的…

C++函数(4)

短信计费 题目描述:用手机发短信,一条短信资费为0.1元,但限定一条短信的内容在70个字以内(包括70个字)。如果你一次所发送的短信超过了70个字,则会按照每70个字一条短信的限制把它分割成多条短信发送。假设…

《Python 3 基础》- numpy的array,python的list、tuple的区别与联系再辨析

这里写自定义目录标题 一、基本认识二、list与传统数组(以C为例)的联系与区别三、1维list切片规则四、2维list类似于2维数组,但表达方式需适应五、list与元组的联系与区别1. tuple的创建方法类似于list,tuple用(&#…

白码CRM快速实现报价转订单功能

某crm项目已经做到销售模块了,销售模块实现了从报价到销售单,再到财务模块的应收流程。但使用过程中发现不好用的地方:报价通过后客户下单,销售相关人员又要重新录入数据一样的销售单,觉得这样的操作比较繁琐&#xff…

【STM32】HAL库的STOP低功耗模式UART串口唤醒,第一个接收字节出错的问题(已解决)

【STM32】HAL库的STOP低功耗模式UART串口唤醒,第一个接收字节出错的问题(已解决) 文章目录 BUG复现调试代码推测原因及改进方案尝试中断时钟供电外设唤醒方式校验码硬件问题 切换到STOP0模式尝试结论和猜想解决方案附录:Cortex-M…

【leetcode100-035】【链表/哈希链表】LRU缓存

【题干】 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类: LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,…

说清楚Kubernetes、Docker、Dockershim、Containerd、runC、CRI、OCI的关系

Kubernetes v1.20版本 的 release note 里说 deprecated docker。并且在后续版本 v1.24 正式删除了 dockershim 组件,这对我们有什么影响呢?Kubernetes 1.20: The Raddest Release | Kubernetes 为了搞明白这件事情,以及理解一系列容器名词 …

仿真机器人-深度学习CV和激光雷达感知(项目2)day01【项目介绍与环境搭建】

文章目录 前言项目介绍功能与技术简介硬件要求环境配置虚拟机运行项目demo 前言 💫你好,我是辰chen,本文旨在准备考研复试或就业 💫本文内容是我为复试准备的第二个项目 💫欢迎大家的关注,我的博客主要关注…

03.neuvector之组的划分逻辑

neuvector之组的划分逻辑 原文链接,欢迎大家关注我的github账号 一、组的定义 NeuVector 会自动从正在运行的应用程序中创建组。这些组以前缀‘nv‘开头。您也可以使用 CRD 或 REST API 手动添加它们,并且可以在任何模式下创建、发现、监视或保护。网络和响应规则需…