JVM内存模型剖析与参数设置

news2024/10/5 18:32:20

目录

Java语言的跨平台特性

JVM 的主要组成部分及其作用是什么?

JVM整体结构及内存模型

线程栈(Machine Stack)

局部变量表(Local Variable Table)

操作数栈(Operand Stack)

程序计数器(Program Counter Register)

动态链接(Dynamic Linking)

方法出口(Method Exit)

堆(Heap)

栈(Stack)

本地方法栈(Native Method Stack)

方法区(Method Area)

在minor gc过程中对象挪动后,引用如何修改?

JVM内存参数设置


Java语言的跨平台特性

Java语言具有跨平台特性,这意味着可以编写一次Java代码,并在不同的操作系统和硬件平台上运行,而无需进行大量的修改或重新编译。

  1. Java虚拟机(Java Virtual Machine):Java程序在运行时被编译为字节码(bytecode),而不是特定于某个平台的机器代码。字节码可以在任何支持Java虚拟机的平台上运行,因此Java程序可以在Windows、Mac、Linux等各种操作系统上执行。
  2. Write Once, Run Anywhere(一次编写,到处运行):通过Java的跨平台特性,可以编写一次Java代码,然后在不同的平台上运行。只需将编译后的字节码文件(.class文件)拷贝到目标平台,并确保目标平台上有合适版本的Java虚拟机,就可以在该平台上运行程序。
  3. 平台无关的标准库:Java提供了丰富的标准库,涵盖了各种常用功能和API。这些库是与平台无关的,因此可以在任何支持Java虚拟机的平台上使用。
  4. 自动内存管理:Java通过垃圾回收器(Garbage Collector)自动管理内存,开发人员无需手动分配和释放内存。这有助于减少与特定平台相关的内存管理问题。
  5. 安全性:Java具有内置的安全机制,可以防止恶意代码对系统的损害。Java的安全性模型包括类加载器、安全管理器和沙箱环境,可以确保代码在不同平台上以安全的方式运行。

JVM 的主要组成部分及其作用是什么?

1、类加载器(Class Loader):类加载器负责将字节码文件(.class文件)加载到内存中,并将其转换为可执行的Java类,并在运行时动态链接这些类。它根据类的全限定名查找和加载字节码文件,并生成类的运行时数据结构,供JVM使用。

它分为三个主要的层次:

  • Bootstrap Class Loader
  • Application Class Loader
  • Extension Class Loader

2、执行引擎(Execution Engine):执行引擎负责解释和执行Java字节码指令。它将字节码转换为可执行的机器指令,并执行这些指令。

它包含两个主要的部分:

  • 解释器(Interpreter):逐行解释执行字节码指令,实现跨平台的特性,但执行速度相对较慢。
  • 即时编译器(Just-In-Time Compiler,JIT):将字节码转换为本地机器码,这样可以在后续的执行中直接运行本地机器码,提高执行速度。

3、运行时数据区(Runtime Data Area):运行时数据区是JVM中的内存区域,用于存储各种数据和程序运行时所需的数据。主要包括方法区、堆、栈、程序计数器和本地方法栈等。

  • 方法区(Method Area):方法区用于存储类的结构信息、常量、静态变量和字节码等。它是被所有线程共享的内存区域。
  • 垃圾回收器(Garbage Collector):垃圾回收器负责自动回收不再被使用的对象,并释放它们占用的内存空间。它通过检测和标记不可达对象,并回收它们的内存,以供后续的对象分配使用。
  • 本地方法栈(Native Method Stack):本地方法栈用于执行本地方法(Native Method)。本地方法是使用其他编程语言(如C、C++)编写的方法,通过Java本地接口(JNI)与Java代码进行交互。
    • 本地接口(Native Interface):允许Java代码调用本地库中的方法,也允许本地库调用Java代码。这样可以在Java中使用其他语言编写的库,实现与底层系统的交互。
  • 程序计数器(Program Counter Register):程序计数器用于存储当前线程正在执行的字节码指令的地址或索引。它在方法调用、执行和返回过程中发挥重要作用。
  • 栈(Stack):栈用于管理方法的调用和执行过程。每个线程在执行时都会有一个栈,用于存储局部变量、方法调用、返回信息和操作数栈等。
  • 堆(Heap):堆用于存储对象实例和数组。在Java中,所有通过new关键字创建的对象都存储在堆上,堆是Java动态分配内存的主要区域。也是垃圾回收的主要区域。

JVM的主要作用是提供一个可移植、安全和高性能的运行环境,使得Java程序可以在不同的操作系统和硬件平台上运行。它负责加载、解释和执行Java字节码,提供内存管理和垃圾回收、线程管理、异常处理、安全检查等功能。JVM的设计和实现使得Java具备了跨平台性、可移植性和安全性的优势。

JVM整体结构及内存模型

线程栈(Machine Stack)

每个线程在执行时都有自己的线程栈,线程栈独立于其他线程,互不共享。

线程栈的主要作用如下:

  1. 方法调用和执行:线程栈用于管理方法的调用和执行过程。每当一个方法被调用时,JVM会在线程栈上创建一个新的栈帧(Stack Frame),栈帧用于存储方法的参数、局部变量和中间结果。方法执行期间,栈帧会保持在栈顶,直到方法执行完毕。
  2. 局部变量存储:线程栈用于存储方法的局部变量。每个方法在执行时,会分配一定的栈空间用于存储方法的参数和局部变量。局部变量包括方法的参数和方法内部声明的变量,它们的生命周期仅限于方法的执行期间。
  3. 递归调用支持:线程栈支持方法的递归调用。当一个方法在执行过程中调用自身或其他方法时,每次调用都会在线程栈上创建一个新的栈帧,用于保存方法调用的上下文信息。
//运行main方法时,创建线程,Java虚拟机为每个线程创建的一块内存区域,用于支持线程的方法调用和执行。
//main方法在线程栈内开辟属于自己的独立内存空间(栈帧),存放math;执行compute方法时,会另外开辟一块compute的独立内存空间(栈帧),存放a、b、c。如上图所示
//栈采用后进先出(LIFO)的数据结构,所以后进栈的compute方法会先执行完成(出栈释放内存)
package com.bubble.jvm;
public class Math {
    public static final int initData = 666;
    public static User user = new User();

    public int compute() {  //一个方法对应一块栈帧内存区域
        int a = 1;
        int b = 2;
        int c = (a + b) * 10;
        return c;
    }

    public static void main(String[] args) {
        Math math = new Math();
        math.compute();
        System.out.println("test");
    }
}

生成反汇编文件的指令: javap -c Math.class > Math.txt

Compiled from "Math.java"
public class com.bubble.jvm.Math {
  public static final int initData;

  public static com.bubble.jvm.User user;

  public com.bubble.jvm.Math();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public int compute();
    Code:
       0: iconst_1     //将int类型常量1压入操作数栈
       1: istore_1     //将int类型值存入局部变量1
       2: iconst_2     //将int类型常量2压入操作数栈
       3: istore_2     //将int类型值存入局部变量2
       4: iload_1      //从局部变量1中装载int类型值 
       5: iload_2      //从局部变量2中装载int类型值
       6: iadd         //执行int类型的加法
       7: bipush        10    //将一个8位带符号整数压入栈(将10压入栈)
       9: imul         //执行int类型的乘法
      10: istore_3     //将int类型值存入局部变量3
      11: iload_3      //从局部变量3中装载int类型值
      12: ireturn      //从方法中返回int类型的数据

  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class com/bubble/jvm/Math
       3: dup
       4: invokespecial #3                  // Method "<init>":()V
       7: astore_1
       8: aload_1
       9: invokevirtual #4                  // Method compute:()I
      12: pop
      13: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
      16: ldc           #6                  // String test
      18: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      21: return

  static {};
    Code:
       0: new           #8                  // class com/bubble/jvm/User
       3: dup
       4: invokespecial #9                  // Method com/bubble/jvm/User."<init>":()V
       7: putstatic     #10                 // Field user:Lcom/bubble/jvm/User;
      10: return
}

局部变量表(Local Variable Table)

JVM运行时数据区中的一个部分,用于存储方法中的局部变量和方法参数的值。每个方法在执行时都会创建一个局部变量表。

操作数栈(Operand Stack)

是JVM中的一块内存区域,用于存储方法执行过程中操作数和中间结果的内存区域。每个线程在执行方法时都会拥有自己的操作数栈。

操作数栈采用后进先出(LIFO)的数据结构,它可以执行一些基本的算术和逻辑操作。

操作数栈的主要作用如下:

  1. 存储方法执行过程中的操作数:当方法需要进行计算时,操作数栈用于存储方法所需的操作数,如整数、浮点数、对象引用等。
  2. 保存中间结果:在方法执行过程中,操作数栈可以保存计算的中间结果,以便后续的操作使用。
  3. 方法调用的参数传递:在方法调用时,参数会被压入操作数栈中,供被调用方法使用。
  4. 支持方法调用和返回:操作数栈在方法调用和返回过程中发挥重要作用。当方法调用其他方法时,当前方法的操作数栈可以用来传递参数;而在方法返回时,返回值会被压入操作数栈中。

操作数栈的大小是由编译器在编译阶段根据字节码指令的需求进行计算,并在方法运行时创建。栈帧(Stack Frame)中的局部变量和操作数栈共同组成了方法的运行时数据区。

程序计数器(Program Counter Register)

程序计数器是JVM中的一块内存空间,它是线程私有的,即每个线程都有自己独立的程序计数器。

作用:用来存储当前线程正在执行的字节码指令的地址或索引。每个线程都有自己的程序计数器,它们独立地记录各自线程的执行位置。

  1. 字节码解释器工作的依据:解释器通过不断地读取程序计数器的值,获取下一条需要执行的字节码指令。这样可以实现字节码的逐行解释执行。
  2. 线程切换的恢复点:由于每个线程都有自己的程序计数器,当线程切换时,JVM可以通过程序计数器的值恢复到上次执行的位置,以便继续执行。
  3. 异常处理的依据:在异常处理过程中,程序计数器能够记录异常处理器的返回地址,以确保异常处理后能够正确返回到原来的执行点。
  4. 方法间的跳转依据:当方法调用其他方法时,程序计数器可以用来保存调用点的信息,以便方法执行完成后能够返回到正确的调用位置。

动态链接(Dynamic Linking)

动态链接是通过类加载器(Class Loader)和运行时的链接过程实现的,它实现了类、字段、方法等符号引用与具体内存地址的绑定,并在程序的执行期间动态进行。当Java程序在JVM中执行时,类加载器负责将字节码文件(.class文件)加载到内存中,并在需要时进行链接操作。

动态链接在Java中的实现方式如下:

  1. 类加载过程:类加载器负责将字节码文件加载到内存中,并对类进行初始化。这个过程包括了加载、验证、准备、解析和初始化等步骤。在加载阶段,类加载器会根据类的全限定名找到对应的字节码文件,并将其加载到内存中。
  2. 链接过程:
    1. 验证(Verification):验证阶段确保加载的字节码符合Java虚拟机规范,不会造成安全漏洞和不一致性。
    2. 准备(Preparation):准备阶段为类的静态变量分配内存空间,并设置默认初始值。
    3. 解析(Resolution):解析阶段将符号引用转换为直接引用,即将类、字段、方法等符号引用解析为具体的内存地址。
  3. 运行时链接:在Java程序执行过程中,JVM会动态地将类、字段、方法等符号引用与具体的内存地址进行绑定。这个过程发生在程序的执行期间,根据需要进行动态链接。

Java的动态链接具有以下特点:

  • 延迟加载:类的加载是在需要时进行的,避免了不必要的加载和初始化过程。
  • 运行时绑定:方法的绑定是在程序执行期间动态进行的,根据实际的类和对象进行绑定,实现多态特性。
  • 灵活性:由于动态链接是在运行时进行的,可以根据运行环境和需求进行动态替换和更新,提供了更高的灵活性和可扩展性。

方法出口(Method Exit)

方法出口指的是方法执行结束后的返回点,即方法返回时程序要继续执行的位置。可以是方法返回指令的下一条指令或调用方(方法调用者)的位置。取决于方法的正常返回、异常抛出或非正常返回情况。

方法出口由以下几种情况确定

  1. 方法正常返回:当方法执行完毕并顺利返回时,程序将继续执行调用方的下一条指令。方法返回指令(return)将方法出口指定为调用方的位置
  2. 方法抛出异常:如果方法在执行过程中抛出异常,并且没有被当前方法处理,则异常将传播到调用方。此时,方法出口也是指向调用方的位置。
  3. 方法非正常返回:在某些情况下,方法可能会发生非正常的返回,比如遇到了异常、使用了非局部跳转指令(如goto)等。这种情况下,方法出口的位置取决于具体的非正常返回情况。

注意:方法出口并不一定是方法的末尾,它可以在方法的任意位置,因为方法可能会在中间通过返回指令或异常抛出来提前结束。

堆(Heap)

堆是一块用于动态分配对象的运行时数据区域。它是Java程序运行时内存管理的重要组成部分。

堆是用来存放对象和数组的内存空间,几乎所有的Java对象、数组都存储在JVM的堆内存中。当我们使用new关键字创建对象时,对象实例就会被分配在堆上。类加载器读取了类文件后,需要把类、方法、常变量放到堆内存中,保存所有引用类型的真实信息,便于后续的执行。

Java堆具有以下特点:

  1. 动态分配:堆的内存空间在程序运行期间动态分配和扩展。当我们创建对象时,JVM会根据对象的大小动态分配堆中的内存空间,并保证对象之间没有碎片化的空闲空间。
  2. 垃圾回收:由于堆存储了所有的Java对象实例和数组,Java堆也是垃圾回收器(Garbage Collector)的主要工作区域。当对象不再被引用时,垃圾回收器会自动回收这些对象占用的内存空间,以便后续的对象分配使用。
  3. 对象生命周期:堆中的对象生命周期不受方法的作用域限制,即对象可以在不同的方法中被引用和操作。对象的生命周期由程序的逻辑控制和引用关系决定。

通过调整JVM参数,可以控制Java堆的大小。常见的参数包括-Xms(初始堆大小)和-Xmx(最大堆大小)等。

注意:堆是Java虚拟机管理的内存区域,与操作系统的堆内存并不完全一样。Java堆只是虚拟机规范中定义的概念,并不一定直接对应操作系统堆内存。

栈(Stack)

栈是用于存储方法调用和局部变量的一块内存区域。每个线程在执行方法时都会拥有自己的栈。

栈采用后进先出(LIFO)的数据结构,用于管理方法的调用和执行过程。每当一个方法被调用时,JVM会在栈上创建一个栈帧(Stack Frame),栈帧用于存储方法的局部变量、操作数栈、动态链接和返回地址等信息。栈在方法执行期间动态分配和释放内存,是实现方法调用和局部变量存储的关键组成部分。

栈的主要作用如下:

  1. 方法调用和返回:栈用于管理方法的调用和返回过程。当一个方法被调用时,JVM会在栈上创建一个新的栈帧,将方法的参数、局部变量等信息存储在栈帧中。方法执行期间,栈帧会保持在栈顶,用于存储方法执行所需的局部变量和中间结果。当方法执行完毕后,栈帧被销毁,返回到上一个方法的执行点。
  2. 局部变量存储:栈用于存储方法的局部变量。每个方法都有自己的局部变量空间,用于存储方法中定义的局部变量。局部变量包括方法参数和方法内部声明的变量,它们的生命周期仅限于方法的执行期间。
  3. 操作数栈:栈也用于存储方法执行过程中的操作数栈(Operand Stack)。操作数栈用于执行方法中的运算操作,如算术运算、逻辑运算等。方法执行时,操作数栈存储方法所需的操作数和中间结果。

注意:栈的大小是有限的,并且在JVM启动时就被预先设置好了。当栈空间不足时,会抛出StackOverflowError异常。

本地方法栈(Native Method Stack)

本地方法栈是一块用于执行本地方法(Native Method)的内存区域。它用于调用本地方法、分配本地方法的局部变量和管理本地方法执行过程。本地方法是使用其他编程语言(如C、C++)编写的方法,通过Java本地接口(Java Native Interface,JNI)与Java代码进行交互。

与Java虚拟机栈类似,本地方法栈采用后进先出(LIFO)的数据结构。每当一个本地方法被调用时,JVM会在本地方法栈上创建一个新的栈帧,用于存储本地方法的参数和局部变量。本地方法执行期间,栈帧会保持在栈顶。每个线程在执行本地方法时都会拥有自己的本地方法栈。

本地方法栈的主要作用是为本地方法的执行提供支持,包括以下功能:

  1. 调用本地方法:当Java代码调用本地方法时,JVM会将本地方法的参数传递到本地方法栈中,准备进行本地方法的执行。
  2. 分配本地方法的局部变量:本地方法栈用于分配本地方法所需的局部变量空间,存储本地方法中定义的局部变量。
  3. 本地方法执行过程的管理:本地方法栈负责管理本地方法的调用和执行过程。它保存了本地方法的返回地址、动态链接和异常处理信息等。

注意:不同于Java虚拟机栈,它是Java虚拟机为了支持本地方法的调用而提供的专门内存区域。

方法区(Method Area)

在Java虚拟机(JVM)中,方法区是一块用于存储类信息、静态变量、常量、方法字节码等数据的内存区域。它是Java程序运行时内存管理的一部分。

方法区是被所有线程共享的内存区域,存储了加载的类信息和类的运行时常量池。它与堆不同,方法区不存储对象实例,而是存储类级别的数据。

方法区的主要作用如下:

  1. 存储类信息:方法区存储加载的类的结构信息,包括类的字段、方法、构造函数、父类、接口等。这些信息在类加载过程中被加载到方法区,并被JVM用于类的验证、准备、解析等操作。
  2. 运行时常量池:方法区中有一个运行时常量池(Runtime Constant Pool),它是每个类或接口在编译期间生成的常量池的运行时表示。运行时常量池包含类中的常量、字面量、符号引用等。方法区中的运行时常量池在类加载时被创建,存储了编译期生成的常量信息,供JVM在运行时使用。
  3. 静态变量和静态方法:方法区存储了类的静态变量(static variable)和静态方法(static method)。静态变量是在类加载时初始化的,并且在整个程序执行期间都存在于方法区中。

注意:方法区的大小在JVM启动时就被固定下来,并且通常比堆要小。方法区的大小可以通过JVM参数进行调整,如-XX:MaxMetaspaceSize。在Java 8及之前的版本,方法区被实现为永久代(Permanent Generation)。但在Java 8及以后的版本,永久代被元数据区(Metaspace)取代,元数据区是一块位于本地内存中的区域,与堆内存分开。

在minor gc过程中对象挪动后,引用如何修改?

对象在堆内部挪动的过程其实是复制,原有区域对象还在,一般不直接清理,JVM内部清理过程只是将对象分配指针移动到区域的头位置即可,比如扫描s0区域,扫到gcroot引用的非垃圾对象是将这些对象复制到s1或老年代,最后扫描完了将s0区域的对象分配指针移动到区域的起始位置即可,s0区域之前对象并不直接清理,当有新对象分配了,原有区域里的对象也就被清除了。

minor gc在根扫描过程中会记录所有被扫描到的对象引用(在年轻代这些引用很少,因为大部分都是垃圾对象不会扫描到),如果引用的对象被复制到新地址了,最后会一并更新引用指向新地址。

JVM内存参数设置

#Spring Boot程序的JVM参数设置格式(Tomcat启动直接加在bin目录下catalina.sh文件里):
java -Xms2048M -Xmx2048M -Xmn1024M -Xss512K -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -jar microservice-eureka-server.jar

-Xss:每个线程的栈大小

-Xms:设置堆的初始可用大小,默认物理内存的1/64

-Xmx:设置堆的最大可用大小,默认物理内存的1/4

-Xmn:新生代大小

-XX:NewRatio:默认2表示新生代占老年代的1/2,占整个堆内存的1/3。

-XX:SurvivorRatio:默认8表示一个survivor区占用1/8的Eden内存,即1/10的新生代内存。

关于元空间的JVM参数有两个:-XX:MetaspaceSize=N和 -XX:MaxMetaspaceSize=N

-XX:MaxMetaspaceSize: 设置元空间最大值, 默认是-1, 即不限制, 或者说只受限于本地内存大小。

-XX:MetaspaceSize: 指定元空间触发Fullgc的初始阈值(元空间无固定初始大小), 以字节为单位,默认是21M左右,达到该值就会触发full gc进行类型卸载, 同时收集器会对该值进行调整: 如果释放了大量的空间, 就适当降低该值; 如果释放了很少的空间, 那么在不超过-XX:MaxMetaspaceSize(如果设置了的话) 的情况下, 适当提高该值。这个跟早期jdk版本的-XX:PermSize参数意思不一样,-XX:PermSize代表永久代的初始容量。

由于调整元空间的大小需要Full GC,这是非常昂贵的操作,如果应用在启动的时候发生大量Full GC,通常都是由于永久代或元空间发生了大小调整,基于这种情况,一般建议在JVM参数中将MetaspaceSize和MaxMetaspaceSize设置成一样的值,并设置得比初始值要大,对于8G物理内存的机器来说,一般我会将这两个值都设置为256M。

StackOverflowError示例:

// JVM设置  -Xss128k(默认1M),
public class StackOverflowTest {
    static int count = 0;
    static void redo() {
        count++;
        redo();
    }
    
    public static void main(String[] args) {
        try {
            redo();
        } catch (Throwable t) {
            t.printStackTrace();
            System.out.println(count);
        }
    }
}

//运行结果:
java.lang.StackOverflowError
    at com.bubble.jvm.StackOverflowTest.redo(StackOverflowTest.java:12)
    at com.bubble.jvm.StackOverflowTest.redo(StackOverflowTest.java:13)
    at com.bubble.jvm.StackOverflowTest.redo(StackOverflowTest.java:13)
   ......

结论:

-Xss设置越小count值越小,说明一个线程栈里能分配的栈帧就越少,但是对JVM整体来说能开启的线程数会更多

尽可能让对象都在新生代里分配和回收,尽量别让太多对象频繁进入老年代,避免频繁对老年代进行垃圾回收,同时给系统充足的内存大小,避免新生代频繁的进行垃圾回收。

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

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

相关文章

【Linux】已解决:Ubuntu虚拟机安装Java/JDK

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项结论 已解决&#xff1a;Ubuntu虚拟机安装Java/JDK 一、分析问题背景 在Ubuntu虚拟机上安装Java开发工具包&#xff08;JDK&#xff09;是许多开发者的常见任务。然而&#xff0c;在…

Pc端多功能视频混剪工具/便携版打开即用

PC便携版 视频批量剪辑大师&#xff0c;全自动剪辑神器&#xff0c;会打字就能做视频 多功能&#xff0c;视频混剪&#xff0c;视频配音&#xff0c;文字生成语音&#xff0c;图片合成视频&#xff0c;自动识别音频并生成字幕等功能 链接&#xff1a;https://pan.baidu.com/…

2007-2022年 省级-绿色农业合作社数量相关数据整理

绿色农业合作社作为一种推动农业可持续发展的组织形式&#xff0c;对于促进环境保护、提高农产品质量和增加农民收入等方面具有重要作用。以下是对省级绿色农业合作社数量相关数据的介绍&#xff1a; 数据简介 定义&#xff1a;绿色农业合作社是由农民、农业专家、企业家等组…

详细解释Redis的SET NX命令

详细解释Redis的SET NX命令 SET NX 命令是 Redis 中用于实现分布式锁的一个重要命令。它的语法和用法如下&#xff1a; SET key value NX [EX seconds | PX milliseconds]参数解释 key&#xff1a;要设置的键名。value&#xff1a;要设置的键值&#xff0c;通常用一个唯一标…

【小沐学AI】Python实现语音识别(whisper+HuggingFace)

文章目录 1、简介1.1 whisper 2、HuggingFace2.1 安装transformers2.2 Pipeline 简介2.3 Tasks 简介2.3.1 sentiment-analysis2.3.2 zero-shot-classification2.3.3 text-generation2.3.4 fill-mask2.3.5 ner2.3.6 question-answering2.3.7 summarization2.3.8 translation 3、…

SM2258XT量产工具,SM2258XT开卡三星SSV4颗粒成功分享,SM2259XT量产参考教程,威刚ADATA SP580开卡记录

前两天拆了笔记本上的威刚ADATA SP580 240GB&#xff0c;准备做移动硬盘用&#xff0c;装入移动硬盘盒之后接入电脑&#xff0c;发现系统可认盘&#xff0c;SMART显示正常&#xff0c;Windows的磁盘管理能显示正确容量&#xff0c;但处于未初始化状态&#xff0c;且始终无法初始…

鸿蒙系统——强大的分布式系统

鸿蒙相比较于传统安卓最最最主要的优势是微内核分布式操作系统&#xff0c;具有面向未来&#xff0c;跨设备无缝协作&#xff0c;数据共享的全场景体验。下面简单来感受一下鸿蒙系统的多端自由流转。 自由流转概述 场景介绍 随着全场景多设备的生活方式不断深入&#xff0c;…

SSM网上旅游信息管理系统-计算机毕业设计源码06975

目 录 摘要 1 绪论 1.1 研究背景 1.2 研究意义 1.3论文结构与章节安排 2 系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据新增流程 2.2.2 数据删除流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 系统用例分析 2.5本章小结 3 系统总体设…

计算神经网络中梯度的核心机制 - 反向传播(backpropagation)算法(1)

计算神经网络中梯度的核心机制 - 反向传播&#xff08;backpropagation&#xff09;算法&#xff08;1&#xff09; flyfish 链式法则在深度学习中的主要应用是在反向传播&#xff08;backpropagation&#xff09;算法中。 从简单的开始 &#xff0c;文本说的就是链式法则 R …

酒店客房管理系统(Java+MySQL)

技术栈 Java: 作为主要编程语言。Swing GUI: 用于开发图形用户界面。MySQL: 作为数据库管理系统。JDBC: 用于连接和操作MySQL数据库。 功能要点 管理登录认证 系统提供管理员登录认证功能。通过用户名和密码验证身份&#xff0c;确保只有授权的用户可以访问和管理酒店客房信…

如何利用react框架快速创建一个electron项目

1、搭建electron项目 创建一个electron入门项目还是很容易的&#xff0c;基体方法可以参考&#xff1a;eletron入门教程 -- 快速写一个electron demo程序 但是如果要利用react框架搭建一个electron项目&#xff0c;但是有一点麻烦&#xff0c;不过可以利用工具包来进行创建&am…

opengl 实现反锯齿

// 启用混合 //glEnable(GL_BLEND); // 设置混合函数 //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //glEnable(GL_POINT_SMOOTH); // 启用点平滑 //glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); // 选择最佳点平滑 glEnable(GL_BLEND); glBlendFu…

这四款软件很好用,可以提升工作、学习效率

TableConvert TableConvert是一个基于Web的在线表格转换工具&#xff0c;能够将多种格式的表格数据进行快速转换。它支持将Excel、URL、HTML、JSON、CSV等格式转换为Markdown表、CSV/TSV、XML、YAML、插入SQL、HTML、Excel和LaTeX等格式。用户只需将表格数据粘贴到编辑器&#…

pikachu靶场 利用Rce上传一句话木马案例(工具:中国蚁剑)

目录 一、准备靶场&#xff0c;进入RCE 二、测试写入文件 三、使用中国蚁剑 一、准备靶场&#xff0c;进入RCE 我这里用的是pikachu 打开pikachu靶场&#xff0c;选择 RCE > exec "ping" 测试是否存在 Rce 漏洞 因为我们猜测在这个 ping 功能是直接调用系统…

驱动开发:配置Visual Studio驱动开发环境

100编程书屋_孔夫子旧书网 配置驱动开发环境配置驱动开发模板配置驱动双机调试 在正式开始驱动开发之前&#xff0c;需要自行搭建驱动开发的必要环境&#xff0c;首先我们需要安装Visual Studio 2013这款功能强大的程序开发工具&#xff0c;在课件内请双击ISO文件并运行内部的…

【单片机毕业设计选题24038】-基于STM32的木材厂环境监测系统

系统功能: 系统上电后根据采集到的传感器值自动控制&#xff0c;温度过高后自动开启风扇通风降温&#xff0c;湿度过 高后自动开启风扇除湿&#xff0c;光照过低后自动开启补光&#xff0c;雨量过高蜂鸣器报警&#xff0c;火焰传感器检 测到火灾后蜂鸣器报警并打开水泵灭火。…

(漏洞检查项) | 任意文件包含漏洞 file-include

(漏洞检查项)|任意文件包含漏洞 file-include 漏洞场景 1.含有动态包含语句 2.有类似于文件读取的url 漏洞描述 攻击者可以利用任意文件包含漏洞&#xff0c;读取任意文件&#xff0c;对服务器造成危害。 程序开发人员为了代码的灵活性&#xff0c;常常会将包含文件的路径…

c++重载(运算符)

1&#xff09;C入门级小知识&#xff0c;分享给将要学习或者正在学习C开发的同学。 2&#xff09;内容属于原创&#xff0c;若转载&#xff0c;请说明出处。 3&#xff09;提供相关问题有偿答疑和支持。 对于系统的所有操作符&#xff0c;一般情况下&#xff0c;只支持基本数…

算法:链表

目录 链表的技巧和操作总结 常用技巧&#xff1a; 链表中的常用操作 题目一&#xff1a;反转一个单链表 题目二&#xff1a;链表的中间结点 题目三&#xff1a;返回倒数第k个结点 题目四&#xff1a;合并两个有序链表 题目五&#xff1a;移除链表元素 题目六&#xff…

【快速排序】| 详解快速排序 力扣912

&#x1f397;️ 主页&#xff1a;小夜时雨 &#x1f397;️专栏&#xff1a;快速排序 &#x1f397;️如何活着&#xff0c;是我找寻的方向 目录 1. 题目解析2. 代码 1. 题目解析 题目链接: https://leetcode.cn/problems/sort-an-array/ 我们上道题讲过快速排序的核心代码&a…