当前位置: 首页 > news >正文

13JVM进阶

JVM内存模型

1、线程私有的数据区

1)、程序计数器

  我们知道,线程是CPU调度的基本单位。在多线程情况下,当线程数超过CPU数量或CPU内核数量时,线程之间就要根据 时间片轮询抢夺CPU时间资源。也就是说,在任何一个确定的时刻,一个处理器都只会执行一条线程中的指令。因此,为了线程切换后能够恢复到正确的执行位置,每条线程都需要一个独立的程序计数器去记录其正在执行的字节码指令地址。

  因此,程序计数器是线程私有的一块较小的内存空间,其可以看做是当前线程所执行的字节码的行号指示器。如果线程正在执行的是一个 Java 方法,计数器记录的是正在执行的字节码指令的地址;如果正在执行的是 Native 方法,则计数器的值为空。

  程序计数器是唯一一个没有规定任何 OutOfMemoryError 的区域。

2)、虚拟机栈

虚拟机栈描述的是Java方法执行的内存模型,是线程私有的。每个方法在执行的时候都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息,而且 每个方法从调用直至完成的过程,对应一个栈帧在虚拟机栈中入栈到出栈的过程。其中,局部变量表主要存放一些基本类型的变量(int, short, long, byte, float, double, boolean, char)和 对象句柄,它们可以是方法参数,也可以是方法的局部变量。

  虚拟机栈有两种异常情况:StackOverflowError 和 OutOfMemoryError。我们知道,一个线程拥有一个自己的栈,这个栈的大小决定了方法调用的可达深度(递归多少层次,或嵌套调用多少层其他方法,-Xss 参数可以设置虚拟机栈大小),若线程请求的栈深度大于虚拟机允许的深度,则抛出 StackOverFlowError 异常。此外,栈的大小可以是固定的,也可以是动态扩展的,若虚拟机栈可以动态扩展(大多数虚拟机都可以),但扩展时无法申请到足够的内存(比如没有足够的内存为一个新创建的线程分配栈空间时),则抛出 OutofMemoryError 异常。

3)、本地方法栈

本地方法栈与Java虚拟机栈非常相似,也是线程私有的,区别是虚拟机栈为虚拟机执行 Java 方法服务,而本地方法栈为虚拟机执行 Native 方法服务。与虚拟机栈一样,本地方法栈区域也会抛出 StackOverflowError 和 OutOfMemoryError 异常。

2、线程共享的数据区

1)、Java 堆

Java 堆的唯一目的就是存放对象实例,几乎所有的对象实例(和数组)都在这里分配内存。Java堆是线程共享的,类的对象从中分配空间,这些对象通过new、newarray、 anewarray 和 multianewarray 等指令建立,它们不需要程序代码来显式的释放。

  由于Java堆唯一目的就是用来存放对象实例,因此其也是垃圾收集器管理的主要区域,故也称为称为 GC堆。从内存回收的角度看,由于现在的垃圾收集器基本都采用分代收集算法,所以为了方便垃圾回收Java堆还可以分为 新生代 和 老年代 。新生代用于存放刚创建的对象以及年轻的对象,如果对象一直没有被回收,生存得足够长,对象就会被移入老年代。新生代又可进一步细分为 eden、survivorSpace0 和 survivorSpace1。刚创建的对象都放入 eden,s0 和 s1 都至少经过一次GC并幸存。如果幸存对象经过一定时间仍存在,则进入老年代。更多关于Java堆和分代收集算法的介绍,请移步我的博文《Java 垃圾回收机制概述》。下图给出了Java堆的结构图:

注意,Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可。而且,Java堆在实现时,既可以是固定大小的,也可以是可拓展的,并且主流虚拟机都是按可扩展来实现的(通过-Xmx(最大堆容量) 和 -Xms(最小堆容量)控制)。如果在堆中没有内存完成实例分配,并且堆也无法再拓展时,将会抛出 OutOfMemoryError 异常。

2)、方法区

 方法区与Java堆一样,也是线程共享的并且不需要连续的内存,其用于存储已被虚拟机加载的 类信息、常量、静态变量、即时编译器编译后的代码等数据。方法区通常和永久区(Perm)关联在一起,但永久代与方法区不是一个概念,只是有的虚拟机用永久代来实现方法区,这样就可以用永久代GC来管理方法区,省去专门内存管理的工作。根据Java虚拟机规范的规定,当方法区无法满足内存分配的需求时,将抛出 OutOfMemoryError 异常。

(1)、运行时常量池

  运行时常量池(Runtime Constant Pool)是方法区的一部分,用于存放编译期生成的各种 字面量 和 符号引用。其中,字面量比较接近Java语言层次的常量概念,如文本字符串、被声明为final的常量值等;而符号引用则属于编译原理方面的概念,包括以下三类常量:类和接口的全限定名、字段的名称和描述符 和 方法的名称和描述符。因为运行时常量池(Runtime Constant Pool)是方法区的一部分,那么当常量池无法再申请到内存时也会抛出 OutOfMemoryError 异常

  运行时常量池相对于Class文件常量池的一个重要特征是具备动态性。Java语言并不要求常量一定只有编译期才能产生,运行期间也可能将新的常量放入池中,比如字符串的手动入池方法intern()。

3)、Java堆 与 方法区的区别

  Java堆是 Java代码可及的内存,是留给开发人员使用的;而非堆(Non-Heap)是JVM留给自己用的,所以方法区、JVM内部处理或优化所需的内存 (如JIT编译后的代码缓存)、每个类结构 (如运行时常量池、字段和方法数据)以及方法和构造方法的代码都在非堆内存中。

说一下 JVM 有哪些垃圾回收器?
Serial:最早的单线程串行垃圾回收器。
Serial Old:Serial 垃圾回收器的老年版本,同样也是单线程的,可以作为 CMS 垃圾回收器的备选预案。
ParNew:是 Serial 的多线程版本。
Parallel 和 ParNew 收集器类似是多线程的,但 Parallel 是吞吐量优先的收集器,可以牺牲等待时间换取系统的吞吐量。
Parallel Old 是 Parallel 老生代版本,Parallel 使用的是复制的内存回收算法,Parallel Old 使用的是标记-整理的内存回收算法。
CMS:一种以获得最短停顿时间为目标的收集器,非常适用 B/S 系统。
G1:一种兼顾吞吐量和停顿时间的 GC 实现,是 JDK 9 以后的默认 GC 选项。
详细介绍一下 CMS 垃圾回收器?

  

CMS 是英文 Concurrent Mark-Sweep 的简称,是以牺牲吞吐量为代价来获得最短回收停顿时间的垃圾回收器。对于要求服务器响应速度的应用上,这种垃圾回收器非常适合。在启动 JVM 的参数加上“-XX:+UseConcMarkSweepGC”来指定使用 CMS 垃圾回收器。
CMS 使用的是标记-清除的算法实现的,所以在 gc 的时候回产生大量的内存碎片,当剩余内存不能满足程序运行要求时,系统将会出现 Concurrent Mode Failure,临时 CMS 会采用 Serial Old 回收器进行垃圾清除,此时的性能将会被降低。
新生代垃圾回收器和老生代垃圾回收器都有哪些?有什么区别?
新生代回收器:Serial、ParNew、Parallel Scavenge
老年代回收器:Serial Old、Parallel Old、CMS
整堆回收器:G1新生代垃圾回收器一般采用的是复制算法,复制算法的优点是效率高,缺点是内存利用率低;老年代回收器一般采用的是标记-整理的算法进行垃圾回收。
简述分代垃圾回收器是怎么工作的?
分代回收器有两个分区:老生代和新生代,新生代默认的空间占比总空间的 1/3,老生代的默认占比是 2/3。
新生代使用的是复制算法,新生代里有 3 个分区:Eden、To Survivor、From Survivor,它们的默认占比是 8:1:1,它的执行流程如下:
把 Eden + From Survivor 存活的对象放入 To Survivor 区;
清空 Eden 和 From Survivor 分区;
From Survivor 和 To Survivor 分区交换,From Survivor 变 To Survivor,To Survivor 变 From Survivor。
每次在 From Survivor 到 To Survivor 移动时都存活的对象,年龄就 +1,当年龄到达 15(默认配置是 15)时,升级为老生代。大对象也会直接进入老生代。
老生代当空间占用到达某个值之后就会触发全局垃圾收回,一般使用标记整理的执行算法。以上这些循环往复就构成了整个分代垃圾回收的整体执行流程。
说一下 JVM 调优的工具?
JDK 自带了很多监控工具,都位于 JDK 的 bin 目录下,其中最常用的是 jconsole 和 jvisualvm 这两款视图监控工具。
jconsole:用于对 JVM 中的内存、线程和类等进行监控;
jvisualvm:JDK 自带的全能分析工具,可以分析:内存快照、线程快照、程序死锁、监控内存的变化、gc 变化等。
常用的 JVM 调优的参数都有哪些?

-Xms2g:初始化推大小为 2g;
-Xmx2g:堆最大内存为 2g;
-XX:NewRatio=4:设置年轻的和老年代的内存比例为 1:4;
-XX:SurvivorRatio=8:设置新生代 Eden 和 Survivor 比例为 8:2;
–XX:+UseParNewGC:指定使用 ParNew + Serial Old 垃圾回收器组合;
-XX:+UseParallelOldGC:指定使用 ParNew + ParNew Old 垃圾回收器组合;
-XX:+UseConcMarkSweepGC:指定使用 CMS + Serial Old 垃圾回收器组合;
-XX:+PrintGC:开启打印 gc 信息;
-XX:+PrintGCDetails:打印 gc 详细信息。

相关文章:

13JVM进阶

JVM内存模型 1、线程私有的数据区 1)、程序计数器 我们知道,线程是CPU调度的基本单位。在多线程情况下,当线程数超过CPU数量或CPU内核数量时,线程之间就要根据 时间片轮询抢夺CPU时间资源。也就是说,在任何一个确定的时刻&#…...

java与c++中的交换方法

最近在写算法的时候,遇到一个问题。 java中编写swap(交换)方法还需要传入一个数组,但是在c中则不需要。 可以看到,在没有传入数组进行交换数组元素的时候,交换前与交换后的值是一样的。 而在c中&#xff…...

OpenCV中world模块介绍

OpenCV中有很多模块,模块间保持最小的依赖关系,用户可以根据自己的实际需要链接相关的库,而不需链接所有的库,这样在最终交付应用程序时可以减少总库的大小。但如果需要依赖OpenCV的库太多,有时会带来不方便,此时可以使…...

IMX6ULL板开发——第一个应用程序

实现第一个应用程序&#xff1a;在IMX6ULL开发板上运行程序hello.c #include <stdio.h>/* 执行命令: ./hello weidongshan* argc 2* argv[0] ./hello* argv[1] weidongshan*/int main(int argc, char **argv) {if (argc > 2)printf("Hello, %s!\n", arg…...

MyBatis Generator - 快速生成 实体类 和 映射文件

目录 一、MyBatis Generator 的使用 1.1、生成类和映射文件 1.1.1、在 pom.xml 中引入依赖 1.1.2、根据 configurationFile 标签中配置的路径 创建 generatorConfig.xml 文件 1.1.3、自动生成类 和 映射文件 1.1.4、在 Insert 标签中添加获取主键值的选项 1.1.5、扫描配置…...

点击查看详情 | 网页版微信客户管理系统如何操作试用?

微信作为我们日常生活中最常用的社交应用之一&#xff0c;早已成为我们与朋友、家人和同事保持联系的重要工具&#xff0c;也是营销引流的重要平台。 通过微信营销&#xff0c;可以比较精准定向亲近用户。而微信的功能并没有很能满足做微信营销的人群&#xff0c;所以我们需要借…...

新加坡攻略

文章目录 基础信息入境行李App电信交通餐饮购物法规旅游牛车水&#xff08;Chinatown&#xff09;克拉码头&#xff08;Clarke Quay&#xff09;东海岸&#xff08;East Coast&#xff09;丹戎巴葛&#xff08;Tanjong Pagar&#xff09;滨海湾&#xff08;Marina Bay&#xff…...

AM@导数的应用@二阶导数的应用@函数的性态研究@函数图形的绘制

文章目录 概念称呼说明驻点极值和极值点最值极值点和最值比较曲线的凹凸性凹凸性判定定理&#x1f47a;例证明 凹凸性和单调性无必然关系拐点寻找拐点&#x1f47a; 函数图形的绘制例 概念 本文讨论导数的应用:利用导数研究函数的性态相关定理主要通过Lagrange中值定理进行推导…...

【2024秋招】2023-9-14 最右后端开发线下一面

1 自我介绍 2 计算机网络 2.1 说说你对tcp滑动窗口的理解 TCP 滑动窗口是 TCP 协议流量控制的一个重要机制。它的主要目的是确保发送方不会因为发送太多数据而使接收方不堪重负。下面我会详细地描述滑动窗口的概念&#xff1a; 窗口的大小&#xff1a; 滑动窗口的大小&#…...

uniapp无感刷新token实现过程

路漫漫其修远兮&#xff0c;前端道路逐渐迷茫&#xff0c;时隔好久好久终于想起了我还有一个小博客&#xff0c;最近在一直在弄uniapp&#xff0c;属实有被恶心到&#xff0c;但也至少会用了&#xff0c;最近实现了一个比较通用的功能&#xff0c;就是无感刷新token&#xff0c…...

一步步掌握Java IO的奥秘:深入学习BIO、NIO,实现客户端与服务器通信

众所周知&#xff0c;Java IO是一个庞大的知识体系&#xff0c;很多人在学习的过程中会感到迷茫&#xff0c;甚至学得一头雾水&#xff0c;而我也曾有同样的困惑。因此&#xff0c;本文的目标是帮助大家一步一步深入学习Java IO&#xff0c;从BIO开始&#xff0c;然后引出JDK1.…...

MIT 生物信息课程

youtube链接 Regulatory Genomics (Lecture 07): 这门课程介绍了基因调控的概念&#xff0c;涉及到基因的开启和关闭。这是生物信息学中的一个核心概念&#xff0c;对于理解整个生物网络至关重要。 Deep Learning for Regulatory Genomics (Lecture 08): 在了解了基因调控的基…...

Windows下安装PyTorch(GPU版本)

PyTorch环境配置及安装 初步机器学习&#xff0c;这里记录下一些学习经过&#xff0c;之后以便于自己查看&#xff0c;同时欢迎各位大佬点评&#xff0c;本节是机器计算的一个包的安装和简单验证。 1.流程 确定自己的硬件信息-确定电脑有英伟达&#xff08;NVIDIA&#xff…...

力扣每日一题57:插入区间

题目描述&#xff1a; 给你一个 无重叠的 &#xff0c;按照区间起始端点排序的区间列表。 在列表中插入一个新的区间&#xff0c;你需要确保列表中的区间仍然有序且不重叠&#xff08;如果有必要的话&#xff0c;可以合并区间&#xff09;。 示例 1&#xff1a; 输入&#x…...

大河弯弯:CSS 文档流与三大元素显示模式

文章目录 参考环境文档流概念三大显示模式 内联元素概念常见的内联元素宽高由内容决定 块级元素概念常见的块级元素宽度受容器影响&#xff0c;高度受内容影响 内联块级元素概念常见的内联块级元素折中方案 设置元素的显示模式display 属性内联元素与块级元素的切换为什么要通过…...

第六章:函数(中)

函数的参数 1.位置参数 位置参数是指函数调用时,参数的位置与函数定义中参数的位置对应,从而确定参数的值。 def fight(x,y,z):return .join((z,y,x)) fight(八神庵,打败了...

Top 10 数据恢复工具,可从iPhone 和 iPad 恢复数据

您是否正在寻找最好的 iPad 恢复软件&#xff0c;但不知道哪个选项最好&#xff1f;没有什么可担心的。本文将为您提供有关根据文件类型、设备兼容性和数据丢失原因等因素选择合适的 iPad 恢复软件的提示。此外&#xff0c;前 10 名提到的恢复软件是安全可靠的。 第 1 部分、iP…...

【C++程序员必修第一课】C++基础课程-14:C++ 函数(上)

1 本课主要内容&#xff1a; 函数是什么&#xff1f;函数的声明、定义和调用&#xff1b;函数返回值&#xff0c;函数参数&#xff0c;参数默认值函数参数不同类型的调用方式&#xff1a;传值、指针、数组、常量引用、引用等 2 主要知识点&#xff1a; 函数是什么&#xff1f; …...

android studio打开flutter项目报红

一、android studio打开flutter项目报红&#xff0c;如下图&#xff1a; 二、解决方法&#xff1a; 2.1 在这个build.gradle添加以下代码&#xff0c;如图&#xff1a; 2.2 在build.gradle最顶部添加如下代码&#xff1a; def localProperties new Properties() def localPr…...

julia笔记:字符和字符串

1 字符 Char类型的值代表单个字符 ca #a: ASCII/Unicode U0061 (category Ll: Letter, lowercase)typeof(c) #Char 将 Char 转换为其对应的整数值&#xff0c;即 Unicode 代码 cInt(c) c #97typeof(c) #Int64 将一个整数值&#xff08;Unicaode&#xff09;转回 Char Cha…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

Redis:现代应用开发的高效内存数据存储利器

一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发&#xff0c;其初衷是为了满足他自己的一个项目需求&#xff0c;即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源&#xff0c;Redis凭借其简单易用、…...

零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程

STM32F1 本教程使用零知标准板&#xff08;STM32F103RBT6&#xff09;通过I2C驱动ICM20948九轴传感器&#xff0c;实现姿态解算&#xff0c;并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化&#xff0c;适合嵌入式及物联网开发者。在基础驱动上新增…...

Visual Studio Code 扩展

Visual Studio Code 扩展 change-case 大小写转换EmmyLua for VSCode 调试插件Bookmarks 书签 change-case 大小写转换 https://marketplace.visualstudio.com/items?itemNamewmaurer.change-case 选中单词后&#xff0c;命令 changeCase.commands 可预览转换效果 EmmyLua…...

pgsql:还原数据库后出现重复序列导致“more than one owned sequence found“报错问题的解决

问题&#xff1a; pgsql数据库通过备份数据库文件进行还原时&#xff0c;如果表中有自增序列&#xff0c;还原后可能会出现重复的序列&#xff0c;此时若向表中插入新行时会出现“more than one owned sequence found”的报错提示。 点击菜单“其它”-》“序列”&#xff0c;…...