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

JVM内存结构介绍

8a4f26c1086942dda8108e9d9dcfc06c.jpg1. 什么是JVM

 

我们都知道在 Windows 系统上一个软件包装包是 exe 后缀的,而这个软件包在苹果的 Mac OSX 系统上是无法安装的。类似地,Mac OSX 系统上软件安装包则是 dmg 后缀,同样无法在 Windows 系统上安装。

 

Java 代码为什么可以在 Windows 系统运行,也可以在 Linux 系统运行?这就是 jvm 的功劳, Java 虚拟机可以理解为一个翻译官,在 Linux 系统上将 Java 代码翻译成 Linux 机器码,在 Windows 系统上将 Java 代码翻译成 Windows 机器码,所以 Java 有了虚拟机之后,可以让 Java 代码运行在不同的系统上。

 

2. JVM内存结构(运行时数据区)

运行时数据区是官方说法,但很多时候这个名词并不是很形象,再加上日积月累的习惯,很多人都习惯用 JVM 内存结构这个说法

 

JVM 内存结构(运行时数据区)主要包括:堆、栈(虚拟机栈)、本地方法栈、方法区、程序计数器等。

 

线程公有:堆、方法区

线程私有:栈、本地方法栈、程序计数器

 

 

2.1 堆(公有)

堆内存被所有线程共享。堆内存用于存放由 new 创建的对象和数组。

 

Java堆分为年轻代(Young Generation)和老年代(Old Generation);年轻代又分为乐园(Eden)和幸存区(Survivor区);幸存区又分为 From 区(From Survivor 区)和 To 区(To Survivor 区)。

 

而 JVM 垃圾回收机制主要收集堆中年轻代和老年代对象所占用的内存空间。

 

 

 

为什么默认的虚拟机配置,Eden:from :to = 8:1:1 ?

 

这是经过大量统计得出的结果发现 80% 的对象存活时间都很短,于是将 Eden 区设置为年轻代的 80%,这样可以减少内存空间的浪费,提高内存空间利用率。

 

年轻代中的 Minor GC

 

1、绝大多数刚刚被创建的对象会存放在乐园(Eden)。

2、在乐园内存满时,执行第一次GC(Minor GC)之后,存活的对象被移动到其中一个幸存区(Survivor)。

3、此后,每次乐园执行GC后,存活的对象会被堆积在同一个幸存区。

4、当一个幸存区饱和,还在存活的对象会被移动到另一个幸存区。然后会清空已经饱和的那个幸存区。

5、在以上步骤中重复N次(N = MaxTenuringThreshold(年龄阀值设定,默认15))依然存活的对象,就会被移动到老年代。

 

从上面的步骤可以发现,两个幸存者空间,必须有一个是保持空的。

 

需要重点记住的是,对象在刚刚被创建之后,是保存在乐园的(Eden)。那些长期存活的对象会经由幸存区(Survivor)转存到老年代(Old generation)。

 

也有例外出现,对于一些比较大的对象(需要分配一块比较大的连续内存空间)则直接进入到老年代(内存分配担保机制)。

 

注意:当年轻代满时就会触发Minor GC,这里的年轻代满指的是Eden满,Survivor满不会引发Minor GC。由于年轻代中的对象存活时间比较短,Minor GC比较频繁,GC 速度也很快。

 

老年代中的 Full GC

 

老年代空间的构成很简单,它不像新生代空间那样划分为几个区域,它只有一个区域,里面存储的对象并不像新生代一样存活时间很短。这里的对象几乎都是从Survivor 区中熬过来的,它们绝不会轻易的被回收掉。

 

注意:Full GC 是清理整个堆空间,包括年轻代和老年代,如果Full GC之后,堆中仍然无法存储对象,就会抛出OutOfMemoryError异常。由于老年代内存不会轻易的被回收掉,因此 Full GC 发生的次数不会有 Minor GC 那么频繁。但是老年代内存大,做一次 Full GC 的时间比 Minor GC 要更长(约10倍)。

 

2.2 方法区(公有)

方法区被所有线程共享。方法区用于存放静态变量、常量、类信息(版本、方法、字段等)、常量池。可以看做是将类(Class)的元数据,保存在方法区里。

 

Integer常量池

 

都知道数据类型 == 比较的是内存地址,先看个下边的例子。

 

public static void main(String[] args)

{

    Integer i1 = 66;

    Integer i2 = 66;

    Integer i3 = 150;

    Integer i4 = 150;

    System.out.println(i1 == i2);//true

    System.out.println(i3 == i4);//false

}

i1 == i2 结果为 true,i3 == i4 结果为 false。由结果得知 i1 和 i2 的内存地址是相同的,而 i3 和 i4 内存地址是不同的。

 

产生这样结果的原因是 Integer i1 = 66 实际上有一步装箱的操作,通过 Integer 的 valueOf 方法将 int 型的 66 装箱成 Integer。下边是 Integer 中的 valudOf 方法。

 

public static Integer valueOf(int i) {

    if (i >= IntegerCache.low && i <= IntegerCache.high)

        return IntegerCache.cache[i + (-IntegerCache.low)];

    return new Integer(i);

}

Integer 的 valueOf 方法很简单,它判断变量是否在 IntegerCache 的最小值(-128)和最大值(127)之间,如果在,则返回常量池中的内容,否则 new 一个 Integer 对象。

 

由于 66 在 -128 ~ 127 之间,所以 66 装箱时,使用的是常量池中的 66,所以 == 结果为 true。

而 150 不在范围内,在装箱时执行了 new Integer(150),所以返回的是新创建的对象,所以 == 结果为 false。

 

String常量池

 

String 是由 final 修饰的类,是不可以被继承的。通常有两种方式来创建对象。

 

// 1

String str = new String("abc");

// 2

String str = abc;

第一种:使用 new 创建的对象,存放在堆中,每次 new 出来的内存地址都不同。

第二种:先在常量池中找有没有 “abc”。有,则直接取常量池内存地址赋值给 str。没有,先在常量池创建“abc”,再取内存地址赋值给 str。

 

通过代码验证上面理论。

 

public static void main(String[] args) {

    String s1 = new String("abc");

    String s2 = new String("abc");

    String s3 = "abc";

    String s4 = "abc";

    System.out.println(s1 == s2);// false

    System.out.println(s3 == s4);// true

}

s1 == s2 为 false 原因:str1 和 str2 使用 new 创建对象,分别在堆上创建了不同的对象。两个引用指向堆中两个不同的对象,所以为 false。

s3 == s4 为 true 原因:首先在栈上存放变量引用 s3,然后去常量池中找是否有 abc,没有,则将 abc 存储在常量池中,然后将 s3 指向常量池的 abc。当 s4 = "abc" 时,去常量池中发现已经有 abc 了,就将 s4 引用指向常量池已有的 abc 。所以s3 == s4,指向同一个内存地址。

String 类中有一个方法 intern,可以返回池中的字符串,如下代码

 

public static void main(String[] args) {

    String s1 = new String("abc");

    String s2 = "abc";

    System.out.println(s1 == s2);// false

    System.out.println(s1.intern() == s2);// true

}

上边的结果可以看下 intern() 方法注释就知道结果。当调用 intern 方法时,如果常量池中已经该字符串,则返回池中的字符串;否则将此字符串添加到常量池中,并返回字符串的引用。

 

2.3 栈(私有)

栈是后进先出的。栈是线程私有的,他的生命周期与线程相同。每个线程都会分配一个栈的空间,一个线程会对应一个栈。

 

栈存储什么

 

栈中存储的是栈帧。每个方法在执行时都会创建一个栈帧。栈帧中存储了局部变量表、操作数栈、动态连接和方法出口等信息。每个方法从调用到运行结束的过程,就对应着一个栈帧在栈中压栈到出栈的过程。可以理解为栈帧就是线程所执行的方法。

 

使用递归时,会导致 StackOverflowError 错误,就是因为不断的在栈中创建栈帧,当栈帧的数量超过了栈的大小时,就会导致报错。

 

 

2.4 本地方法栈(私有)

本地方法栈是线程私有的,主要为 JVM 使用到的 Native 方法服务。Native 方法不是以 Java 语言实现的,而是以本地语言实现的(比如 C 或 C++)。

 

可以理解为 Native 方法是与操作系统直接交互的,比如通知垃圾收集器进行垃圾回收的代码 System.gc(),获取常量池中的字符串引用 String.intern(),都是使用 native 修饰的。

 

2.5 程序计数器(私有)

程序计数器是一个比较小的内存区域,可能是CPU寄存器或者操作系统内存,其主要用于指示当前线程所执行的字节码执行到了第几行,可以理解为是当前线程的行号指示器。

 

字节码解释器在工作时,会通过改变这个计数器的值来取下一条语句指令。 每个程序计数器只用来记录一个线程的行号,所以它是线程私有(一个线程就有一个程序计数器)的。

相关文章:

JVM内存结构介绍

1. 什么是JVM 我们都知道在 Windows 系统上一个软件包装包是 exe 后缀的&#xff0c;而这个软件包在苹果的 Mac OSX 系统上是无法安装的。类似地&#xff0c;Mac OSX 系统上软件安装包则是 dmg 后缀&#xff0c;同样无法在 Windows 系统上安装。 Java 代码为什么可以在 Windows…...

Linux常见指令总结

ls&#xff1a;显示当前目录下文件列表 常用的命令行参数&#xff1a; -l 显示更多的文件属性 -a 显示所有的文件/目录&#xff08;包括隐藏的&#xff09; -d 只显示目录 ps&#xff1a;参数可以叠加使用。 例如&#xff1a;ls -la 显示所有文件…...

Day35-Linux网络管理5

Day35-Linux网络管理5 1. 网卡配置2. DNS客户端域名解析配置3. 给网卡配多个IP4. ip地址查看和设置4.1 ifconfig命令4.2 ip命令4.3 ip命令&#xff1a;查看和设置网络配置4.4 ip命令帮助 5. 路由5.1 路由功能分类&#xff1a;5.2 查看路由&#xff1a;5.3 路由表&#xff1a;5.…...

9个神奇免费AI编程助手,实现高效自动代码生成!

在AIGC技术工具快速发展的时代&#xff0c;对高效智能编程工具的需求和关注已达到空前的高度。本文将介绍9款免费且好用的AI编程助手工具。无论你是经验丰富的开发人员还是刚开始编程旅程的新手&#xff0c;这些AI代码软件都能帮助你提高项目开发的生产力、创造力和准确性&…...

Python 导入Excel三维坐标数据 生成三维曲面地形图(体) 5-3、线条平滑曲面且可通过面观察柱体变化(三)

环境和包: 环境 python:python-3.12.0-amd64包: matplotlib 3.8.2 pandas 2.1.4 openpyxl 3.1.2 scipy 1.12.0 代码: import pandas as pd import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from scipy.interpolate import griddata fro…...

【CSP】2022–09-3 防疫大数据 100分 STL大模拟 使用map优化索引 有坑得注意

2022–09-3 防疫大数据 STL大模拟 使用map优化索引 2022–09-3 防疫大数据 STL大模拟 使用map优化索引基本思路遇到的问题&#xff08;学到的东西&#xff09;感悟完整代码 2022–09-3 防疫大数据 STL大模拟 使用map优化索引 这题中规中矩&#xff0c;不算太难也不算太简单&am…...

【Linux基础(三)】信号

学习分享 1、信号的基本概念2、查看信号列表3、常见信号名称4、signal库函数5、发送信号kill6、kill - signal &#xff08;无参信号&#xff09;示例6.1、kill - signal (不可靠信号)示例6.2、kill - signal (可靠信号)示例 7、信号分类7.1、信号运行原理分类7.2、信号是否携带…...

GEE图像可视化常用函数

目录 图层操作Map.addLayer&#xff08;&#xff09;Map.centerObject&#xff08;&#xff09; 直方图ui.Chart.image.histogram&#xff08;&#xff09; 时间序列统计ui.Chart.image.series&#xff08;&#xff09;ui.Chart.image.seriesByRegion&#xff08;&#xff09; …...

c++基础语法

文章目录 前言命名空间命名空间的使用 缺省参数缺省参数的使用 函数重载函数重载的作用函数重载的使用函数重载原理 引用引用的使用引用的使用场景引用和指针 extern Cinlineauto范围fornullptr 前言 大家好我是jiantaoyab&#xff0c;这篇文章给大家带来的是c语言没有的一些特…...

【工作实践-07】uniapp关于单位rpx坑

问题&#xff1a;在浏览器页面退出登录按钮上“退出登录”字样消失&#xff0c;而在手机端页面正常;通过查看浏览器页面的HTML代码&#xff0c;发现有“退出登录”这几个字&#xff0c;只不过由于样式问题&#xff0c;这几个字被挤到看不见了。 样式代码中有一行为&#xff1a…...

服务层组件

目录 连接层(Connection Pool) SQL接口(SQL Interface) 查询缓存(Caches&Buffers) Management Services&Utilities 查询分析器(Parser) 优化器(Optimizer)...

【学习笔记】VMware vSphere 6.7虚拟化入门

VMware vSphere 6.7虚拟化入门课程介绍 课程内容 1、VMware vSphere 6.7虚拟化入门课程介绍 2、ESXi6.7控制台设置 3、使用vSpkere Host client管理虚拟机 4、VMware EsXi基础操作 5、VMware Esxi存储管理 6、管理ESXi主机网络与虚拟机网络 7、安装配置vCenter Server Applia…...

如何防范企业内部安全威胁?

1 用户行为分析&#xff08;UEBA&#xff09; 现代化的用户行为分析产品具有多种优势功能&#xff0c;使企业能够有效地检测内部威胁。用户行为分析软件通过收集和分析来自各种来源的数据来分析和检测内部人员的可疑行为。这些来源包括网络日志和用户活动日志。通过检查这些数…...

内网渗透-跨域环境渗透-1

目录 smbclient工具 mimikatz工具 Kerbers协议 NTLM认证 hash传递攻击&#xff08;PTH攻击&#xff09; 黄金票据攻击 白银票据 MS14-068 smbclient工具 在linux里面连接远程windows共享目录&#xff0c;可以使用这个工具 ​ 第一种连接方式&#xff1a;smbclient -L 目…...

安信可IDE(AiThinker_IDE)编译ESP8266工程方法

0 工具准备 AiThinker_IDE.exe ESP8266工程源码 1 安信可IDE&#xff08;AiThinker_IDE&#xff09;编译ESP8266工程方法 1.1 解压ESP8266工程文件夹 我们这里使用的是NON-OS_SDK&#xff0c;将NON-OS_SDK中的1_UART文件夹解压到工作目录即可 我这里解压到了桌面&#xff0c…...

【java数据结构】HashMap和HashSet

目录 一.认识哈希表&#xff1a; 1.1什么是哈希表&#xff1f; 1.2哈希表的表示&#xff1a; 1.3常见哈希函数&#xff1a; 二.认识HashMap和HashSet: 2.1关于Map.Entry的说明:,> 2.2Map常用方法说明&#xff1a; 2.3HashMap的使用案例&#xff1a; 2.4Set常见方法…...

基于Springboot的高校汉服租赁网站(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的高校汉服租赁网站&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…...

分布式解决方案

目录 1. 分布式ID1-1. 传统方案1-2. 分布式ID特点1-3. 实现方案1-4. 开源组件 2. 分布式Session2-1. 传统Session2-2. Spring-Session2-3. Token Redis2-4. JWT2-5. 拦截器统一处理Token2-6. Oauth2 3. 分布式锁3-1. redis3-2. Zookeeper 1. 分布式ID 1-1. 传统方案 时间戳U…...

力扣刷题日记——L724. 寻找数组的中心下标

1. 前言 今天是力扣刷题日记的第二天&#xff0c;今天依旧是一道简单题啊&#xff0c;慢慢来&#xff0c;先看看题目是什么吧。 2. 题目描述 给你一个整数数组 nums &#xff0c;请计算数组的 中心下标。 数组 中心下标 是数组的一个下标&#xff0c;其左侧所有元素相加的和…...

【Kotlin】类和对象

1 前言 Kotlin 是面向对象编程语言&#xff0c;与 Java 语言类似&#xff0c;都有类、对象、属性、构造函数、成员函数&#xff0c;都有封装、继承、多态三大特性&#xff0c;不同点如下。 Java 有静态&#xff08;static&#xff09;代码块&#xff0c;Kotlin 没有&#xff1…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

(二)原型模式

原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

#Uniapp篇:chrome调试unapp适配

chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器&#xff1a;Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...