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

【JVM详解一】类加载过程与内存区域划分

一、简介

1.1 概述

JVM是Java Virtual Machine(Java虚拟机)的缩写,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。由一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域等组成。JVM屏蔽了与操作系统平台相关的信息,使得Java程序只需要生成在Java虚拟机上运行的目标代码(字节码),就可在多种平台上不加修改的运行,这也是Java能够“一次编译,到处运行的”原因。

所谓java能实现跨平台,是由在不同平台上运行不同的虚拟机决定的,因此java文件的执行不直接在操作系统上执行,而是通过jvm虚拟机执行,我们可以从这张图看到,JVM并没有直接与硬件打交道,而是与操作系统交互用以执行java程序。

1.2 JRE、JDK和JVM的关系

JRE(Java Runtime Environment, Java运行环境)是Java平台,所有的程序都要在JRE下才能够运行。包括JVM和Java核心类库和支持文件。

JDK(Java Development Kit,Java开发工具包)是用来编译、调试Java程序的开发工具包。包括Java工具(javac/java/jdb等)和Java基础的类库(java API )。

JVM(Java Virtual Machine, Java虚拟机)是JRE的一部分。JVM主要工作是解释自己的指令集(即字节码)并映射到本地的CPU指令集和OS的系统调用。Java语言是跨平台运行的,不同的操作系统会有不同的JVM映射规则,使之与操作系统无关,完成跨平台性。

使用JDK(调用JAVA API)开发JAVA程序后,通过JDK中的编译程序(javac)将Java程序编译为Java字节码,在JRE上运行这些字节码,JVM会解析并映射到真实操作系统的CPU指令集和OS的系统调用。

二、JVM架构

JVM的架构分为多个子系统,主要包括类加载子系统、运行时数据区、垃圾回收机制和执行引擎等。

2.1 类加载子系统

JVM 将 class 字节码文件加载到内存中, 并将这些静态数据转换成方法区中的运行时数据结构,在堆(并不一定在堆中,HotSpot在方法区中)中生成一个代表这个类的 java.lang.Class 对象,作为方法区类数据的访问入口。 

2.1.1 类加载器

把类加载阶段的 “ 通过一个类的全限定名来获取描述此类的二进制字节流 ” 这个动作交给虚拟机之外的类加载器来完成。这样的好处在于,我们可以自行实现类加载器来加载其他格式的类,只要是二进制字节流就行,这就大大增强了加载器灵活性。系统自带的类加载器分为三种:

  • 启动类加载器 ===》 Bootstrap ClassLoader
  • 扩展类加载器 ===》 Extension ClassLoader
  • 应用程序类加载器 ===》Application ClassLoader

2.1.1.1 双亲委派机制

如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父加载器去完成,每个层次的类加载器都是如此。因此所有的加载请求最终都会传送到Bootstrap类加载器(启动类加载器)中,只有父类加载反馈自己无法加载这个请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。

层级结构如下图所示:

双亲委派模型的优点:

java类随着它的加载器一起具备了一种带有优先级的层次关系。

例如类 java.lang.Object ,它存放在 rt.jar 之中,无论哪一个类加载器都要加载这个类,最终都是双亲委派模型最顶端的 Bootstrap 类加载器去加载。因此 Object 类在程序的各种类加载器环境中都是同一个类。相反,如果没有使用双亲委派模型,由各个类加载器自行去加载的话,如果用户编写了一个称为 “java.lang.Object” 的类,并存放在程序的ClassPath中,那系统中将会出现多个不同的 Object 类,java 类型体系中最基础的行为也就无法保证,应用程序也将会一片混乱。

2.1.1.2 自定义类加载器

继承 ClassLoader 类,重写 findClass() 方法:

2.1.2 类加载过程

类的加载过程如下:

 JVM类加载机制分为五个部分:加载,校验,准备,解析,初始化,下面我们就分别来看一下这五个过程。其中加载、校验、准备、初始化和卸载这个五个阶段的顺序是固定的,而解析则未必。为了支持动态绑定,解析这个过程可以发生在初始化阶段之后。

加载(Loading):类加载器从字节流中读取类的二进制数据并将其加载到内存中。
验证(Verification):验证类的字节码是否符合JVM规范,防止恶意代码的侵入。
准备(Preparation):为类的静态变量分配内存并设置默认值。
解析(Resolution):将类中的符号引用解析为直接引用。
初始化(Initialization):执行类的构造方法,初始化类的静态变量和静态代码块。

2.1.2.1 加载

类加载器从字节流中读取类的二进制数据并将其加载到内存中。

加载过程主要完成三件事情:

  • 通过类的全限定名来获取定义此类的二进制字节流
  • 将这个类字节流代表的静态存储结构转为方法区的运行时数据结构
  • 在堆中生成一个代表此类的 java.lang.Class 对象,作为访问方法区这些数据结构的入口。

这个过程主要由类加载器完成。

2.1.2.2 校验

验证类的字节码是否符合JVM规范,防止恶意代码的侵入。

  • 文件格式验证:基于字节流验证。
    • 是否以魔数0xCAFEBABE开头。
    • 主、次版本号是否在当前虚拟机处理范围之内。
    • 常量池的常量中是否有不被支持的常量类型(检查常量tag标志)。
    • 指向常量的各种索引值中是否有指向不存在的常量或不符合类型的常量。
    • CONSTANT_Utf8_info型的常量中是否有不符合UTF8编码的数据。
    • Class文件中各个部分及文件本身是否有被删除的或附加的其他信息。
  • 元数据验证:基于方法区的存储结构验证。
    • 这个类是否有父类(除了java.lang.Object之外,所有类都应当有父类)。
    • 这个类是否继承了不允许被继承的类(被final修饰的类)。
    • 如果这个类不是抽象类,是否实现了其父类或接口之中所要求实现的所有方法。
    • 类中的字段、方法是否与父类产生矛盾(例如覆盖了父类的final字段,或者出现不符合规则的方法重载,例如方法参数都一致,但返回值类型却不同等等)。
  • 字节码验证:基于方法区的存储结构验证。主要目的是通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的。
    • 保证任意时刻操作数栈的数据类型与指令代码序列都能配合工作,例如不会出现类似这样的情况:在操作数栈放置了一个int类型的数据,使用时却按long类型来加载入本地变量表中。
    • 保证跳转指令不会跳转到方法体以外的字节码指令上。
    • 保证方法体中的类型转换是有效的,例如可以把一个子类对象赋值给父类数据类型,但是把父类对象赋值给子类数据类型,甚至把对象赋值给与它毫无继承关系、完全不相干的一个数据类型,则是危险不合法的。
  • 符号引用验证:基于方法区的存储结构验证。可以看作是类对自身以外(常量池中的各种符号引用)的信息进行匹配性校验。
    • 符号引用中通过字符串描述的全限定名是否能够找到对应的类。
    • 在指定类中是否存在符合方法的字段描述符以及简单名称所描述的方法和字段。
    • 符号引用中的类、字段、方法的访问性(private、protected、public、default)是否可被当前类访问。

2.1.2.3 准备

为类变量分配内存(不包括实例变量),并将其初始化为默认值。(此时为默认值,在初始化的时候才会给变量赋值)即在方法区中分配这些变量所使用的内存空间。例如:

此时在准备阶段过后的初始值为0而不是123;将value赋值为123的 putstatic 指令是程序被编译后,存放于类构造器<clinit>方法之中。
特例:

此时value的值在准备阶段过后就是123。

2.1.2.4 解析

把类型中的符号引用转换为直接引用。

  • 符号引用与虚拟机实现的布局无关,引用的目标并不一定要已经加载到内存中。各种虚拟机实现的内存布局可以各不相同,但是它们能接受的符号引用必须是一致的,因为符号引用的字面量形式明确定义在Java虚拟机规范的Class文件格式中。
  • 直接引用可以是指向目标的指针,相对偏移量或是一个能间接定位到目标的句柄。如果有了直接引用,那引用的目标必定已经在内存中存在

主要有以下四种:

  • 类或接口的解析
  • 字段解析
  • 类方法解析
  • 接口方法解析

2.1.2.5 初始化

初始化阶段是执行类构造器<clinit>方法的过程。<clinit>方法是由编译器自动收集类中的类变量的赋值操作和静态语句块中的语句合并而成的。虚拟机会保证<clinit>方法执行之前,父类的<clinit>方法已经执行完毕。如果一个类中没有对静态变量赋值也没有静态语句块,那么编译器可以不为这个类生成<clinit>方法。

java中,对于初始化阶段,有且只有以下五种情况才会对要求类立刻“初始化”(加载,验证,准备,自然需要在此之前开始):

  • 使用 new 关键字实例化对象、访问或者设置一个类的静态字段(被final修饰、编译器优化时已经放入常量池的例外)、调用类方法,都会初始化该静态字段或者静态方法所在的类。
  • 初始化类的时候,如果其父类没有被初始化过,则要先触发其父类初始化。
  • 使用 java.lang.reflect 包的方法进行反射调用的时候,如果类没有被初始化,则要先初始化。
  • 虚拟机启动时,用户会先初始化要执行的主类(含有main)。
  • jdk 1.7后,如果 java.lang.invoke.MethodHandle 的实例最后对应的解析结果是 REF_getStatic、REF_putStatic、REF_invokeStatic方法句柄,并且这个方法所在类没有初始化,则先初始化。

2.2 运行时数据区(HotSpot虚拟机)

JVM在程序执行时,管理着多个内存区域,称为运行时数据区。每个区域有不同的用途,主要包括以下几个区域:

  • 方法区:存储类的相关信息(类信息、常量、静态变量、方法数据等)。
  • 堆(Heap):存储Java对象,是垃圾回收器管理的区域。
  • 虚拟机栈(JVM Stack):每个线程都有一个栈,用来存储方法的局部变量、操作数栈、返回地址等信息。
  • 程序计数器(PC Register):存储当前线程正在执行的字节码的地址。
  • 本地方法栈(Native Method Stack):为JVM调用本地方法(如C/C++编写的库)提供支持。

2.2.1 程序计数器

线程私有;是一块较小的内存空间,可以看做是当前线程所执行的字节码的行号指示器,唯一不会造成 OutOfMemoryError 情况的区域。不过当线程执行的是 Native 方法的时候这个计数器中的值为 undefined 。

2.2.2 java虚拟机栈

线程私有;描述的是 java 方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。栈帧指执行一个方法所使用的那部分栈,线程的所有方法的栈帧串起来就组成了一个完整的 java 虚拟机栈。java 虚拟机栈针对线程而言,线程里的方法对应栈中的元素----栈帧;每执行一个方法,就为这个方法创建对应的栈帧,并 push 到 线程这个大容器-----java虚拟机栈 中,执行完成就 pop 出栈。

局部变量表存放了编译期可知的各种基本数据类型(boolean、byte、char、short、int、long、float、double)、对象引用(用来指向内存中分配的类实例或者数组) 和 returnAddress 类型(指向字节码的指针)。注:long和double会占用2个局部变量空间(8字节),其余数据类型只占用一个(4字节)。对于局部变量,如果是基本类型,会把值直接存储在栈;如果是引用类型,比如String s = new String("william");会把其对象存储在堆,而把这个对象的引用(指针)存储在栈。

Java虚拟机规范中,对这个区域规定了两种异常状况:

  • 线程请求栈的深度大于虚拟机所允许栈的深度,将抛出Stack Overflow Error
  • 如果虚拟机栈可以动态扩展且扩展时无法申请到足够的内存,会抛出OutOfMemoryError

这里注意的是如果递归的方法递归的太深很容易抛出上面两种异常,所以递归虽然写起来方便,但是性能会有所下降,并且容易抛出异常。

-Xss128k:设置每个线程的堆栈大小为128k,若不设置则为JVM默认值,此时默认可动态扩展。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。

2.2.3 本地方法栈

线程私有;作用和 java 虚拟机栈相似,区别是 java 虚拟机栈为虚拟机执行 java 方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的 Native 方法服务。Native方法指java调用非java代码(c++)的接口(jni)。

sayHello() 方法加了一个关键字 native ,就代表是一个native接口。执行这个方法时,会根据 jni.h来找到真正的C++编写的sayHello() 的实际函数。jni.h 是存在于 %JAVA_HOME%\include 下面的一个文件,另外还有个 %JAVA_HOME%\include\win32 下的jni_md.h。

2.2.4 java堆

线程共享;是java虚拟机所管理的内存中最大的一块,在虚拟机启动时创建,用于存放对象实例。java堆是垃圾收集器管理的主要区域。由于现在的垃圾回收算法多是分代收集,所以Java堆里面又可分为:新生代和老年代;再细致一点年轻代还能分为Eden区、From Survivor空间、To Survivor空间。并且根据Java虚拟机规范的规定:Java堆可以处于物理上不连续的内存空间中,只要逻辑上连续即可。注意:有实例没有被分配,且堆无法再扩展的时候会抛出OutOfMemoryError异常,虚拟机调优其实也主要关注的是这个区域。成员变量作为对象的属性,当然是放在堆里了。对象在堆里,对象中的内容就是各种字段。

  • -Xms:初始堆大小(最小堆)。
  • -Xmx:最大堆大小。

-Xms 和 -Xmx 设置成一致的值可以避免堆自动扩展。Oracle官方推荐堆的初始化大小与堆可设置的最大值一般是相等的,即 Xms = Xmx,因为起始堆内存太小(Xms),会导致启动初期频繁 GC,起始堆内存较大(Xmx)有助于减少 GC 次数

  • -Xmn:年轻代大小(Sun官方推荐配置为整个堆的1/3)。对 -XX:newSize、-XX:MaxnewSize两个参数的同时配置。

JVM内存大小 = 年轻代大小 + 老年代大小 + 永久代大小(perm)。永久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。

  • -XX:NewSize :指定新生代初始大小。
  • -XX:MaxNewSize :指定新生代最大大小。
  • -XX:NewRatio :是年老代 新生代相对的比例,比如NewRatio=2,表明年老代是新生代的2倍。老年代占了heap的2/3,新生代占了1/3。
  • -XX:SurvivorRatio :配置的是在新生代里面Eden和一个Survivor比例。-XX:SurvivorRatio=8表示新生代的Eden占8/10,S1和S2各占1/10.

2.2.5 方法区

线程共享;方法区是JVM的一种规范,方法区在jdk1.7的实现是永久代,jdk1.8的实现是元空间Metaspace。可以选择不实现垃圾收集。方法区主要用于存储类字节码、静态变量、常量池、即时编译器编译后的代码等数据。

对于方法区的理解我们要注意以下几个方面:

  • 方法区(Method Area)与堆一样,是各个线程共享的内存区域。
  • 方法区在JVM启动的时候被创建,并且它实际的物理内存空间和虚拟机堆区一样都可以是不连续的。
  • 方法区在JVM启动的时候被创建,并且它实际的物理内存空间和虚拟机堆区一样都可以是不连续的。
  • 方法区的大小跟堆空间一样,可以选择固定大小或者可扩展。方法区的大小决定了系统可以保存多少个类。如果系统定义了太多的类,导致方法区溢出,虚拟机同样会抛出内存溢出错误,如java.lang.OutOfMemoryError:PermGen space或者java.lang.OutOfMemoryError:Metaspace。

以下情况都可能导致方法区发生OOM异常:加载大量的第三方jar包、Tomcat部署的工程过多(30~50个)或者大量动态地生成反射类。

JVM常量池(详细见下一章):

  • class文件常量池:诞生于编译时,存在于class文件中,存放符号引用和字面量。
  • 运行时常量池:诞生于JVM运行时,jdk1.7永久代被移除后存在于元空间,存放class文件元信息描述、引用类型数据、编译后的代码数据、类文件常量池(综合了每个class文件常量池)
  • 字符串常量池:jdk1.6处于永久代,jdk1.7后处于堆区;存放字符串对象的引用
  • 基本类型包装类常量池:位于堆区
2.2.5.1 永久代

存储已被 java 虚拟机加载的类字节码、静态变量、常量池、即时编译器编译后的代码等数据。jdk1.7 的 HotSpot 虚拟机中,已经把原本放在永久代的 字符串常量池 和 静态变量 转移到 java 堆;符号引用(Symbols) 转移到了本地内存(Native Memory)。jdk1.8中,原有的永久代改为了元空间(Metaspace),直接使用机器物理内存,因为原来的永久代内存大小不易评估,同时调优效率较低。永久代的垃圾收集是和老年代捆绑在一起的。

配置参数:

-XX:PermSize=300M 设置永久代大小

-XX:MaxPermSize=300M 设置永久代最大大小

2.2.5.2 元空间(Metaspace)
存储类的元信息;存储位置不在虚拟机中,而是使用本地内存
-XX:MetaspaceSize ,初始空间大小,达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize时,适当提高该值。
-XX:MaxMetaspaceSize ,最大空间,默认是没有限制的。
  除了上面两个指定大小的选项以外,还有两个与 GC 相关的属性:
-XX:MinMetaspaceFreeRatio ,在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾收集。
-XX:MaxMetaspaceFreeRatio ,在GC之后,最大的Metaspace剩余空间容量的百分比,减少为释放空间所导致的垃圾收集。
永久代和元空间的区别
1) 存储位置不同:永久代物理上是堆的一部分,和老年代、新生代地址在逻辑上是连续的;元空间属于本地内存。
2) 存储内容不同:元空间存储类的元信息,静态变量和字符串常量池等并入堆中;相当于永久代的数据被分裂到了堆和元空间。
JDK 8 中永久代向元空间的转换原因
  • 1、字符串存在永久代中,容易出现性能问题和内存溢出。
  • 2、类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出。而对于元空间来说类的元数据可以在本地内存(native memory)分配,所以其最大可利用空间是整个系统内存的可用空间。
  • 永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。
  • Oracle 可能会将HotSpot 与 JRockit 合二为一。

相关文章:

【JVM详解一】类加载过程与内存区域划分

一、简介 1.1 概述 JVM是Java Virtual Machine&#xff08;Java虚拟机&#xff09;的缩写&#xff0c;是通过在实际的计算机上仿真模拟各种计算机功能来实现的。由一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域等组成。JVM屏蔽了与操作系统平台相关…...

《图解设计模式》笔记(五)一致性

十一、Composite模式&#xff1a;容器与内容的一致性 像文件夹与文件一样&#xff0c;文件夹中可以放子文件夹与文件&#xff0c;再比如容器中可以放更小的容器和具体内容。 Composite模式&#xff1a;使容器与内容具有一致性&#xff0c;创造出递归结构。 Composite&#x…...

burpsuite抓取html登陆和上传数据包

一、burpsuite抓取html登陆数据包 1、先写一个html格式的登陆页面 <!doctype html> <html lang="en"> <head><meta charset="UTF-8"><title>这是标签</title></head> <body> <hr><!-- 登陆表单…...

前端导出pdf,所见即所得

一、推荐方案&#xff1a;html2canvas jsPDF&#xff08;图片式PDF&#xff09; javascript import html2canvas from html2canvas; import jsPDF from jspdf;const exportPDF async (elementId, fileName) > {const element document.getElementById(elementId);// 1.…...

使用orjson库提升Python JSON处理性能

使用orjson库提升Python JSON处理性能 引言 在现代软件开发中&#xff0c;JSON&#xff08;JavaScript Object Notation&#xff09;作为一种轻量级的数据交换格式&#xff0c;广泛应用于Web服务、配置文件、数据存储等场景。Python作为一门流行的编程语言&#xff0c;提供了…...

TcpClientTest

ClientTest&#xff1a; using System; using System.Net.Sockets; using System.Text;class TcpClientTest {static void Main(string[] args){try{// 创建一个TcpClient实例并连接到服务器 TcpClient client new TcpClient("1vg5062570.51mypc.cn", 43319);//1v…...

【系统架构设计师】操作系统 ② ( 存储管理 | 页式存储 | 逻辑地址 与 物理地址 | 页表结构 | 物理内存淘汰机制 )

文章目录 一、页式存储1、CPU 调用数据2、内存存储数据弊端3、分页存储4、逻辑地址 和 物理地址 的结构5、逻辑地址 和 物理地址 的结构 示例6、页式存储 优缺点 二、逻辑地址 与 物理地址1、逻辑地址2、物理地址3、逻辑地址 与 物理地址 区别4、逻辑地址 与 物理地址 的转换 三…...

STM32自学记录(八)

STM32自学记录 文章目录 STM32自学记录前言一、ADC杂记二、实验1.学习视频2.复现代码 总结 前言 ADC 一、ADC杂记 ADC其实就是一个电压表&#xff0c;把引脚的电压值测出来&#xff0c;放在一个变量里。 ADC&#xff1a;模拟——数字转换器。 ADC可以将引脚上连续变化的模拟电…...

Vim 多窗口编辑及文件对比

水平分割 :split 默认使用水平分割的方式。 :split :sp 垂直分割 :vsplit :vs 带文件的分割 :split 文件名 :sp 文件名 在光标所在的窗口&#xff0c;输入分割窗口命令就会对那个窗口进行分割。 切换窗口 Ctrlw 切换正在编辑的窗口 快速分割窗口 Ctrlwn 快速分割当前…...

基于深度学习的人工智能量化衰老模型构建与全流程应用研究

一、引言 1.1 研究背景与意义 1.1.1 人口老龄化现状与挑战 人口老龄化是当今全球面临的重要社会趋势之一,其发展态势迅猛且影响深远。根据联合国的相关数据,1980 年,全球 65 岁及以上人口数量仅为 2.6 亿,到 2021 年,这一数字已翻番,达到 7.61 亿,而预计到 2050 年,…...

第八届大数据与应用统计国际学术研讨会(ISBDAS 2025)

重要信息 官网&#xff1a;www.is-bdas.org 时间&#xff1a;2025年2月28-3月2日 地点&#xff1a;中国 广州 主办单位&#xff1a;广东省高等教育学会人工智能与高等教育研究分会 协办单位&#xff1a;北京师范大学人工智能与未来网络研究院、人工智能与大数据科研基地 …...

链表专题-03

链表专题(三) 两数相加 问题 [力扣2] 2. 两数相加 - 力扣&#xff08;LeetCode&#xff09; 问题描述 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。请你将两个数相加&#xff…...

Ollama下载安装教程

一、去官网下载Ollama 点击前往Ollama官网 进去后点击下载 根据不同的系统去选择 由于服务器在国外可能下载界面进不去或者下载非常慢&#xff0c;可以去网盘获取 点击下方蓝色字体直达 点击前往夸克网盘下载 点击前往百度网盘下载 下载好后双击应用程序安装即可 点击ins…...

SQL Server查询计划操作符(7.3)——查询计划相关操作符(6)

7.3. 查询计划相关操作符 48)Key Lookup:该操作符对一个有簇索引的表进行书签查找。参数列包含簇索引的名字和用于查找簇索引中数据行的簇键。该操作符总是伴随一个Nested Loops操作符。如果其参数列中出现WITH PREFETCH子句,则查询处理器已决定使用异步预取(预读,read-ah…...

IDEA查看项目依赖包及其版本

一.IDEA将现有项目转换为Maven项目 在IntelliJ IDEA中,将现有项目转换为Maven项目是一个常见的需求,可以通过几种不同的方法来实现。Maven是一个强大的构建工具,它可以帮助自动化项目的构建过程,管理依赖关系,以及其他许多方面。 添加Maven支持 如果你的项目还没有pom.xm…...

网络分析工具—WireShark的安装及使用

Wireshark 是一个广泛使用的网络协议分析工具&#xff0c;常被网络管理员、开发人员和安全专家用来捕获和分析网络数据包。它支持多种网络协议&#xff0c;能够帮助用户深入理解网络流量、诊断网络问题以及进行安全分析。 Wireshark 的主要功能 数据包捕获与分析&#xff1a; …...

【LeetCode 刷题】贪心算法(2)-进阶

此博客为《代码随想录》贪心算法章节的学习笔记&#xff0c;主要内容为贪心算法进阶的相关题目解析。 文章目录 135. 分发糖果406. 根据身高重建队列134. 加油站968. 监控二叉树 135. 分发糖果 题目链接 class Solution:def candy(self, ratings: List[int]) -> int:n l…...

网络工程师 (25)OSI模型—服务访问点

前言 OSI模型&#xff0c;即开放式通信系统互联参考模型&#xff08;Open System Interconnection Reference Model&#xff09;&#xff0c;是国际标准化组织&#xff08;ISO&#xff09;提出的一个旨在使各种计算机在世界范围内互连为网络的标准框架。 一、定义 服务访问点&a…...

如何在RTACAR中配置IP多播(IP Multicast)

一、什么是IP多播 IP多播&#xff08;IP Multicast&#xff09;是一种允许数据包从单一源地址发送到多个目标地址的技术&#xff0c;是一种高效的数据传输方式。 多播地址是专门用于多播通信的IP地址&#xff0c;范围从 224.0.0.0到239.255.255.255 与单播IP地址不同&#x…...

使用docker搭建FastDFS文件服务

1.拉取镜像 docker pull registry.cn-hangzhou.aliyuncs.com/qiluo-images/fastdfs:latest2.使用docker镜像构建tracker容器&#xff08;跟踪服务器&#xff0c;起到调度的作用&#xff09; docker run -dti --networkhost --name tracker -v /data/fdfs/tracker:/var/fdfs -…...

VC播放mp3的方法

1、使用msi库 #include <mmsystem.h> #pragma comment(lib,"winmm.lib") .......//打开文件MCI_OPEN_PARMS mciOpen; mciOpen.lpstrDeviceType _T("mpegvideo"); mciOpen.lpstrElementName _T("c://1.mp3"); MCIERROR mciError mci…...

【读书笔记·VLSI电路设计方法解密】问题46:什么是bug覆盖率

在IC设计项目的验证过程中&#xff0c;功能测试&#xff08;通过使用测试平台&#xff09;有助于定位设计错误或漏洞。这个验证过程有三个阶段&#xff1a;构建和启动测试平台、验证基本测试用例以及验证边界情况。 在前两个阶段&#xff0c;漏洞很容易被检测到&#xff0c;因…...

sqli-lab靶场学习(五)——Less15-17(post方法盲注、修改密码)

前言 第11-14关开始用post方法&#xff0c;15-17关会用到盲注&#xff0c;post方法盲注和get方法类似。 Less15 这关是单引号闭合&#xff0c;有报错但没有具体情况的回显&#xff0c;因此适合使用错误盲注。 在用户名密码框分别输入 账号&#xff1a;admin and 11 -- asd…...

1、http介绍

一、HTTP 和 HTTPS 简介 HTTP&#xff08;HyperText Transfer Protocol&#xff09; 用途&#xff1a;用于网页数据传输&#xff08;不加密&#xff09;。协议特性&#xff1a;以明文形式传输数据&#xff0c;默认端口 80&#xff0c;无身份验证和完整性保护。典型场景&#xf…...

Vim跳转文件及文件行结束符EOL

跳转文件 gf 从当前窗口打开那个文件的内容&#xff0c;操作方式&#xff1a;让光标停在文件名上&#xff0c;输入gf。 Ctrlo 从打开的文件返回之前的窗口 Ctrlwf 可以在分割的窗口打开跳转的文件&#xff0c;不过在我的实验不是次次都成功。 统一行尾格式 文本文件里存放的…...

LLM:DeepSeek 系列(二)

原文链接 3、DeepSeek-V2 DeepSeek-V2 发布于 2024 年 5 月&#xff0c;为多领域专家&#xff08;MoE&#xff09;语言模型&#xff0c;包含总共 2360 亿个参数&#xff0c;其中每个词元激活 210 亿个参数&#xff0c;并支持 12.8 万个词元的上下文长度。DeepSeek-V2 采用包括…...

订单超时设计(1)--- 如何使用redis实现订单超时实时关闭功能

如何使用redis实现订单超时实时关闭功能 准备工作实现步骤解释注意事项&#xff08;重点&#xff09; 使用Redis实现订单超时实时关闭功能&#xff0c;可以利用Redis的延时队列&#xff08;使用Sorted Set实现&#xff09;和过期键&#xff08;使用TTL和Keyspace Notifications…...

【0401】Postgres内核 CREATE DATABASE database-name 源码实现 ①

文章目录 1. CREATE DATABASE 语句1.1 CREATE DATABASE 语法1.2 CREATE DATABASE 调用栈2. CREATE DATABASE 内核实现2.1 从 CreatedbStmt 节点树 提取 options2.2 获取 datdba(proposed owner) OID2.3 当前用户具有 create DB 权限?2.4 获取 database template1. CREATE DA…...

Termux安装ssh实现电脑ssh

Termux下载 点击下载 在 Termux 中安装并使用 SSH&#xff0c;按照以下步骤操作&#xff1a; 1. 更新软件包列表 pkg update && pkg upgrade2. 安装 OpenSSH pkg install openssh3. 设置 SSH 密码&#xff08;必须&#xff0c;否则无法使用 SSH 服务器&#xff09…...

nexus部署及配置https访问

1. 使用docker-compose部署nexus docker-compose-nexus.yml version: "3" services:nexus:container_name: my-nexusimage: sonatype/nexus3:3.67.1hostname: my-nexusnetwork_mode: hostports:- 8081:8081deploy:resources:limits:cpus: 4memory: 8192Mreservations…...

【MySQL】表操作

表操作 一、创建表 1、语句2、语句介绍3、注意事项4、介绍5、示例 二、查看表结构 1、语句2、介绍3、返回的信息4、示例 三、添加字段 1、语句2、语句介绍3、示例 四、修改 1、语句2、语句介绍3、示例 五、删除 1、语句2、示例 六、修改表名 1、语句2、语句介绍3、示例 七、删…...

浅析Ruby类污染及其在Sinatra框架下的利用

和JavaScript中的原型链污染类似&#xff0c;Ruby中也存在类似的概念——类污染&#xff0c;两者都是对象进行不安全的递归合并导致的。 网上也没有相关的分析文章&#xff0c;只有下面这篇文章应该是第一次谈到这个问题 Class Pollution in Ruby: A Deep Dive into Exploiti…...

iPhone 在华销量大幅下挫

iPhone在乔布斯时代缔造的神话在中国正逐渐走向没落&#xff0c;挤牙膏式的升级方式类似于诺基亚的N70系列&#xff0c;毫无新意的创新能力&#xff0c;求稳着陆的经营理念&#xff0c;工艺和美学不再独领风骚&#xff0c;甚至拍照领域和AI增强计算&#xff0c;折叠屏等技术领域…...

Fedora 的 2025 年展望:AI 集成与 HDR 支持打造强大 Linux 桌面体验

Fedora 项目已经从节庆活动中恢复&#xff0c;准备在未来几个月推出一系列关键计划。Red Hat 软件工程总监 Christian Schaller 在他的博客文章中分享了 2025 年 Fedora 发行版的重点发展方向和优先事项&#xff0c;涵盖了人工智能集成、Wayland、HDR 协议、PipeWire 等多个领域…...

mysql 学习11 事务,事务简介,事务操作,事务四大特性,并发事务问题,事务隔离级别

一 事务简介&#xff0c; 数据库准备&#xff1a; create table account(id int auto_increment primary key comment 主键ID,name varchar(128) not null comment 姓名,backaccountnumber char(18) unique comment 银行账号,money float comment 余额 )comment 银行账号表;…...

C# Winform怎么设计串口,客户端和相机控件界面显示

首先我们必须把这个类创建好 INIAPI using System; using System.Text; using System.Runtime.InteropServices;namespace Ini {public class IniAPI{#region INI文件操作/** 针对INI文件的API操作方法&#xff0c;其中的节点&#xff08;Section)、键&#xff08;KEY&#x…...

【场景题】架构优化 - 解耦Redis缓存与业务逻辑

1. 需求分析 某公司需要将原有的Redis缓存抽离出来&#xff0c;并且还要要实现&#xff1a; 可配置热拔插高可用高通用 请问你会如何实现&#xff1f; 2. 思路 话不多说直接上思路&#xff1a; 自定义缓存注解&#xff0c;当容器扫描到该注解自动调用AOP想应的增强方法为…...

WGCLOUD监控系统部署教程

官网地址&#xff1a;下载WGCLOUD安装包 - WGCLOUD官网 第一步、环境配置 #安装jdk 1、安装 EPEL 仓库&#xff1a; sudo yum install -y epel-release 2、安装 OpenJDK 11&#xff1a; sudo yum install java-11-openjdk-devel 3、如果成功&#xff0c;你可以通过运行 java …...

linux——网络计算机{序列化及反序列化(JSON)(ifdef的用法)}

linux——网络&#xff08;服务器的永久不挂——守护进程&#xff09;-CSDN博客 目录 一、序列化与反序列化 1. 推荐 JSON 库 2. 使用 nlohmann/json 示例 安装方法 基础用法 输出结果 3. 常见操作 4. 其他库对比 5. 选择建议 二、ifdef宏的用法 基本语法 核心用途…...

Android 开发APP中参数配置与读取总结

以使用MQTT配置的参数 MQTT_BROKER_UR 、MQTT_USER_NAME、 MQTT_PASSWORD为例&#xff0c;说明配置设置和读取应用 项目中使用系统参数&#xff08;如环境变量和gradle.properties文件中的属性&#xff09;在Gradle构建脚本中&#xff0c;以下是一个详细的操作文档资料&…...

Web应用国际化(i18n)实现详解 python

Web应用国际化&#xff08;i18n&#xff09;实现详解 1. 设计理念 本项目的国际化&#xff08;Internationalization&#xff09;解决方案基于Python的gettext模块&#xff0c;提供了一个灵活、可扩展的多语言支持系统。 2. 语言支持 2.1 支持的语言列表 项目支持超过35种…...

mysql mvcc 锁 关系

多版本并发控制&#xff08;MVCC&#xff09;是一种用于数据库并发控制的机制&#xff0c;它可以在保证数据一致性的同时&#xff0c;提高数据库的并发性能。下面结合 MVCC 机制&#xff0c;详细阐述常见的四种事务隔离级别&#xff08;读未提交、读已提交、可重复读、串行化&a…...

【银河麒麟高级服务器操作系统】系统日志Call trace现象分析及处理全流程

了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer.kylinos.cn 文档中心&#xff1a;https://document.kylinos.cn 服务器环境以及配置 系统环境 物理机/虚拟机/云…...

新能源产业的质量革命:六西格玛培训如何重塑制造竞争力

在新能源行业狂飙突进的今天&#xff0c;企业若想在全球供应链中占据高地&#xff0c;仅靠技术突破已远远不够。制造效率的毫厘之差&#xff0c;可能成为市场话语权的千里之距。某光伏巨头曾因电池片良率低于行业均值1.5%&#xff0c;导致年损失超2.3亿元——这恰恰印证了六西格…...

【ArcGIS】R语言空间分析、模拟预测与可视化技术

R语言在空间数据挖掘中具有广泛的应用&#xff0c;以下是一些关键内容和常用包的介绍&#xff1a; R语言空间数据挖掘的关键技术 空间数据类型 矢量数据&#xff1a;包括点&#xff08;Point&#xff09;、线&#xff08;Line&#xff09;、面&#xff08;Polygon&#xff09;等…...

单例模式几种实现

静态内部类holder实现&#xff08;推荐&#xff09; public class UniqueIdGenerator {public static final UniqueIdGenerator INSTANCE Holder.INSTANCE;// Private holder class for lazy initializationprivate static class Holder {static final UniqueIdGenerator INS…...

什么是Prompt工程?

什么是提示工程&#xff1f; Prompt一词&#xff0c;在英语中主要用作动词、形容词、名词和副词&#xff0c;主要意思包括“促使&#xff0c;导致&#xff1b;鼓励&#xff0c;提示&#xff1b;迅速的&#xff0c;立刻的&#xff1b;准时地”等。 在人工智能的语境下&#xf…...

C++,设计模式,【单例模式】

文章目录 一、模式定义与核心价值二、模式结构解析三、关键实现技术演进1. 基础版(非线程安全)2. 线程安全版(双重检查锁)3. 现代C++实现(C++11起)四、实战案例:全局日志管理器五、模式优缺点深度分析✅ 核心优势⚠️ 潜在缺陷六、典型应用场景七、高级实现技巧1. 模板化…...

详解SQLAlchemy的函数relationship

在 SQLAlchemy 中&#xff0c;relationship 是一个非常重要的函数&#xff0c;用于定义模型之间的关系。它用于在 ORM 层面上表示数据库表之间的关联关系&#xff08;如 1 对 1、1 对多和多对多&#xff09;。relationship 的主要作用是提供一个高级接口&#xff0c;用于在模型…...

vue 的 watch 和 computed 有什么区别?

在 Vue.js 中,watch 和 computed 都是用于响应式数据处理的功能,但它们有不同的用途和实现方式。以下是二者的主要区别: 1. 用途 computed 计算属性:用于基于已有数据计算出新的值。它们是基于依赖的数据变化而自动重新计算的,通常用于模板中显示的派生状态。缓存:计算…...