JVM相关-JVM模型、垃圾回收、JVM调优

news2024/11/15 19:54:06

一、JVM模型

JVM内部体型划分

模型图

JVM的内部体系结构分为三部分,分别是:类加载器(ClassLoader)子系统、运行时数据区(内存)和执行引擎

1、类加载器
概念

每个JVM都有一个类加载器子系统(class loader subsystem),JVM的类加载器包括:用户自定义类加载器、应用类加载器、拓展类加载器、启动类加载器

  • 启动类加载器(BootstrapClassLoader)

    非java语言实现
    作用:加载指定路径中jar里面的class文件
    路径1:java安装目录\jre\lib
    路径2:java安装目录\jre\classes
    例如:rt.jar

  • 扩展类加载器(ExtClassLoader)

    java语言实现,是ClassLoader类型的对象
    作用:加载指定路径中jar里面的class文件( 只能是jar中存在的class)
    路径:java安装目录\jre\lib\ext
    例如:ext中默认存在的jar,或者用户放到ext目录下的jar包

  • 应用类加载器 (AppClassLoader)

    java语言实现,是ClassLoader类型的对象
    作用:加载指定路径中class文件或者jar里面的class文件
    路径:CLASSPATH中配置路径,这个是用户自己配置的
    例如:.:bin:hello.jar

JVM的类加载机制

  • 全盘负责

    所谓全盘负责,就是当一个类加载器负责加载某个Class时,该Class所依赖和引用其他Class也将由该类加载器负责载入,除非显示使用另外一个类加载器来载入

  • 双亲委派

    image
    双亲委派机制(如上图),当一个Hello.class这样的文件要被加载时。不考虑我们自定义类加载器,首先会在应用类加载器(如果存在用户自定义类加载器则从用户自定义类加载器开始)中检查是否加载过,如果有就无需再加载。如果没有,那么会拿到父加载器,然后调用父加载器的loadClass方法。父类中同理也会先检查自己是否已经加载过,如果没有再往上。这个类似递归的过程,直到到达启动类加载器之前,都是在检查是否加载过,并不会选择自己去加载。直到启动类加载器,已经没有父加载器了,这时候开始考虑自己是否能加载了,如果自己无法加载,会下沉到子加载器去加载,一直到最底层,如果没有任何加载器能加载,就会抛出ClassNotFoundException异常

    双亲委派机制的优势

    采用双亲委派模式的是好处是Java类随着它的类加载器一起具备了一种带有优先级的层次关系,通过这种层级关可以避免类的重复加载,当父亲已经加载了该类时,就没有必要子ClassLoader再加载一次。其次是考虑到安全因素,java核心api中定义类型不会被随意替换,假设通过网络传递一个名为java.lang.Integer的类,通过双亲委托模式传递到启动类加载器,而启动类加载器在核心Java API发现这个名字的类,发现该类已被加载,并不会重新加载网络传递的过来的java.lang.Integer,而直接返回已加载过的Integer.class,这样便可以防止核心API库被随意篡改

  • 缓存机制

    缓存机制将会保证所有加载过的Class都会被缓存,当程序中需要使用某个Class时,类加载器先从缓存区中搜寻该Class,只有当缓存区中不存在该Class对象时,系统才会读取该类对应的二进制数据,并将其转换成Class对象,存入缓冲区中。这就是为很么修改了Class后,必须重新启动JVM,程序所做的修改才会生效的原因

作用

java中的类,想要运行就必须把类对应的class文件加载到内存,JVM中真正负责加载class文件内容的是类加载器

负责将Java字节码文件(class文件)加载进JVM内存(运行时数据区)

2、 执行引擎
概念

每一个Java虚拟机都有一个执行引擎(execution engine)

作用

负责执行被加载类中包含的指令

3、 运行时数据区

JVM内存模型

运行时数据区又可以分为两大部分:

1、线程共享(堆区、方法区)

2、线程私有(程序计数器、Java虚拟机栈、本地方法栈)

3.1 程序计数器
  • 概念

    程序计数器就是记录当前线程执行程序的位置,通过改变计数器的值来确定执行的下一条指令,比如循环、分支、方法跳转、异常处理,线程恢复都是依赖程序计数器来完成

    Java虚拟机多线程是交替运行的。为了线程切换能恢复到正确的位置,每条线程都需要一个独立的程序计数器,所以它是线程私有的

    如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Native方法,这个计数器值则为空(Undefined)。此内存区域是唯一一个在Java虚拟机中没有内存溢出情况的区域

  • 作用

    存储指向下一条指令的地址。由于Java虚拟机多线程是根据时间片交替运行的,使用程序计数器可以使线程切换能恢复到正确的位置

3.2 Java虚拟机栈
  • 概念

    Java虚拟机栈是线程私有,生命周期与线程相同。创建线程的时候就会创建一个java虚拟机栈

    虚拟机执行java程序的时候,每个方法都会创建一个栈帧,栈帧存放在java虚拟机栈中,通过压栈出栈的方式进行方法调用

    栈帧又分为一下几个区域:局部变量表、操作数栈、动态连接、方法返回地址等

    平时我们所说的变量存在栈中,这句话说的不太严谨,应该说局部变量存放在java虚拟机栈的局部变量表中

    Java的8中基本类型的局部变量的值存放在虚拟机栈的局部变量表中,如果是引用型的变量,则只存储对象的引用地址

  • 作用

    实现方法的调用

3.3 本地方法栈

本地方法:native关键字修饰,非java语言实现的方法。例如,java调用C语言,来操作某些硬件信息

本地方法栈为虚拟机使用到本地方法服务(native)。本地方法栈为线程私有,功能和虚拟机栈非常类似。线程在调用本地方法时,来存储本地方法的局部变量表,本地方法的操作数栈等信息

3.4 堆区

image-20211017144759455

堆是被所有线程共享的区域,在虚拟机启动时创建。堆里面存放的都是对象的实例(new 出来的对象都存在堆中)

我们平常所说的垃圾回收,主要回收的区域就是堆区

为了提升垃圾回收的性能,又对堆进行了新生代和年老代(比例1:2),根据不同对象生命周期的不同,存放在不同代中,使用不同的垃圾回收算法进行回收,效率更高

老年代的特点是每次垃圾收集时只有少量对象需要被回收,而新生代的特点是每次垃圾回收时都有大量的对象需要被回收,那么就可以根据不同代的特点采取最适合的收集算法。

目前大部分垃圾收集器对于新生代都采取复制算法,因为新生代中每次垃圾回收都要回收大部分对象,也就是说需要复制的操作次数较少,但是实际中并不是按照1:1的比例来划分新生代的空间的,一般来说是将新生代划分为一块较大的Eden空间和两块较小的Survivor空间(8:1:1),每次使用Eden空间和其中的一块Survivor空间,当进行回收时,将Eden和Survivor中还存活的对象复制到另一块Survivor空间中,然后清理掉Eden和刚才使用过的Survivor空间

最新的创建的对象存放到Eden区,随着项目的运行,当对象占满Eden区,就会触发GC,执行引擎开启一个GC垃圾回收线程,利用可达性分析算法标记非垃圾对象,垃圾对象会被回收,非垃圾对象移动到Survior区,年龄+1(经历过一次垃圾回收没有被收集年龄+1),此时年经代使用的是复制算法进行垃圾回收。当对象的年龄达到15,会从Survivor区移动到老年代

而由于老年代的特点是每次回收都只回收少量对象,一般使用的是标记-整理算法(压缩法)

stw(stop the world)停止事件(用户线程暂停,专注垃圾回收),当Eden区堆满会触发Minior gc或young gc,当老年代堆满会触发Full gc,young gc 和 full gc都会引发stw,但是full gc引发的stw时间会比较长

3.5 方法区

img

方法区是被所有线程共享区域,用于存放已被虚拟机加载的类信息、常量、静态变量等数据。被Java虚拟机描述为堆的一个逻辑部分。习惯是也叫它永久代(permanment generation)

永久代也会垃圾回收,主要针对常量池回收,类型卸载(比如反射生成大量的临时使用的Class等信息)。

常量池用于存放编译期生成的各种字节码和符号引用,常量池具有一定的动态性,里面可以存放编译期生成的常量;运行期间的常量也可以添加进入常量池中,比如string的intern()方法

当方法区满时,无法在分配空间,就会抛出内存溢出的异常(OutOfMemoneyError)

Java8中已经没有方法区了,取而代之的是元空间(Metaspace)

4、 拓展理解
4.1 一个普通java程序的运行过程
  1. javac 将java源代码编译成class文件
  2. java 命令将class文件加载进JVM
  3. 类加载将class文件加载进方法区
  4. 此时初始化静态成员方法以及执行静态方法(先父后子,main方法本就是静态方法)
  5. 创建main线程
  6. 将main方法加载进java虚拟机栈
  7. 执行main方法中的代码
  8. 输出结果
4.2 各变量在内存中的位置
  • 成员变量

    作为对象的一部分存储在堆区中

  • 局部变量

    作为方法的一部分存放在栈区中。执行方法时,方法压栈;方法执行完毕,方法弹栈,局部变量也会消除

  • 静态变量

    方法区中

4.3 简单类执行过程

示例代码

class Student{
    private static country = "CN";
    private String name;
    private int age;
    public static void printlnCountry(){
        System.out.println(country);
    }
    public void showValue(){
        System.out.println(this.name);
        System.out.println(this.age);
    }
    public Student(String name, int age){
        this.String = name;
        this.age = age;
    }
}
public class Test{
    public static void main(String[] args){
        Student student = new Student("张三"20);
        student.showValue();
        Student.printlnCountry();
    }
}

上述类的执行过程:

  1. 首先Test类的字节码文件加载进方法区

  2. Test静态方法区加载执行Test类的的静态变量、静态方法、main方法

  3. main方法进栈

  4. 执行到 Student student = new Student(“张三”,20);

    1. Student.class被加载进方法区

    2. Student静态方法区加载执行Student类的静态变量、静态方法

    3. 在堆区开辟一个Student对象的空间,并赋予成员变量默认值,name = null;age = 0; 返回一个内存地址 9988#。成员变量赋值、匿名代码块、构造方法(如果存在则按此顺序执行)

    4. 构造方法 Student(String name, int age)压栈,this指向内存地址9988#,执行方法,弹栈

    5. 初始化堆区中的Student对象,为其赋值,name = “张三”;age = 20;

    6. =赋值操作,将内存地址9988#指向student变量

  5. showValue()方法压栈,this指向内存地址9988#,执行方法,弹栈

  6. Student类的静态方法区的printlnCountry()方法压栈,执行方法,弹栈

  7. main方法弹栈

  8. 等待JVM GC回收Student对象

二、JVM垃圾回收

举例:在食堂里吃饭,吃完把餐盘端走清理的,是 C++ 程序员;吃完直接就走的,是 Java 程序员。

相关概念
  • 内存泄漏(Memory Leak)

    使用完的对象不能及时回收

  • 内存溢出(Out of Memory)

    程序申请内存时没有足够的内存供程序使用,内存泄漏的堆积会造成内存溢出

对象回收判断
  • 引用计数法

    每一个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0的时候可以回收

  • 可达性分析

    从GcRoots开始向下搜索对象,搜索所走过的路径被称为引用链,当一个对象到GcRoots没有任何引用链相连时,则证明此对象是可回收的

    可以作为GcRoots的对象有:

    1. 虚拟机栈中引用的对象
    2. 本地方法栈中(即一般说的native方法)引用的对象
    3. 方法区中静态属性引用的对象。
    4. 方法区中常量引用的对象

    可达性算法中的不可达对象并不是立即死亡的,对象拥有一次自我拯救的机会,对象被系统宣告死亡至少要经历两次标记过程,第一次是经过可达性分析发现没有与GcRoots 相连接的引用链,第二次是对象执行finalize()方法后(收尾工作)即可被回收

    当对象变成GcRoot不可达时,Gc会判断该对象是否覆盖了finalize方法,若未覆盖,则直接回收,否则,若对象未执行过finalize方法,将其放入F-Queue队列,由一低优先级线程执行该队列中对象的finalize方法

常见的垃圾回收算法
  • 标记-清除算法(Mark-Sweep)

    分为两个阶段:标记阶段和清除阶段。标记阶段的任务是通过可达性分析标记出所有需要被回收的对象,清除阶段就是回收被标记的对象所占用的空间

    从图中可以很容易看出标记-清除算法实现起来比较容易,但是有一个比较严重的问题就是容易产生内存碎片(就是导致可用内存不连续,零零散散的),碎片太多可能会导致后续过程中需要为大对象分配空间时无法找到足够的空间而提前触发新的一次垃圾收集动作

    img

  • 复制算法

    1969年Fenichel提出了一种称为“半区复制”(Semispace Copying)的垃圾收集算法,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉,这样一来就不容易出现内存碎片的问题,但是存在空间浪费的问题。具体过程如下图所示

    img

  • 标记-整理算法(标记-整理-清除)

    为了解决Copying算法的缺陷,充分利用内存空间,提出了Mark-Compact算法。该算法标记阶段和Mark-Sweep一样,在通过可达性分析标记出可以被回收的对象,然后将存活对象都向一端移动,然后清理掉端边界以外的内存(效率不高)。(在标记清除的基础上对可利用内存进行整理)具体过程如下图所示:
    img

  • 分代收集算法

    分代收集算法是目前大部分JVM的垃圾收集器采用的算法。它的核心思想是根据对象存活的生命周期将内存划分为若干个不同的区域。一般情况下将堆区划分为老年代(Tenured Generation)和新生代(Young Generation),老年代的特点是每次垃圾收集时只有少量对象需要被回收,而新生代的特点是每次垃圾回收时都有大量的对象需要被回收,那么就可以根据不同代的特点采取最适合的收集算法。目前主流的分代垃圾回收算法是新生代使用复制算法,老年代使用标记-整理算法

典型的垃圾回收器
  • Serial/Serial Old收集器

    最基本最古老的收集器,它是一个单线程串行收集器,并且在它进行垃圾收集时,必须暂停所有用户线程。Serial收集器是针对新生代的收集器,采用的是Copying算法,Serial Old收集器是针对老年代的收集器,采用的是Mark-Compact算法。它的优点是实现简单高效,但是缺点是会给用户带来停顿

  • ParNew收集器

    Serial收集器的多线程版本,即多线程串行化收集器,使用多个线程进行垃圾收集

  • Parallel Scavenge收集器

    一个新生代的多线程收集器(并行收集器),它在回收期间不需要暂停其他用户线程,其采用的是Copying算法,该收集器与前两个收集器有所不同,它主要是为了达到一个可控的吞吐量,吞吐率(代码运行时间/代码运行时间+垃圾收集时间)优先,代码运行的时间更多

  • Parallel Old收集器

    Parallel Scavenge收集器的老年代版本(并行收集器),使用多线程和Mark-Compact算法。

  • CMS(Concurrent Mark Sweep)收集器

    一种以获取最短回收停顿时间为目标的收集器,它是一种并发收集器,采用的是Mark-Sweep算法

    执行阶段:

    1. 初始标记:可达性分析标记,会引发stw停止事件(停止用户线程)
    2. 并发标记:可以和用户线程并发执行
    3. 重新标记:重新标记,会引发stw停止事件
    4. 并发清除:可以与用户线程并发执行,不会引发stw停止事件
  • G1收集器

    当今收集器技术发展最前沿的成果,它是一款面向服务端应用的收集器,它能充分利用多CPU、多核环境。因此它是一款并行与并发收集器,并且它能建立可预测的停顿时间模型

三、JVM调优

何为性能调优?
  1. 根据项目需求对JVM规划和预调优
  2. 优化运行程序中JVM导致的卡顿
  3. 解决JVM运行中的各种问题
JVM调优参数
-Xms  设置 JVM堆内存初始空间大小,如-Xms2g
-Xmx  设置 JVM堆内存最大空间大小,如-Xmx2g
-Xmn  设置 JVM新生代空间大小,-Xmn1g
-XX:+UseG1GC  使用G1垃圾回收器
-XX:SurvivorRatio=8  设置survivor与eden的比例(1:8)
-XX:NewRatio=4  设置新生代和老年代的比例(1:4)
排查线上OOM
  • 产生OOM的原因

    1. 一次性申请的对象太多

      解决思路:更改申请对象的数量

    2. 内存资源耗尽未释放

      解决思路:找到未释放的对象进行释放

    3. 本身内存资源不够

      解决思路:使用命令jmap -heap [pid] 查看堆内存信息

      可以通过jps(JavaVirtualMachine Process Status JVM进程状态)查看java进程id

      示例:

      [root@iZ7xvjebghrlinlgmirqudZ ~]# jmap -heap 669
      Attaching to process ID 669, please wait...
      Debugger attached successfully.
      Server compiler detected.
      JVM version is 25.74-b02
      
      using thread-local object allocation.
      Mark Sweep Compact GC
      
      Heap Configuration:
         MinHeapFreeRatio         = 40 #最小堆使用比例
         MaxHeapFreeRatio         = 70 #最大堆可用比例
         MaxHeapSize              = 1073741824 (1024.0MB) #最大堆空间大小
         NewSize                  = 89456640 (85.3125MB)  #新生代分配大小
         MaxNewSize               = 357892096 (341.3125MB) #最大新生代可分配大小
         OldSize                  = 178978816 (170.6875MB) #老年代分配大小
         NewRatio                 = 2 #survivor区与eden区比例(survivor)
         SurvivorRatio            = 8 #survivor区与eden区比例(eden)
         MetaspaceSize            = 21807104 (20.796875MB) #元空间(方法区)大小
         CompressedClassSpaceSize = 1073741824 (1024.0MB) 
         MaxMetaspaceSize         = 17592186044415 MB #最大元空间大小
         G1HeapRegionSize         = 0 (0.0MB) #G1单个Region大小
      
      Heap Usage: #堆使用情况
      New Generation (Eden + 1 Survivor Space): #新生代
         capacity = 80609280 (76.875MB) #总容量
         used     = 65509680 (62.47489929199219MB) #已使用
         free     = 15099600 (14.400100708007812MB) #剩余容量
         81.26816168064025% used #使用占比
      Eden Space: #eden区
         capacity = 71696384 (68.375MB)
         used     = 61261624 (58.42363739013672MB)
         free     = 10434760 (9.951362609863281MB)
         85.44590477533707% used
      From Space: #from survivor
         capacity = 8912896 (8.5MB)
         used     = 4248056 (4.051261901855469MB)
         free     = 4664840 (4.448738098144531MB)
         47.661904727711395% used
      To Space: #to survivor
         capacity = 8912896 (8.5MB)
         used     = 0 (0.0MB)
         free     = 8912896 (8.5MB)
         0.0% used
      tenured generation: #老年代
         capacity = 178978816 (170.6875MB)
         used     = 41792568 (39.85649871826172MB)
         free     = 137186248 (130.83100128173828MB)
         23.350566806744325% used
      
      30639 interned Strings occupying 3078128 bytes.
      

      另外,可以通过命令jmap -histo:live [pid] | more 查看JVM运行时最耗费资源的对象

  • 如何定位以及解决办法

    1. 系统已经发生OOM到导致宕机了

      提前设置内存溢出记录

      Dump 文件是 Java 进程的内存镜像,其中主要包括 系统信息、虚拟机属性、完整的线程 Dump、所有类和对象的状态 等信息

      java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/temp/xxx.hprof -jar xxx.jar
      
      #JVM运行时导出Dump
      jmap -dump:file=[文件路径] [pid]
      

      当内存溢出发生时可以根据生成的dump文件进行分析,快速定位问题所在

    2. 导出dump文件(JVM内存快照)

      jamp -dump:file=[文件路径] [pid]

      可能造成一次fullGC和一次STW

      将导出的hhprof类型文件导入jvisualvm(java自带,在jdk的bin目录下)

    3. 结合jvisualvm进行调试

      查看最多跟业务有关对象->找对GCRoot->查看线程栈。根据所得信息对代码进行优化

以上内容收集整理于网络,如有疏漏和错误的地方,欢迎指正~

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

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

相关文章

C语言的malloc(0)问题

malloc(0)详解 首先来解释malloc(0)的问题,这个语法是对的,而且确实也分配了内存,但是内存空间是0,就是说返回给你的指针是不能用的,感觉奇怪吧?但是从操作系统的原理来解释就不奇怪…

(c语言版)开源项目热榜,某个开源社区希望将最近热度比较高的开源项目出一个榜单,推荐给社区里面的开发者。对于每个开源项目

某个开源社区希望将最近热度比较高的开源项目出一个榜单,推荐给社区里面的开发者。对于每个开源项目,开发者可以进行关注(watch)、收藏(star)、fork、提issue、提交合并请求(MR)等。 数据库里面统计了每个开源项目关注、收藏、fork、issue、MR的数量&…

3. ⼤语⾔模型深度学习背景知识

1. LLM⼤语⾔模型⼀般训练过程 #mermaid-svg-8kci1fjEPiVolPue {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-8kci1fjEPiVolPue .error-icon{fill:#552222;}#mermaid-svg-8kci1fjEPiVolPue .error-text{fill:#5522…

前端实现标题滚动点击导航

效果图 右边滚动的html代码 <div class"right-box"><el-tabs v-model"isScrollNow" tab-position"right" class"updateTab" tab-click"scrollTo"style"height: fit-content;"><el-tab-pane label…

怎么把视频音乐提取成mp3?分享详细工具和方法!

在数字媒体时代&#xff0c;音乐已经成为我们生活中不可或缺的一部分。有时候&#xff0c;我们会在社交媒体、视频分享网站或在线视频平台上看到一些非常喜欢的视频音乐&#xff0c;想要将其保存为MP3格式以便随时随地聆听。那么&#xff0c;如何从视频中提取音乐并转换为MP3格…

Python操作Word表格对齐、单元格对齐

通过Table的alignment可以设置表格居左对齐、居中对齐、居右对齐。通过Cell的vertical_alignment可以设置垂直位置。通过单元格里段落的alignment可以设置文本的左右对齐方式。 import docx from docx.enum.table import WD_TABLE_ALIGNMENT, WD_CELL_VERTICAL_ALIGNMENT from…

@Repository注解的作用和用法,以及和@Mapper的区别

1、Repository的作用 Repository是属于Spring的注解。它用来标注访问层的类&#xff08;Dao层&#xff09;&#xff0c;它表示一个仓库&#xff0c;主要用于封装对于数据库的访问。其实现方式与Component注解相同&#xff0c;只是为了明确类的作用而设立。 即Repository是Comp…

Qt:QFileDialog

目录 一、介绍 二、功能 三、具体事例 1、将某个界面保存为图片&#xff0c;后缀名可选PNG、JPEG、SVG等 一、介绍 QFileDialog提供了一个对话框&#xff0c;允许用户选择文件或者目录&#xff0c;也允许用户遍历文件系统&#xff0c;用以选择一个或多个文件或者目录。 QF…

基于Java超市管理系统设计与实现(源码+部署文档)

博主介绍&#xff1a; ✌至今服务客户已经1000、专注于Java技术领域、项目定制、技术答疑、开发工具、毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅 &#x1f447;&#x1f3fb; 不然下次找不到 Java项目精品实…

牛客网--------------小红统计区间(easy)

题目描述&#xff1a; 本题为easy版本&#xff0c;和hard版本的唯一区别是aia_iai​保证是正整数&#xff01; 小红拿到了一个数组&#xff0c;她想知道&#xff0c;有多少非空区间满足区间所有元素之和不小于kkk&#xff1f; 输入描述: 输出描述: 输出一个整数表示满足条件的非…

Camunda流程引擎数据库架构

&#x1f496;专栏简介 ✔️本专栏将从Camunda(卡蒙达) 7中的关键概念到实现中国式工作流相关功能。 ✔️文章中只包含演示核心代码及测试数据&#xff0c;完整代码可查看作者的开源项目snail-camunda ✔️请给snail-camunda 点颗星吧&#x1f618; &#x1f496;数据库架构…

WINDOWS搭建NFS服务器

下载并安装 Networking Software for Windows 启动配置 找到安装目录&#xff08;如C:\Program Files\nfsd&#xff09;&#xff0c;双击nfsctl.exe&#xff0c;菜单Edit->Preferences 启动后&#xff1a; 配置Export Exports->Edit exports file 其他的几句我都删除…

[Linux] 网络编程套接字

目录 预备知识 网络字节序 网络字节序和主机字节序转换的库函数 socket编程接口 socket常见API sockaddr结构 套接字的种类 预备知识 1.在IP数据包头部中&#xff0c;有两个IP地址&#xff0c;分别叫做源IP地址和目的IP地址。 2.端口号&#xff1a;是传输层协议的内容…

速过计算机二级python——第八讲:基本编程

第八讲:基本编程 基本编程题【15 分】简单应用题【25 分】综合应用题【20 分】**问题一**【5分】问题二【5 分】问题二【10 分】小结基本编程题【15 分】 考生文件夹下存在一个文件 PY101.py,请写代码替换横线,不修改其他代码,实现以下功能:【5 分】键盘输入正整数 n,按要…

EMNLP 2023精选:Text-to-SQL任务的前沿进展(上篇)——正会论文解读

导语 本文记录了今年的自然语言处理国际顶级会议EMNLP 2023中接收的所有与Text-to-SQL相关&#xff08;通过搜索标题关键词查找得到&#xff0c;可能不全&#xff09;的论文&#xff0c;共计12篇&#xff0c;包含5篇正会论文和7篇Findings论文&#xff0c;以下是对这些论文的略…

国图公考:公务员面试资格复审需要准备什么?

参加国考面试的考生在资格审核阶段需要准备以下材料&#xff1a; 1、本人身份证、学生证或工作证复印件。 2、公共科目笔试准考证复印件。 3、考试报名登记表。 4、本(专)科、研究生各阶段学历、学位证书(应届毕业生没有可以暂时不提供)。 5、报名资料上填写的各类证书材料…

Debezium发布历史103

原文地址&#xff1a; https://debezium.io/blog/2021/03/18/understanding-non-key-joins-with-quarkus-extension-for-kafka-streams/ 欢迎关注留言&#xff0c;我是收集整理小能手&#xff0c;工具翻译&#xff0c;仅供参考&#xff0c;笔芯笔芯. 了解 Kafka Streams 的 Q…

文心一言用户规模破亿 /微软宣布:支付费用延长旧版Windows 10使用寿命|魔法半周报

我有魔法✨为你劈开信息大海❗ 高效获取AIGC的热门事件&#x1f525;&#xff0c;更新AIGC的最新动态&#xff0c;生成相应的魔法简报&#xff0c;节省阅读时间&#x1f47b; &#x1f525;资讯预览 百度大模型重要突破&#xff0c;文心一言用户规模破亿&#xff0c;飞桨开发者…

LeetCode、198. 打家劫舍【中等,一维线性DP】

文章目录 前言LeetCode、198. 打家劫舍【中等&#xff0c;一维线性DP】题目及分类思路线性DP&#xff08;一维&#xff09; 资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝2W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者、专注…

Netty源码 之 bind绑定流程

1.Netty框架总览 Netty是一个基于NIO异步通信框架 Netty框架是由许多组件&#xff0c;优化的数据结构所构建成。 正是通过灵活的组件构建&#xff0c;优化后的数据结构&#xff0c;进而才能保证Netty框架面对高并发场景具有一定的能力 1.1 Netty相关组件 Netty重要的组件有…