JVM运行时数据区域(Run-Time Data Areas)的解析
# JVM运行时数据区域(Run-Time Data Areas)的解析
欢迎来到我的博客:TWind的博客
我的CSDN::Thanwind-CSDN博客
我的掘金:Thanwinde 的个人主页
本文参考于:深入理解Java虚拟机:JVM高级特性与最佳实践
本文的JVM均指HotSpot 虚拟机
0.前言
首先,JMM(Java 内存模型)和JVM运行时数据区域是两个东西(JVM内存模型),前者是一种规范,类似于接口,譬如 可见性(visibility) 、有序性(ordering )和 原子性(atomicity)
后者则是实打实的对JVM内存的严格划分区域
尽管作为一个八股中经久不衰的考查点,但很少有文章对其进行深度的剖析
虽然我的理解可能也不是很深,但我会尽己所能写出我觉得不该遗漏的地方
1.JDK 1.7
JVM的运行时数据区域在1.7->1.8阶段进行了一次巨大变化,后面的版本直到现在并未有很大的变化,我们就用1.7 和1.8来展示,首先先是1.7:
这里用了一个大致的图像来展现了JDK1.7版本下的JVM内存的大致分布
大致可以分为:
- 虚拟机栈
- 本地方法栈
- 程序计数器(PC)
- 堆内存
- 永久代
- 直接内存
但实际上,内存的划分比这些更为复杂,这里只是简单的概括
虚拟机栈
显而易见的,虚拟机栈是用来存储虚拟机执行的方法栈帧的
每一条线程都拥有自己的一个栈用于储存自己的栈帧
栈帧在其中以栈的形式存储,其严格的分为:
-
局部变量表:存储了这个方法的基本类型变量以及引用类型变量的引用,在编译完成后便不会改变
-
动态链接:包含一个指向当前方法所属类型的运行时常量池(后面会介绍),栈帧会通过这个去找到对应的对象的符号引用和实际引用
[!WARNING]
注意!HotSpot在堆中存储的是对象实例数据+指向对象类型数据的指针!对象类型数据是存储在方法区之中的!
-
操作数栈:用来存储做运算的数,譬如要计算a+b,就会往里面压入a,压入b,然后执行
iadd
(字节码)就会弹出两个数相加并把答案压回 -
返回地址:链接到其执行处,你可以简单的理解为:int a = test(b),这里的test所指的地址也就是返回地址,也就是一个栈帧连接到另一个栈帧上
虚拟机栈有溢出风险:栈帧过多 ,栈内存过小都会引起栈溢出
我在查资料时看到有一种说法:递归过多会引起局部变量表膨胀导致栈溢出:实际上这是错误的,局部变量表在编译完成后就不会变了,膨胀的说法无从说起
涉及到class文件的信息会在后面再行详细讲解
本地方法栈
本地方法为JVM提供了一个用来操作底层的接口,相对应的,其栈内存的管理,使用完全取决于底层来管理
可以参考https://www.artima.com/insidejvm/ed2/jvm9.html
里面提到了:
When a thread invokes a native method, it enters a new world in which the structures and security restrictions of the Java virtual machine no longer hamper its freedom.
也就是说,虚拟机并不会妨碍其运行,就像是用一个“拓展”方法一样
程序计数器(PC)
请不要将其与OS中的PC寄存器弄混!
但你也可以将程序计数器理解为OS中的PC寄存器的虚拟机版:JVM理所当然的需要支持多个线程
那么就需要保存每一个线程上次执行到哪里,便于在每个线程之间来回切换
那么就有一小片内存用来保存其位置,这就是程序计数器
其并不会内存泄漏:就保存个位置想必也泄露不了
[!WARNING]
程序计数器并不属于栈,栈郑等等,你要硬说的话其属于线程:线程中的_last_Java_pc变量就是其上次执行到的位置,可参考
https://cr.openjdk.org/~aph/8064357-rev-1/src/share/vm/runtime/javaFrameAnchor.hpp-.html
每个线程的程序计数器相互独立
堆内存
堆内存是JVM中最重要的存储区之一:他存储了几乎所有Java中的对象的实例数据,字符串常量池,静态变量等等
所以,堆是被所有线程所共享的
就拿栈帧来举例:
对于基本类型的数据,一般会直接存储在局部变量表中
但是对于引用类型的数据,就会引到堆内存中:其存储了实例的数据以及指向实例类型数据的指针,程序会通过实例类型数据来正确的加载使用这个类
对象数据会存储在堆内存中,对象的类型数据会存储在永久代之中
堆内存中还存有譬如字符串常量池,引用类型的静态变量(还没有完全迁移过来,目前基本类型还是储存在方法区,引用类型则在堆区,到了1.8后会把所有静态变量都迁移过来,后面会有实验验证,参考https://stackoverflow.com/questions/8387989/where-are-static-methods-and-static-variables-stored-in-java,以及https://openjdk.org/jeps/122,里面提到了JDK8完全迁移了静态变量区到了堆内存中)
但是:
[!CAUTION]
目前来说,在高版本的JDK中,JIT,逃逸分析,栈上分配使得不是所有的对象都会存储在堆内存之中了,需要注意!
JVM大名鼎鼎的GC回收,在1.7版本的主要对象就是堆内存:永久代由于其设计的原因,难以被回收,所以,堆内存该如何去高效率的回收利用就成了一项十分关键的技术
对于1.7来说,主要是采用分代回收技术:将其分为新生代与老年代,分别采用不同的回收策略:但这并不是我们今天的主角,你只需要知道,堆内存相当于JVM的“硬盘”,需要经常清理就对了
字符串常量池
用来存储字符串常量的地方,原本位于永久代,JDK1.7因为大字符串容易引起永久代溢出便被移到了堆内存之中
这个池子本质上是 JVM 运行时常量池(Runtime Constant Pool)里的一个哈希表 StringTable,你可以理解为:引用在运行时常量池中,本体在堆中
具体来说,所有"xxx"双引号之中的字符串会被加入其中,“a” + "b"这种在编译就能确定的字符串也会加入其中
对于手动拼接的:String a = new String(“a”) + new String(“b”),可以调用intern方法将其加入,本质是将其对象整个移入字符串常量池,而不是复制一份
这样能很好的避免保存很多重复的字符串,比如
public static void main(String[] args) {String a = "a";String b = "b";String c = a + b;c.intern();System.out.println(c == "ab");}
这里会返回true,原因在于c的引用被“移”到了字符串常量池中,String是引用类型
实际上,Integer,Boolean等类型也存在类似的复用:Integer会存储-128-127的对象复用,Boolean会复用true和false,这称为享元机制
永久代
[!WARNING]
永久代在JDK1.8,即JDK8被移除,取而代之的是元空间
经常文章大言不惭的说:永久代就是方法区
实际上,在Java虚拟机规范上,是这么描述方法区的:
The Java Virtual Machine has a method area that is shared among all Java Virtual Machine threads. The method area is analogous to the storage area for compiled code of a conventional language or analogous to the “text” segment in an operating system process. It stores per-class structures such as the run-time constant pool, field and method data, and the code for methods and constructors, including the special methods (§2.9) used in class and instance initialization and interface initialization.
Java虚拟机具有一个方法区域,该方法区域在所有Java虚拟机线程中共享。该方法区域类似于存储区域的常规语言代码,或类似于操作系统过程中的“文本”段。它存储了每个类结构,例如运行时常数池,字段和方法数据以及方法和构造函数的代码,包括类和实例初始化和接口初始化中使用的特殊方法。
所以,方法区就像一个interface,元空间,永久代就是它的实现
如同翻译所说:方法区存储了每个类结构,例如运行时常数池,字段和方法数据以及方法和构造函数的代码
也就是说,每个类的“骨干”就被存在了方法区之中
对于永久代,也就有了这种思想:类不容易被卸载,所以永久代就像蜂巢一样,把每一个类塞进去
这样当然会很方便去管理,但是,对于去卸载类,扩展类会极其困难
随着发展,人们发现对于方法区的GC是非常重要的,对于无用类的回收也非常重要
而且永久代拥有大小限制,不像元空间那样理论上限就是机器的内存大小
于是,在JDK1.8永久代就被移除替换成了可以拓展,便于GC的元空间了
其中的静态变量也被全部移到了堆内存之中(之前只是引用类型的静态变量被移到了堆内存之中)
举个例子,static int a = 10;属于基本类型,会直接存在永久代之中
但是,static student a = new student();student是你的一个自定义类,这里就属于引用类型:永久代之中存储的就是一个指向堆中的引用
运行时常量池
栈帧的动态链接链到的就是这里
运行时常量池就像一个字典:作为符号引用和实际地址的桥梁:
比如说,x = y x,y都是符号,指什么?
这里就要去运行时常量池查找,将其解析为实际上的在堆中的引用(解析的过程并不像这样简单,这里不涉及)
然后会把引用返回,栈帧会将其加入动态链接来替换掉原来的符号引用,便于后序加速访问
上文提到的字符串常量区中的StringTable就存储在其中,StringTable所指向的实际字符串存储在堆中
类元数据
除开运行时常量池外,永久代还存储着最为重要的信息,类元数据:被虚拟机加载的各种类的类型信息,譬如的结构信息,包括类的名称、父类、方法、字段、接口、注解等以及JIT编译后的代码等
所有的类加载后都会将其信息存储在在其中,更形象的说明是:堆中的类的内容,而且永久代中是类的骨架
这一点可以从java对对象的访问看出:先从栈帧的局部变量表中的引用类型可以看出:reference中有一个指向堆的地址,这个地址存储有对象的实例信息和指向永久代的对象的类型信息,两者相辅相成
直接内存
用于NIO的一块内存,这块内存比较特殊,既能直接用native方法操作,又能通过java堆中的DirectByteBuffer直接访问来操作,这样就避免了来回在Java堆和本机内存中来回的复制数据
最常见的用处,就是用于支持NIO的缓冲区:Native内存能直接放入,Java堆能直接读取,极大的提高了IO性能
直接内存不受JVM限制,大小由本地机器的内存限制
2.class文件分析
这是一个简简单单的Java代码:
public class test1 {public static void main(String[] args) {String a = "a";String b = "b";User user = new User();}static class User{String name;String password;}
}
编译后,执行 javap -v target/classes/你的类名.class
就能得到一份比较容易看懂的字节码:
Classfile /E:/JavaSourceCode/jvm-test/target/classes/test1.classLast modified 2025-5-8; size 530 bytes //这里是文件的基本信息,大小,上次修改MD5 checksum 284474226b95abd8838ad253b0d7beb0 //这个文件的M哈希码Compiled from "test1.java" //源文件信息
public class test1minor version: 0 //次版本号major version: 52 //主版本号,52是JAVA 8flags: ACC_PUBLIC, ACC_SUPER //类类型:这里是标识是public,ACC_SUPER无用,已废除
Constant pool: //这个类的常量池,运行后会被搬到自己的运行时常量池(Runtime Constant Pool)#1 = Methodref #7.#28 // java/lang/Object."<init>":()V#2 = String #21 // a//拿最简单的String类型举例//这里#2,你可以理解为是这个量的“位置”,后面的#21对应着其实际或与之关联量的位置#3 = String #23 // b#4 = Class #29 // test1$User#5 = Methodref #4.#28 // test1$User."<init>":()V#6 = Class #30 // test1#7 = Class #31 // java/lang/Object#8 = Utf8 User#9 = Utf8 InnerClasses#10 = Utf8 <init>#11 = Utf8 ()V#12 = Utf8 Code#13 = Utf8 LineNumberTable#14 = Utf8 LocalVariableTable#15 = Utf8 this#16 = Utf8 Ltest1;#17 = Utf8 main#18 = Utf8 ([Ljava/lang/String;)V#19 = Utf8 args#20 = Utf8 [Ljava/lang/String;#21 = Utf8 a//这里直接对应着上面的#2,直接是对应着字符串常量池里面的“a”:运行时记载/链接时会自动将其放到字符串常量池中#22 = Utf8 Ljava/lang/String;#23 = Utf8 b#24 = Utf8 user#25 = Utf8 Ltest1$User;#26 = Utf8 SourceFile#27 = Utf8 test1.java#28 = NameAndType #10:#11 // "<init>":()V#29 = Utf8 test1$User#30 = Utf8 test1#31 = Utf8 java/lang/Object
{//这里是类构造器部分,存储着要去构造类的一些必须的信息//你也可以理解为:类的构造函数,所以它的结构和普通方法很像public test1();descriptor: ()V //方法签名为void,无参flags: ACC_PUBLIC //public范围Code://代码区,从上往下执行stack=1, locals=1, args_size=1 //这里是类的一些信息:操作数栈大小 :1,本地变量表大小:1,只用了一个slot(this),后面解释0: aload_0 //压入this1: invokespecial #1 //调用超类构造器加载(对应着常量池第一个) // Method java/lang/Object."<init>":()V4: return //返回LineNumberTable:line 9: 0 //对应着Java源代码的第九行,没有偏移量:即是这个类的开始地址LocalVariableTable: //本地变量表,仅仅是用来便于你看的,不会存储Start Length Slot Name Signature0 5 0 this Ltest1;//仅仅只有一个变量,就是thispublic static void main(java.lang.String[]); //同上,main的构造类descriptor: ([Ljava/lang/String;)V //返回void,具有一个参数flags: ACC_PUBLIC, ACC_STATIC //具有public和staticCode: //代码区,从上往下执行stack=2, locals=4, args_size=10: ldc #2 // String a2: astore_1 //从常量池中读a,然后存到slot 1中3: ldc #3 // String b5: astore_26: new #4 // class test1$User9: dup //这里是加载User类,通过超类加载器加载10: invokespecial #5 // Method test1$User."<init>":()V13: astore_3 //存储到槽314: returnLineNumberTable: //对应着Java代码的每一行line 11: 0line 12: 3line 13: 6line 14: 14LocalVariableTable: //同上,待会在下面解释slotStart Length Slot Name Signature0 15 0 args [Ljava/lang/String;3 12 1 a Ljava/lang/String;6 9 2 b Ljava/lang/String;14 1 3 user Ltest1$User;
}
SourceFile: "test1.java"
InnerClasses:static #8= #4 of #6; //User=class test1$User of class test1
可以看到,字节码相对于汇编,比较好阅读
其中我们看眼大致的看到,对于一个class,会将其大致分成:常量池+方法(构造函数+其他方法)
其中常量池中,#部分完全可以理解成“地址”,下面的code对应的地址都会回归到常量池
所以常量池就像电话簿一样,提供了每一个要用到的地址和信息
类加载后,常量池会被加入到运行时常量池中
这样就链起来了:
一个方法被调用->创建栈帧->执行code->加载对象->根据栈帧中的动态链接来找到自己类的运行时常量池->从运行时常量池中获取到对象在堆中的地址->读取对象进行操作->根据返回地址返回到对应的栈帧
slot意为“槽”,是对于对于本地变量表的,操作数栈一个基本单位,具体来说,本地变量表里面的所有对象都是用“slot”来作为单位来存储的,比如int,string都占一个slot,long,double则占两个slot,对于其他引用类型,比如你自定义的类,只占一个slot(参照上面表中的user,只占1个slot)
slot更像是用来作为一个“索引”来访问,每个对象都对应着一个自己的slot(占用多个slot的对象会以第一个作为自己的索引),可以通过这个索引直接在局部变量表中找到对应的对象,比如astore_1,就是存储到编号为1的slot之中
class文件的大致描述就这样
3.JDK1.8变化
JDK1.8相对于JDK最大的区别就是,取消了永久代,用元空间代替,把静态变量完全移到了堆区:现在方法区只会存储其引用了,就算是基本类型也是如此
这里如何证明呢?我会新开一篇文章来介绍这个实验
元空间
经过上面的介绍,你大概知道了永久代的缺点了:固定,难回收,难拓展
于是,在JDK1.8,直接删掉了永久代,改用了可以扩展了,便于回收的元空间
元空间可以随意拓展,理论上限制其的只有本地机器对内存的限制:比如win32位限制一个进程最多拥有4GB内存
在存储的内容上,并没有太多的变化,完全剔除了静态变量,主要存储类元数据
这样让GC回收元空间成为可能,虽然想要卸载类还是很困难,但无论如何有了方法
除此之外,JDK1.8在运行时数据区域并未其他区别
4.总结
纸上得来终觉浅,绝知此事要躬行
一定要自己看一些底层的书自己扣扣字眼
并不要完全相信博客之类的内容,尤其是比较偏冷门偏难的内容,最好配合AI自己设计实验去验证!
就比如针对1.8基本类型的静态变量存储在哪,正确答案是堆------但很多文章说是在元空间的运行时常量区中,实际上常量区中存储的只是引用
如果有没说详细或者说错的地方,欢迎指正与讨论!后续我会把我的实验写成文章发布!
相关文章:
JVM运行时数据区域(Run-Time Data Areas)的解析
# JVM运行时数据区域(Run-Time Data Areas)的解析 欢迎来到我的博客:TWind的博客 我的CSDN::Thanwind-CSDN博客 我的掘金:Thanwinde 的个人主页 本文参考于:深入理解Java虚拟机:JVM高级特性与最佳实践 本文的JVM均…...
python基础:序列和索引-->Python的特殊属性
一.序列和索引 1.1 用索引检索字符串中的元素 # 正向递增 shelloworld for i in range (0,len(s)):# i是索引print(i,s[i],end\t\t) print(\n--------------------------) # 反向递减 for i in range (-10,0):print(i,s[i],end\t\t)print(\n--------------------------) print(…...
在k8s中,如何实现服务的访问,k8s的ip是变化的,怎么保证能访问到我的服务
在K8S中,Pod的IP动态变化确实无法直接通过固定IP限制访问,但可以通过标签(Label)、服务(Service)和网络策略(NetworkPolicy)的组合,实现动态身份识别的访问控制ÿ…...
用NVivo革新企业创新:洞悉市场情绪,引领金融未来
在当今快速变化的商业环境中,理解市场和客户的情感脉动是企业成功的关键。尤其在金融行业,无论是评估经济走势、股票市场波动,还是洞察消费者信心,精准把握隐藏在新闻报道、社交媒体和消费者反馈中的情感倾向至关重要。而NVivo这款…...
如何使用极狐GitLab 软件包仓库功能托管 helm chart?
极狐GitLab 是 GitLab 在中国的发行版,关于中文参考文档和资料有: 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 软件包库中的 Helm charts (BASIC ALL) WARNING:Helm chart 库正在开发中,由于功能有限,尚未准备好用…...
Qt 通过控件按钮实现hello world + 命名规范(7)
文章目录 使用编辑框来完成 hello world通过编辑图形化界面方式通过纯代码方式 通过按钮的方式来创建 hello world通过编辑图形化界面方式通过纯代码方式 总结Qt Creator中的快捷键如何使用文档命名规范 简介:这篇文章着重点并不在于创建hello world程序,…...
uniapp index.html怎么改都不生效
打开 manifest.json index.html 模板路径默认为空,所以你改的 index.html 是没用的,uni-app 根本没用这个模板 设置模板后就会生效了...
ABP vNext + gRPC 实现服务间高速通信
ABP vNext gRPC 实现服务间高速通信 💨 在现代微服务架构中,服务之间频繁的调用往往对性能构成挑战。尤其在电商秒杀、金融风控、实时监控等对响应延迟敏感的场景中,传统 REST API 面临序列化负担重、数据体积大、通信延迟高等瓶颈。 本文…...
【JAVA】十三、基础知识“接口”精细讲解!(三)(新手友好版~)
目录 1. Object类 1.1 Object的概念 1.2 Object例子 2. toString 2.1 toString的概念 2.2 为什么要重写toString 2.3 如何重写toString 3. 对象比较equals方法 3.1 equals( ) 方法的概念 3.2 Object类中的默认equals实现 3.3 如何正确重写equals方法 4. hashCode方…...
每周靶点分享:Angptl3、IgE、ADAM9及文献分享:抗体的多样性和特异性以及结构的新见解
本期精选了《脂质代谢的关键调控者Angptl3》《T细胞活化抑制因子VISTA靶点》《文献分享:双特异性抗体重轻链配对设计》三篇文章。以下为各研究内容的概述: 1. 脂质代谢的关键调控者Angptl3 血管生成素相关蛋白3(Angptl3)是血管生…...
网络协议之DHCP和PXE分析
写在前面 本文看下DHCP和PXE相关内容。 1:正文 不知道你自己手动配置过IP地址没有,在Linux的环境中可以通过如下的命令们来进行配置: $ sudo ifconfig eth1 10.0.0.1/24 $ sudo ifconfig eth1 up以及:$ sudo ip addr add 10.0…...
SSH 服务部署指南
本指南涵盖 OpenSSH 服务端的安装、配置密码/公钥/多因素认证,以及连接测试方法。 适用系统:Ubuntu/Debian、CentOS/RHEL 等主流 Linux 发行版。 1. 安装 SSH 服务端 Ubuntu/Debian # 更新软件包索引 sudo apt update# 安装 OpenSSH 服务端 sudo apt i…...
表达式求值(算法题)
#include <bits/stdc.h> // 引入常用头文件 using namespace std;stack<int> num; // 存储操作数的栈 stack<char> op; // 存储运算符的栈/* 执行一次运算操作:1. 从num栈弹出两个操作数(n2先弹出,作为右操作数)2. 从op栈弹出运算符…...
IO流--13--MultipartFile
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 MultipartFile1. 概述2. 常用方法解析2.1 getName方法2.2 getOriginalFileName方法2.3 getContentType方法2.4 isEmpty方法2.5 getSize方法2.6 getBytes方法2.7 get…...
leetcode 242. Valid Anagram
题目描述 因为s和t仅仅包含小写字母,所以可以开一个26个元素的数组用来做哈希表。不过如果是unicode字符,那就用编程语言自带的哈希表。 class Solution { public:bool isAnagram(string s, string t) {int n s.size();if(s.size() ! t.size())return …...
内核态函数strlcpy及strscpy以及用户态函数strncpy
一、背景 编写C程序时有一类看似简单实则经常暗藏漏洞的问题就是字符串的处理。对于字符串的处理,常用的函数如strcpy,sprintf,strcat等,这些函数的区别无外乎就是处理\0结尾相关的逻辑。字符串的长度有时候并不能很好确定&#…...
Matlab 车辆四自由度垂向模型平稳性
1、内容简介 Matlab221-车辆四自由度垂向模型平稳性 可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 4、参考论文 略基于Simulink的汽车平顺性仿真_1_杜充 基于Simulink的汽车平顺性仿真分析_谢俊淋...
【hadoop】Sqoop数据迁移工具的安装部署
一、Sqoop安装与配置 步骤: 1、使用XFTP将Sqoop安装包sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz发送到master机器的主目录。 2、解压安装包: tar -zxvf ~/sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz 3、修改文件夹的名字,将其改为s…...
只出现一次的数字(暴力、哈希查重、异或运算)
目录 一.题目 题目解析 题目链接 二.解题过程 俗手(暴力:数组模拟哈希表) 思路 代码示例 提交情况 本手:哈希查重 思路 代码示例 提交情况 妙手:异或运算 思路 代码示例 提交情况 作者的个人gitee 作者…...
Spark缓存
生活中缓存容量受成本和体积限制(比如 CPU 缓存只有几 MB 到几十 MB),但会通过算法(如 “最近最少使用” 原则)智能决定存什么,确保存的是 “最可能被用到的数据”。 1. 为什么需要缓存? 惰性执…...
linux中的常用命令(一)
目录 常用的快捷键 1- tab键:命令或者路径提示及补全; 2-ctrlc:放弃当前输入,终止当前任务或程序 3-ctrll;清屏 4-ctrlinsert:复制 5-鼠标右键:粘贴; 6-altc:断开连接/ctrlshift r 重新连接 7-alt1/2/3/等:切换回话窗口 8-上下键…...
Lua学习笔记
文章目录 前言1. Lua的数据类型2. Lua的控制结构2.1 循环2.1.1 for2.1.1.1 数值循环2.1.1.2 迭代循环2.1.2 while2.1.3 repeat-until 2.2 条件语句2.3 函数 3. Lua中的变量作用域 前言 Lua是一种轻量级的、高效的、可扩展的脚本语言,由巴西里约热内卢天主教大学&am…...
5月8日星期四今日早报简报微语报早读
5月8日星期四,农历四月十一,早报#微语早读。 1、外交部回应中美经贸高层会谈:这次会谈是应美方请求举行的; 2、河南许昌官方:胖东来联合京东物流打造的供应链产业基地将于今年投入运营; 3、我国外汇储备…...
P2415 集合求和 详解
此题我认为主要考数学逻辑,这个题目考的是你面对代码时,是否会从中去找规律推导一个数学公式。 先看题目: 此题目与集合有关,所以对于数学基础不好的同学,我会先给你讲一下这个集合的相关知识。 一,首先,…...
#define ccw (0)和#define ccw 0什么区别
目录 区别 一般建议 简单总结 #define ccw (0) 和 #define ccw 0 这两者在大多数情况下的功能非常相似,但在细节上有一些区别,主要涉及宏展开时的行为。 区别 #define ccw (0):宏定义的内容是(0),带括…...
跨平台移动开发框架React Native和Flutter性能对比
背景与架构 React Native 和 Flutter 都是跨平台移动开发框架,但它们的性能表现因架构差异而异。React Native 在 2025 年采用了 Bridgeless New Architecture(版本 0.74),使用 JavaScript Interface (JSI) 替代传统的 JavaScrip…...
【PhysUnits】2 SI 量纲 实现解析(prefix.rs)
源码 这是一个编译时量纲检查的物理单位库。 //! Physical Units Library with Type-Level Dimension Checking //! 带类型级量纲检查的物理单位库 //! //! This module provides type-safe physical unit representations using Rusts type system //! to enforce dimension…...
新能源汽车赛道变局:传统车企子品牌私有化背后的战略逻辑
2025年5月,一则资本市场动态引发行业震动:某国内头部传统车企宣布拟以每股2.57美元的价格私有化旗下高端新能源品牌,若交易完成,该新能源品牌将正式从纽交所退市。这一决策发生在全球新能源汽车行业经历剧烈洗牌、资本市场估值逻辑…...
[matlab]private和+等特殊目录在新版本matlab中不允许添加搜索路径解决方法
当我们目录包含有private,或者时候matlab搜索目录不让添加,比如截图: 在matlab2018以前这些都可以加进去后面版本都不行了。但是有时候我们必须要加进去才能兼容旧版本matlab库,比如mexopencv库就是这种情况。因此我们必须找到一个办法加进去…...
ImportError: cannot import name ‘Optional‘ from ‘pydantic‘
概览 再使用Optional定义fastapi可选参数时,出现了错误: ImportError: cannot import name Optional from pydantic python version: 3.8 pydantic version: 2.9.2 快速解决方案 Optional导入修改为typing包,如下 from typing import List…...
“水木精灵” 王泫梓妍时尚造型引关注
“水木精灵” 王泫梓妍一组时尚照片曝光,再次展现其独特时尚品味与青春活力。 照片中,王泫梓妍身着白色针织开衫搭配深蓝色牛仔短裙,开衫上精致的水钻装饰与深蓝色海军领增添了细节亮点,牛仔短裙的金色纽扣设计别致,整…...
数据结构-堆排序
1.定义 -堆中每个节点的值都必须大于等于(或小于等于)其左右子节点的值。如果每个节点的值都大于等于其子节点的值,这样的堆称为大根堆(大顶堆);如果每个节点的值都小于等于其子节点的值,称为…...
影响服务器性能的主要因素是什么
在这个数字化高速发展的时代,服务器就像是幕后的超级英雄,默默支撑着我们丰富多彩的网络世界。首先,硬件配置堪称服务器性能的基石。就好比一辆跑车,强大的引擎(CPU)、宽敞的跑道(内存ÿ…...
为什么 MySQL 用 B+ 树作为数据的索引,以及在 InnoDB 中数据库如何通过 B+ 树索引来存储数据以及查找数据
http://www.liuzk.com/410.html 索引是一种数据结构,用于帮助我们在大量数据中快速定位到我们想要查找的数据。 索引最形象的比喻就是图书的目录了。注意这里的大量,数据量大了索引才显得有意义,如果我想要在 [1,2,3,4] 中找到 4 这个数据&am…...
若依框架Ruoyi-vue整合图表Echarts中国地图标注动态数据
若依框架Ruoyi-vue整合图表Echarts中国地图 概述创作灵感预期效果整合教程前期准备整合若依框架1、引入china.json2、方法3、data演示数据4、核心代码 完整代码[毫无保留]组件调用 总结 概述 首先,我需要回忆之前给出的回答,确保这次的内容不重复&#…...
可撤销并查集,原理分析,题目练习
零、写在前面 可撤销并查集代码相对简单,但是使用场景往往比较复杂,经常用于处理离线查询,比较经典的应用是结合线段树分治维护动态连通性问题。在一些较为综合的图论问题中也经常出现。 前置知识:并查集,扩展域并查…...
中介者模式(Mediator Pattern)详解
文章目录 1. 中介者模式概述1.1 定义1.2 基本思想2. 中介者模式的结构3. 中介者模式的UML类图4. 中介者模式的工作原理5. Java实现示例5.1 基本实现示例5.2 飞机空中交通控制示例5.3 GUI应用中的中介者模式6. 中介者模式的优缺点6.1 优点6.2 缺点7. 中介者模式的适用场景8. 中介…...
Java网络编程:深入剖析UDP数据报的奥秘与实践
在浩瀚的计算机网络世界中,数据传输协议扮演着至关重要的角色。其中,用户数据报协议(UDP,User Datagram Protocol)以其独特的“轻量级”和“无连接”特性,在众多应用场景中占据了一席之地。与更为人熟知的传输控制协议(TCP,Transmission Control Protocol)相比,UDP提…...
17.thinkphp的分页功能
一.分页功能 1.不管是数据库操作还是模型操作,都使用paginate()方法来实现(第一种方式); //查找user表所有数据,每页显示5条 returnView::fetch(index, [list > User::paginate(5)]); 页数: 2.创建一个静态模版页面…...
Pandas比MySQL快?
知乎上有人问,处理百万级数据,Python列表、Pandas、Mysql哪个更快? Pands是Python中非常流行的数据处理库,拥有大量用户,所以拿它和Mysql对比也是情理之中。 实测来看,MySQL > Pandas > Python列表…...
问题 | 低空经济未来发展前景机遇及挑战
低空经济 **一、发展前景与机遇**1. **政策红利加速释放,顶层设计逐步完善**2. **技术突破驱动商业化落地**3. **应用场景多元化拓展**4. **万亿级市场潜力** **二、主要挑战**1. **空域管理与安全监管难题**2. **技术瓶颈与产业链短板**3. **法规与标准体系待完善*…...
Matlab 分数阶PID控制
1、内容简介 Matlab218-分数阶PID控制 可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 4、参考论文 略...
如何对 Oracle 日志文件进行校验
目录 一、基本概述 二、基础知识 1、工具介绍 (1)BBED (2)dump 2、数据解析 (1)BLOCK 0 (2)BLOCK 1 (3)Block n( >=2 ) (4)redo record header (5)redo change 1)redo change header 2)redo change length list (6)Example 三、参考代码…...
从零开始用 AI 编写一个复杂项目的实践方法论
从零开始用 AI 编写一个复杂项目的实践方法论 这篇文章我用ai润色了一下,但是初稿是完全由我个人整理的逻辑思路,不是完全由ai生成的。其中内容也确实是我在实践中遇到问题、解决问题、总结出来的经验。 在从零开发一个复杂项目时,直接把目标…...
k8s监控方案实践(一):部署Prometheus与Node Exporter
k8s监控方案实践(一):部署Prometheus与Node Exporter 文章目录 k8s监控方案实践(一):部署Prometheus与Node Exporter一、Prometheus简介二、PrometheusNode Exporter实战部署1. 创建Namespace(p…...
2.5 特征值与特征向量
本章围绕特征值、特征向量及其应用展开,是线性代数的核心章节之一。以下从四个核心考点系统梳理知识体系: 考点一:矩阵的特征值与特征向量 1. 计算方法 具体矩阵: 解特征方程 ∣ λ E − A ∣ 0 |\lambda E - A| 0 ∣λE−A∣…...
从简历筛选到面试管理:开发一站式智能招聘系统源码详解
当下,如何打造一款高效、精准的一站式智能招聘系统,成为了很多人力资源科技公司和创业团队关注的焦点。在这篇文章中,将带你深入了解如何从零开始开发一款智能招聘系统源码,涵盖从简历筛选到面试管理的全流程。 一、招聘系统的核心…...
10.进程控制(下)
一、进程程序替换(重点) 在程序替换过程中,并没有创建新的进程,只是把当前进程的代码和数据用新程序的代码和数据进行覆盖式的替换。 1)一旦程序替换成功,就去执行新代码了,后序代码不执行 2&am…...
【Python 字符串】
Python 中的字符串(str)是用于处理文本数据的基础类型,具有不可变性、丰富的内置方法和灵活的操作方式。以下是 Python 字符串的核心知识点: 一、基础特性 定义方式: s1 单引号字符串 s2 "双引号字符串" s…...
最新CDGP单选题(第四章)补充
31、 [单选] 企业数据模型主题域的识别准则必须在整个企业模型中保持一致,以下哪项是常用的主题域识别准则: A:使用规范化规则,从系统组合中分离主题域...