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

JVM-Java虚拟机

基础知识

JVM的定义与作用

  • 定义:JVM是Java语言的一部分,它是一个虚拟的计算机,通过它可以执行Java程序。

  • 作用

    • 跨平台支持:实现了“编译一次,到处运行”的目标。

    • 自动内存管理:通过垃圾回收机制(GC)自动管理内存分配和回收。

    • 性能优化:提供即时编译(JIT)技术,将字节码翻译为机器码,提升程序运行效率。

JVM的内存结构

  • 堆(Heap):用于存储所有的对象实例,由GC管理。堆内存分为新生代和老年代,新生代用于存放新创建的对象,老年代存放经过多次GC后仍然存活的对象。

  • 方法区(Method Area):存储类的元数据、静态变量、常量池等。运行时常量池是方法区的一部分,用于存储编译期生成的各种字面量和符号引用。

  • 虚拟机栈(VM Stack):每个线程都有自己的虚拟机栈,用于存储栈帧。栈帧用于存储局部变量、操作数栈、动态链接信息以及方法返回地址等。

  • 本地方法栈(Native Method Stack):用于执行Java程序中的本地方法(如C/C++编写的代码)。

  • 程序计数器(PC Register):记录当前线程执行的字节码指令地址。

JVM的垃圾回收机制

  • 垃圾判定:通过可达性分析算法来判断对象是否可以被回收。如果一个对象无法通过任何引用链与GC Roots相连,则该对象被认为是可回收的。

  • 垃圾回收算法

    • 标记-清除算法:先标记所有需要回收的对象,然后清除这些对象所占用的内存空间。

    • 复制算法:将内存分为两块,每次只使用其中一块,当一块内存用完时,将存活的对象复制到另一块内存中,然后清除已使用的内存块。

    • 标记-整理算法:先标记需要回收的对象,然后将存活的对象向一端移动,最后清除掉边界以外的内存。

  • 垃圾回收器:常见的垃圾回收器有串行垃圾收集器、并行垃圾收集器、CMS(并发)垃圾收集器、G1垃圾收集器等。

JVM的类加载过程

  • 加载:将类的字节码文件加载到内存中,并生成一个对应的Class对象。

  • 验证:确保加载的类信息符合Java语言规范,没有安全问题。

  • 准备:为类的静态变量分配内存,并设置默认初始值。

  • 解析:将类、接口、字段和方法的符号引用转换为直接引用。

  • 初始化:执行类构造器<clinit>()方法,对类的静态变量进行初始化操作。

  • 使用:程序运行期间对类的使用。

  • 卸载:当类不再被使用时,JVM会卸载该类,释放所占用的内存资源。

JVM的双亲委派机制

  • 定义:当一个类加载器加载类时,它会先将类的加载请求委派给父类加载器,只有当父类加载器无法加载该类时,才会尝试自己加载。

  • 作用:保证类的唯一性,避免出现多个相同名称的类被加载到JVM中,从而保证了Java程序的稳定性和安全性。

双亲委派机制的核心思想是:当一个类加载器尝试加载一个类时,它首先会将请求委派给父类加载器,只有当父类加载器无法加载该类时,才会尝试自己加载。这个过程会一直向上委派,直到最顶层的类加载器(启动类加载器)。

具体步骤如下:

  1. 加载请求:当一个类加载器收到类加载请求时,它不会直接尝试加载该类。

  2. 委派给父类加载器:它会先将请求委派给父类加载器,让父类加载器尝试加载该类。

  3. 父类加载器加载:如果父类加载器能够加载该类,则加载完成,返回加载的类。

  4. 子类加载器加载:如果父类加载器无法加载该类(即父类加载器的加载路径中没有该类),则子类加载器才会尝试自己加载该类。

Java中的类加载器分为以下几种:

  • 启动类加载器(Bootstrap ClassLoader)

    • 负责加载Java核心类库(如java.lang.*java.util.*等)。

    • 由JVM实现,通常无法直接访问。

  • 扩展类加载器(Extension ClassLoader)

    • 负责加载Java扩展类库(通常位于$JAVA_HOME/lib/ext目录下)。

    • 是启动类加载器的子类加载器。

  • 应用类加载器(Application ClassLoader)

    • 负责加载用户类路径(classpath)上的类。

    • 是扩展类加载器的子类加载器。

  • 自定义类加载器

    • 用户可以自定义类加载器,继承自java.lang.ClassLoader

    • 自定义类加载器可以加载指定路径下的类文件。

优点

  • 避免重复加载:通过双亲委派机制,确保一个类在JVM中只会被加载一次,避免了类的重复加载。

  • 保护核心类库:防止用户自定义的类覆盖Java核心类库中的类,确保了Java核心类库的安全性。

  • 简化类加载器的实现:子类加载器可以依赖父类加载器来加载核心类库,减少了重复工作。

JVM的调优

  • 内存分配调优:可以通过设置参数来调整堆内存的大小,例如-Xms设置堆的初始内存,-Xmx设置堆的最大内存。

  • 垃圾回收器调优:根据不同的应用场景选择合适的垃圾回收器,例如-XX:+UseG1GC启用G1垃圾收集器。

  • 监控与分析工具:JVM提供了多种工具进行性能监控与调试,如JConsole、VisualVM、jstat等。

JVM调优的主要目标

  • 提高吞吐量:在单位时间内处理更多的请求。

  • 降低延迟:减少响应时间,确保应用程序快速响应用户请求。

  • 减少垃圾回收(GC)停顿:避免长时间的停顿,提高用户体验。

  • 合理使用内存:避免内存溢出(OutOfMemoryError)和内存泄漏问题。

2. JVM调优的关键参数

2.1 堆内存大小

  • 参数

    • -Xms:初始堆大小(建议设置为与最大堆大小相同,避免频繁扩展堆)。

    • -Xmx:最大堆大小(根据服务器可用内存设置,通常为物理内存的1/2到1/4)。

  • 示例

    bash复制

    -Xms1024m -Xmx1024m
  • 说明:合理的堆大小可以减少GC频率和停顿时间。

2.2 堆外内存(Direct Memory)

  • 参数

    • -XX:MaxDirectMemorySize:最大堆外内存大小(默认与-Xmx相同)。

  • 示例

    bash复制

    -XX:MaxDirectMemorySize=512m
  • 说明:堆外内存用于NIO等操作,避免占用过多堆内存。

2.3 线程堆栈大小

  • 参数

    • -Xss:每个线程的堆栈大小(默认为1MB,可根据需要调整)。

  • 示例

    bash复制

    -Xss512k
  • 说明:减少堆栈大小可以增加可用线程数量,但过小可能导致栈溢出。

2.4 垃圾回收器选择

  • 参数

    • -XX:+UseG1GC:使用G1垃圾回收器(适用于大堆内存,低延迟场景)。

    • -XX:+UseParallelGC:使用并行垃圾回收器(适用于多核服务器)。

    • -XX:+UseConcMarkSweepGC:使用并发标记-清除垃圾回收器(适用于老年代)。

  • 示例

    bash复制

    -XX:+UseG1GC
  • 说明:选择合适的垃圾回收器可以显著减少GC停顿时间。

2.5 GC日志

  • 参数

    • -XX:+PrintGCDetails:打印GC详细信息。

    • -XX:+PrintGCTimeStamps:打印GC时间戳。

    • -Xloggc:gc.log:将GC日志输出到指定文件。

  • 示例

    bash复制

    -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:gc.log
  • 说明:通过GC日志分析GC行为,优化内存使用和垃圾回收策略。

2.6 新生代与老年代比例

  • 参数

    • -XX:NewRatio:新生代与老年代的比例(默认为2,即老年代是新生代的两倍)。

  • 示例

    bash复制

    -XX:NewRatio=3
  • 说明:调整新生代与老年代的比例,减少GC频率。

2.7 Eden区与Survivor区比例

  • 参数

    • -XX:SurvivorRatio:Eden区与Survivor区的比例(默认为8,即每个Survivor区是Eden区的1/8)。

  • 示例

    bash复制

    -XX:SurvivorRatio=6
  • 说明:调整Survivor区大小,减少对象晋升到老年代的频率。

2.8 垃圾回收暂停时间目标

  • 参数

    • -XX:MaxGCPauseMillis:最大GC暂停时间目标(以毫秒为单位)。

  • 示例

    bash复制

    -XX:MaxGCPauseMillis=100
  • 说明:G1垃圾回收器会尝试满足此目标,减少GC停顿时间。

2.9 自适应调整

  • 参数

    • -XX:+AggressiveOpts:启用激进优化。

    • -XX:+AggressiveHeap:启用激进堆优化。

  • 示例

    bash复制

    -XX:+AggressiveOpts -XX:+AggressiveHeap
  • 说明:让JVM根据系统资源自动优化性能。

3. JVM监控与分析工具

3.1 jconsole

  • 功能:JVM自带的监控工具,可以查看堆内存、线程、GC等信息。

  • 使用方法

    bash复制

    jconsole

3.2 jstat

  • 功能:命令行工具,用于监控GC和内存使用情况。

  • 使用方法

    bash复制

    jstat -gc <pid> 1000

3.3 VisualVM

  • 功能:图形化监控工具,支持内存分析、线程分析、性能分析等。

  • 使用方法

    bash复制

    jvisualvm

3.4 GCViewer

  • 功能:分析GC日志,提供详细的GC行为分析。

  • 使用方法

    • 将GC日志文件拖入GCViewer工具中进行分析。

3.5 Flight Recorder

  • 功能:JVM自带的低开销监控工具,可以记录JVM运行时的详细信息。

  • 使用方法

    bash复制

    -XX:+UnlockCommercialFeatures -XX:+FlightRecorder

4. 调优步骤

  1. 基准测试:在调优前,对应用程序进行基准测试,记录当前性能指标。

  2. 监控分析:使用监控工具(如jconsole、VisualVM等)分析内存使用、GC行为等。

  3. 调整参数:根据分析结果调整JVM参数,如堆大小、垃圾回收器等。

  4. 重复测试:调整后重新进行基准测试,对比性能变化。

  5. 持续优化:根据测试结果持续调整,直到达到满意的性能指标。

5. 常见问题及解决方法

5.1 堆内存溢出(OutOfMemoryError

  • 原因:堆内存不足,可能是内存泄漏或堆大小设置不合理。

  • 解决方法

    • 使用jmap工具分析堆内存:

      bash复制

      jmap -dump:format=b,file=heapdump.hprof <pid>
    • 使用MAT(Memory Analyzer Tool)分析堆转储文件,查找内存泄漏。

    • 增加堆内存大小,调整-Xms-Xmx参数。

5.2 GC停顿时间过长

  • 原因:垃圾回收器选择不当或堆内存设置不合理。

  • 解决方法

    • 使用G1垃圾回收器:

      bash复制

      -XX:+UseG1GC
    • 调整堆大小和新生代比例,减少GC频率。

5.3 线程过多导致性能下降

  • 原因:线程堆栈过大或线程池配置不合理。

  • 解决方法

    • 减少线程堆栈大小(-Xss)。

    • 优化线程池配置,限制最大线程数。

HotSpot为什么要分为新生代和老年代

HotSpot JVM将堆内存划分为新生代和老年代,主要是基于对象生命周期的特点以及垃圾回收的效率和性能优化,具体原因如下:

1. 基于对象生命周期的优化

  • 新生代:新生代主要用于存放新创建的对象。根据“弱分代假设”(Weak Generational Hypothesis),大部分对象在创建后很快就会被回收,因此新生代的垃圾回收(Minor GC)频率较高。

    • Eden区:新对象首先在Eden区分配。当Eden区满时,触发Minor GC,将存活对象复制到Survivor区。

    • Survivor区:分为From和To两个区域,用于在Minor GC时复制存活对象。每次GC后,存活对象从一个Survivor区复制到另一个,或者晋升到老年代。

  • 老年代:存放经过多次新生代GC后仍然存活的对象。这些对象的生命周期较长,因此老年代的垃圾回收(Major GC或Full GC)频率较低,但回收时间较长。

2. 垃圾回收算法的选择

  • 新生代:采用复制算法,因为新生代中大部分对象都是临时的,复制算法可以高效地清理大量死亡对象。

  • 老年代:采用标记-清除-压缩算法(Mark-Sweep-Compact),因为老年代的对象生命周期长,空间利用率低,需要通过压缩来整理内存。

3. 性能优化

  • 新生代:由于对象生命周期短,Minor GC可以快速完成,减少停顿时间,提高应用性能。

  • 老年代:虽然回收频率低,但每次回收时间较长。通过减少老年代的回收频率,避免频繁的长时间停顿。

4. 内存分配策略

  • 新生代:通过调整新生代和老年代的比例(默认新生代占堆内存的1/3,老年代占2/3),可以更好地满足不同类型应用的内存需求。

  • 大对象直接分配到老年代:可以通过配置参数(如-XX:PretenureSizeThreshold)将大对象直接分配到老年代,避免频繁的Minor GC。

5. 线程局部分配缓冲区(TLAB)

  • HotSpot JVM在新生代中使用TLAB技术,为每个线程分配独立的内存缓冲区,减少线程间的内存分配竞争,提高多线程应用的性能。

强引用、软引用、弱引用、虚引用

1. 强引用(Strong Reference)

强引用是最常见的引用类型。如果一个对象被强引用所指向,那么垃圾回收器(GC)不会回收这个对象,即使当前内存空间不足。

特点:

  • 只要强引用存在,对象就不会被垃圾回收。

  • 如果对象仅被强引用指向,即使它不再被使用,也不会被回收。

2. 软引用(Soft Reference)

软引用是一种相对强引用弱一些的引用类型。被软引用指向的对象,在内存不足时可能会被垃圾回收器回收,但在内存足够时,这些对象通常不会被回收。

特点:

  • 软引用对象在内存不足时可能会被回收。

  • 软引用通常用于实现缓存机制,当内存不足时,可以释放这些对象来避免内存溢出。

3. 弱引用(Weak Reference)

弱引用比软引用更弱。被弱引用指向的对象,只要垃圾回收器运行,就会被回收,无论内存是否充足。

特点:

  • 弱引用对象在垃圾回收器运行时会被回收。

  • 弱引用通常用于实现监听器、缓存等场景,这些对象在不需要时可以被自动回收。

4. 虚引用(Phantom Reference)

虚引用是最弱的一种引用类型。虚引用指向的对象在垃圾回收器运行时会被回收,但虚引用不会保存对象的引用,因此无法通过虚引用来访问对象。虚引用主要用于在对象被回收时执行某些操作,例如清理资源。

判断对象死亡

1. 引用计数法

引用计数法是一种简单直观的判断对象是否死亡的方法,其基本原理是为每个对象维护一个引用计数器:

  • 原理:每当有一个引用指向该对象时,计数器加1;当引用失效(如引用被赋值为null,或者引用的生命周期结束)时,计数器减1。当计数器值为0时,说明该对象没有任何引用指向它,可以被判定为“死亡”。

  • 优点:实现简单,判断速度快。

  • 缺点:无法解决对象之间相互循环引用的问题。例如,两个对象A和B相互引用,但没有其他外部引用指向它们,此时它们的引用计数器都不会为0,但实际上它们已经无法被访问,应该被回收,但引用计数法无法识别这种情况。

2. 可达性分析算法

可达性分析算法是目前主流的垃圾回收算法,它通过根节点集合(Root Set)来判断对象是否存活:

  • 原理:从一组称为“根节点集合”的对象开始,这些根节点通常包括:

    • 栈中的引用变量:当前线程栈中的局部变量。

    • 类加载器的静态变量:类的静态变量。

    • 本地方法栈中的引用:本地方法(如JNI)中使用的对象引用。

    • JVM内部的引用:如常量池、字符串常量池等。

    从这些根节点出发,通过引用关系向下搜索,所有能被根节点直接或间接引用到的对象都被认为是“存活”的。无法被根节点集合引用到的对象则被认为是“死亡”的。

  • 优点:能够解决循环引用的问题,更准确地判断对象的存活状态。

  • 缺点:实现相对复杂,需要遍历整个对象图,对性能有一定影响。

总结

  • 引用计数法:简单但存在循环引用问题,不适合复杂的对象关系。

  • 可达性分析算法:目前主流方法,能够准确判断对象的存活状态,但实现复杂,对性能有一定要求。

垃圾收集算法

1. 标记-清除算法(Mark-Sweep)

  • 工作原理:分为“标记”和“清除”两个阶段。首先遍历所有对象,标记出存活的对象,然后清除未被标记的对象,释放其占用的内存空间。

  • 优点:实现简单,不需要移动对象。

  • 缺点

    • 标记和清除过程效率不高,需要遍历整个堆。

    • 清除后会产生大量不连续的内存碎片,可能导致后续需要分配大对象时无法找到足够的连续空间,从而触发另一次垃圾回收。

2. 复制算法(Copying)

  • 工作原理:将内存空间划分为两个大小相等的区域,每次只使用其中一个区域。当该区域内存用完时,将存活的对象复制到另一个区域,然后清空当前区域的所有对象。

  • 优点

    • 解决了内存碎片问题,因为每次都是对整个半区进行内存回收。

    • 分配内存时只需按顺序分配,实现简单且高效。

  • 缺点

    • 内存利用率低,只有原来的一半空间可用。

    • 如果对象存活率高,复制操作会耗费较多时间。

3. 标记-整理算法(Mark-Compact)

  • 工作原理:标记过程与标记-清除算法相同,但后续步骤不是直接清除对象,而是让所有存活的对象都向内存的一端移动,然后直接清理掉端边界以外的内存。

  • 优点:解决了内存碎片问题,提高了内存利用率。

  • 缺点

    • 标记和整理过程都需要遍历对象,效率相对较低。

    • 需要额外的空间来保存迁移地址等信息。

4. 分代收集算法(Generational Collection)

  • 工作原理:根据对象的存活周期将内存划分为不同的代(如新生代、老年代)。新生代对象存活时间短,采用复制算法进行回收;老年代对象存活时间长,采用标记-清除或标记-整理算法进行回收。

  • 优点

    • 充分利用了对象的生命周期分布特点,提高了垃圾回收的效率。

    • 减少了不必要的内存清理工作。

  • 缺点:需要根据具体的应用场景和对象分布特点进行调优。

5. 引用计数算法(Reference Counting)

  • 工作原理:每个对象维护一个引用计数,表示有多少引用指向该对象。当引用计数为0时,表示该对象不再被使用,可以回收其内存空间。

  • 优点:实现简单,回收速度快。

  • 缺点

    • 无法处理循环引用问题。

    • 每次引用增加或减少时都需要更新引用计数,增加了额外的开销。

6. 自适应混合回收算法(Adaptive Hybrid)

  • 工作原理:结合了多种垃圾回收算法的优点,根据应用程序的特点和运行时数据动态调整回收策略。

  • 优点:能够根据具体情况选择最合适的回收算法,提高垃圾回收的效率和准确性。

  • 缺点:实现复杂,需要收集和分析大量的运行时数据。

常见垃圾回收器

1. Serial(串行垃圾回收器)

  • 特点

    • 单线程执行垃圾回收。

    • 适合单核处理器的机器或小内存环境。

    • 在垃圾回收过程中,会暂停所有用户线程(Stop-The-World,STW)。

  • 适用场景

    • 客户端模式下的小型应用。

    • 对于单线程应用,可以避免线程切换的开销。

  • 参数

    • -XX:+UseSerialGC:启用Serial垃圾回收器。

2. Parallel(并行垃圾回收器)

  • 特点

    • 多线程执行垃圾回收。

    • 适合多核处理器的机器。

    • 仍然会暂停所有用户线程(STW),但通过多线程减少停顿时间。

  • 适用场景

    • 适合多核服务器,尤其是对吞吐量要求较高的场景。

  • 参数

    • -XX:+UseParallelGC:启用Parallel垃圾回收器。

    • -XX:ParallelGCThreads=<N>:设置垃圾回收线程数。

3. Parallel Old(并行老年代垃圾回收器)

  • 特点

    • 是Parallel垃圾回收器的老年代版本。

    • 使用多线程进行老年代的垃圾回收。

  • 适用场景

    • 与Parallel垃圾回收器配合使用,用于老年代的垃圾回收。

  • 参数

    • -XX:+UseParallelOldGC:启用Parallel Old垃圾回收器。

4. CMS(Concurrent Mark-Sweep)

  • 特点

    • 并发标记-清除算法。

    • 尽量减少停顿时间,适合对响应时间要求较高的应用。

    • 但可能会产生内存碎片,且在并发阶段会占用一定的CPU资源。

  • 适用场景

    • 对响应时间敏感的应用,如Web服务器。

  • 参数

    • -XX:+UseConcMarkSweepGC:启用CMS垃圾回收器。

    • -XX:ParallelGCThreads=<N>:设置垃圾回收线程数。

    • -XX:CMSInitiatingOccupancyFraction=<N>:设置触发CMS回收的堆内存占用比例。

5. G1(Garbage-First)

  • 特点

    • 分代收集与区域划分相结合。

    • 采用并发标记和分阶段垃圾回收,减少停顿时间。

    • 适合大堆内存(如多GB)的应用。

  • 适用场景

    • 适合对停顿时间和吞吐量都有较高要求的场景。

  • 参数

    • -XX:+UseG1GC:启用G1垃圾回收器。

    • -XX:G1HeapRegionSize=<N>:设置G1的区域大小。

    • -XX:MaxGCPauseMillis=<N>:设置最大垃圾回收停顿时间。

6. ZGC(Z Garbage Collector)

  • 特点

    • 低延迟垃圾回收器,目标是将停顿时间控制在10ms以内。

    • 使用并发标记和并发回收,几乎不会暂停用户线程。

    • 适合超大堆内存(如TB级)的应用。

  • 适用场景

    • 对延迟要求极高的应用,如高频交易系统。

  • 参数

    • -XX:+UseZGC:启用ZGC垃圾回收器。

    • -XX:ZCollectionInterval=<N>:设置垃圾回收的间隔时间。

7. Shenandoah

  • 特点

    • 低延迟垃圾回收器,目标是减少停顿时间。

    • 使用并发标记和并发回收,减少对用户线程的影响。

    • 与ZGC类似,但实现方式不同。

  • 适用场景

    • 对延迟敏感的应用,尤其是需要处理大堆内存的场景。

  • 参数

    • -XX:+UseShenandoahGC:启用Shenandoah垃圾回收器。

    • -XX:ShenandoahGCHeuristics=<strategy>:设置垃圾回收策略。

8. Epsilon(无操作垃圾回收器)

  • 特点

    • 一个“无操作”的垃圾回收器,实际上不进行垃圾回收。

    • 主要用于测试和基准测试,帮助开发者了解没有垃圾回收时的性能表现。

  • 适用场景

    • 用于测试和基准测试,不适合生产环境。

  • 参数

    • -XX:+UseEpsilonGC:启用Epsilon垃圾回收器。

Minor GC 和 Full GC

Minor GC 和 Full GC 是垃圾回收机制中的两种主要类型,它们在回收范围、触发条件和性能影响等方面存在显著差异:

1. 回收范围

  • Minor GC

    • 回收区域:仅针对年轻代(Young Generation),包括 Eden 区和 Survivor 区。

    • 特点:由于大多数对象生命周期较短,Minor GC 的回收效率较高,通常速度较快。

  • Full GC

    • 回收区域:清理整个堆空间,包括年轻代和老年代,还可能涉及方法区(元空间)。

    • 特点:Full GC 的范围更广,因此回收时间通常比 Minor GC 更长。

2. 触发条件

  • Minor GC

    • 触发条件:当 Eden 区空间不足,无法为新对象分配内存时,会触发 Minor GC。

  • Full GC

    • 触发条件

      • 老年代空间不足。

      • 方法区(元空间)空间不足。

      • 显式调用 System.gc()(不推荐,因为 JVM 不一定会执行 Full GC)。

      • 分配担保失败,即 Minor GC 后存活对象无法放入 Survivor 区。

3. 性能影响

  • Minor GC

    • 停顿时间:通常较短,对应用程序性能的影响较小。

    • 频率:由于对象生命周期短,触发频率较高。

  • Full GC

    • 停顿时间:通常较长,会导致明显的停顿(Stop-The-World),对应用程序性能影响较大。

    • 频率:触发频率较低,但每次执行的开销较大。

4. 垃圾回收算法

  • Minor GC

    • 算法:通常使用复制算法(Copying),将存活对象从 Eden 区复制到 Survivor 区,避免内存碎片化。

  • Full GC

    • 算法:通常使用标记-清除(Mark-Sweep)或标记-整理(Mark-Compact)算法。

相关文章:

JVM-Java虚拟机

基础知识 JVM的定义与作用 定义&#xff1a;JVM是Java语言的一部分&#xff0c;它是一个虚拟的计算机&#xff0c;通过它可以执行Java程序。 作用&#xff1a; 跨平台支持&#xff1a;实现了“编译一次&#xff0c;到处运行”的目标。 自动内存管理&#xff1a;通过垃圾回收…...

Unity底层C#处理机制深度解析

一、Unity脚本执行架构 Unity采用分层架构处理C#脚本&#xff0c;核心由以下组件构成&#xff1a; 脚本引擎层 Mono Runtime&#xff08;旧版本&#xff09; IL2CPP&#xff08;2015版本&#xff09; Burst Compiler&#xff08;DOTS体系&#xff09; 原生交互层 Runtime …...

【WB 深度学习实验管理】使用 PyTorch Lightning 实现高效的图像分类实验跟踪

本文使用到的 Jupyter Notebook 可在GitHub仓库002文件夹找到&#xff0c;别忘了给仓库点个小心心~~~ https://github.com/LFF8888/FF-Studio-Resources 在机器学习项目中&#xff0c;实验跟踪和结果可视化是至关重要的环节。无论是调整超参数、优化模型架构&#xff0c;还是监…...

MFC 应用最小化到系统托盘

本指南将实现 MFC 应用程序在关闭时最小化系统托盘的功能&#xff0c;并左键和右键系统托盘图标进行交互。 目标&#xff1a; 左键点击托盘图标&#xff1a;恢复对话框窗口。右键点击托盘图标&#xff1a;弹出右键菜单&#xff0c;提供 恢复窗口 和 退出程序 两个选项。退出时…...

C++ ——从C到C++

1、C的学习方法 &#xff08;1&#xff09;C知识点概念内容比较多&#xff0c;需要反复复习 &#xff08;2&#xff09;偏理论&#xff0c;有的内容不理解&#xff0c;可以先背下来&#xff0c;后续可能会理解更深 &#xff08;3&#xff09;学好编程要多练习&#xff0c;简…...

【OCPP】ocpp1.6J协议框架说明

目录 1.简介 1.1.本文件的目的 1.2.目标受众 1.3. OCPP-S and OCPP-J 1.4. 约定 1.5.定义和缩写 1.6.参考 2.优点和问题 3.连接 3.1.客户要求 3.1.1.连接URL 3.1.2.OCPP版本 3.1.3.打开HTTP请求的示例 3.2.服务器响应 3.3.更多信息 4.RPC框架 4.1.介绍 4.1.1…...

Swipe横滑与SwipeItem自定义横滑相互影响

背景 vue项目&#xff0c;H5页面&#xff0c;使用vant的组件库轮播组件<Swipe>&#xff0c;UI交互要求&#xff0c;在每个SwipeItem中有内容&#xff0c;可自横滑&#xff0c;查看列表内容 核心代码 <template><Swipeclass"my_swipe":autoplay&quo…...

渗透利器工具:Burp Suite 联动 XRAY 图形化工具.(主动扫描+被动扫描)

Burp Suite 联动 XRAY 图形化工具.&#xff08;主动扫描被动扫描&#xff09; Burp Suite 和 Xray 联合使用&#xff0c;能够将 Burp 的强大流量拦截与修改功能&#xff0c;与 Xray 的高效漏洞检测能力相结合&#xff0c;实现更全面、高效的网络安全测试&#xff0c;同时提升漏…...

C# 学习目录

以下内容仅供参考 基础概念 数据类型(使用与定义)-CSDN博客 var使用-CSDN博客 运算符&#xff08;new、sizeof、is、as)_new 运算符-CSDN博客 数据结构 数组定义与使用-CSDN博客 动态数组和泛型集合-CSDN博客 字典&#xff08;Dictonary)-CSDN博客 集合类型&#xff0…...

react native学习【9】——动态路由

react native学习【9】——动态路由 1、进入终端2、动态路由dynamic router3、编写app/_layout.jsx布局文件4、创建动态路由5、完善index.jsx文件6、完善[id].jsx文件扩展运算符...7、完整的index.jsx文件1、进入终端 2、动态路由dynamic router 官方网站 视频中的举例:当我们…...

[AI]Mac本地部署Deepseek R1模型 — — 保姆级教程

[AI]Mac本地部署DeepSeek R1模型 — — 保姆级教程 DeepSeek R1是中国AI初创公司深度求索&#xff08;DeepSeek&#xff09;推出大模型DeepSeek-R1。 作为一款开源模型&#xff0c;R1在数学、代码、自然语言推理等任务上的性能能够比肩OpenAI o1模型正式版&#xff0c;并采用MI…...

LeetCodehot 力扣热题100 验证二叉搜索树

class Solution {vector<int> nums; // 用来存储二叉树节点值的数组 public:bool isValidBST(TreeNode* root) {inorder(root); // 中序遍历二叉树&#xff0c;填充 nums 数组// 遍历 nums 数组&#xff0c;检查是否为严格递增序列for(int i0; i<nums.size()-1; i){…...

使用Kickstart配置文件封装操作系统实现Linux的自动化安装

使用Kickstart配置文件封装操作系统实现Linux的自动化安装 创建ks.cfg配置文件 可以使用已经安装完成的Linux操作系统中的/root目录下的anaconda.cfg配置文件 注意&#xff0c;配置文件会因为kickstart的版本兼容性的问题导致无法安装报错需要在实际使用过程中删除某些参数 …...

前端开发架构师Prompt指令的最佳实践

前端开发架构师Prompt 提示词可作为系统提示词使用&#xff0c;可基于用户的需求输出对应的编码方案。 本次提示词偏向前端开发的使用&#xff0c;如有需要可适当修改关键词和示例。 推荐使用 Cursor 中作为自定义指令使用Cline 插件中作为自定义指令使用在力所能及的范围内使…...

flink判断两个事件之间有没有超时(不使用CEP)

1.为啥不使用cep呢&#xff0c;cep的超时时间设置不好配置化&#xff0c;无法满足扩展要求 2.超时怎么界定。A事件发生后&#xff0c;过了N时间&#xff0c;还没有收到B事件&#xff0c;算超时。 代码如下&#xff1a; import com.alibaba.fastjson.JSONObject; import lombo…...

vue3+ts+vite+element plus设置日期时间禁止选择小于当前时间精确到时分秒

ts组件 // timeUtils.ts/*** 生成一个数组* param start* param end*/ export const makeRange (start: number, end: number): number[] > {const result: number[] [];for (let i start; i < end; i) {result.push(i);}return result; };/*** 限制今天之前的时间不…...

2025web寒假作业二

一、整体功能概述 该代码构建了一个简单的后台管理系统界面&#xff0c;主要包含左侧导航栏和右侧内容区域。左侧导航栏有 logo、管理员头像、导航菜单和安全退出按钮&#xff1b;右侧内容区域包括页头、用户信息管理内容&#xff08;含搜索框和用户数据表格&#xff09;以及页…...

2025.2.8——二、Confusion1 SSTI模板注入|Jinja2模板

题目来源&#xff1a;攻防世界 Confusion1 目录 一、打开靶机&#xff0c;整理信息 二、解题思路 step 1&#xff1a;查看网页源码信息 step 2&#xff1a;模板注入 step 3&#xff1a;构造payload&#xff0c;验证漏洞 step 4&#xff1a;已确认为SSTI漏洞中的Jinjia2…...

Mysql 函数解析

文章目录 一、模糊匹配【like】二、CASE函数1、简单case2、搜索case3、搜索case 聚合函数 一、模糊匹配【like】 一般形式为&#xff1a;列名 [NOT] LIKE ‘%关键字%’&#xff0c;示例如下&#xff1a; like %北京%列名包括北京的字样like ‘北京%’ 列名北京开头like ‘%北…...

Docker 部署 MongoDB | 国内阿里镜像

一、简易单机版 1、镜像拉取 docker pull registry.cn-hangzhou.aliyuncs.com/farerboy/mongo:8.0.5-rc1 2、运行镜像 docker run -it --name mongodb \ -e MONGO_INITDB_ROOT_USERNAMEmongoroot \ -e MONGO_INITDB_ROOT_PASSWORDmongoroot \ -v /wwwroot/opt/docker/mong…...

加速度计信号处理

【使用 DSP 滤波器加速速度和位移】使用信号处理算法过滤加速度数据并将其转换为速度和位移研究&#xff08;Matlab代码实现&#xff09;_加速度计滤波器-CSDN博客 https://wenku.baidu.com/view/622d38b90f22590102020740be1e650e52eacff9.html?_wkts_1738906719916&bdQ…...

Baumer工业相机堡盟相机的相机传感器芯片清洁指南

Baumer工业相机堡盟相机的相机传感器芯片清洁指南 Baumer工业相机1.Baumer工业相机传感器芯片清洁工具和清洁剂2.Baumer工业相机传感器芯片清洁步骤2.1、准备步骤2.2、清洁过程1.定位清洁工具2.清洁传感器3&#xff0e;使用吹风装置 Baumer工业相机传感器芯片清洁的优势设计与结…...

20240824 美团 笔试

文章目录 1、单选题1.11.21.31.41.51.61.71.81.91.101.111.121.131.141.151.161.171.181.191.202、编程题2.12.2岗位:硬件开发工程师(嵌入式系统软件开发方向) 题型:20 道单选题,2 道编程题题 1、单选题 1.1 C 语言中,如果输入整数 v 是 2 的幂,下面表达式中哪个会返…...

【扫描件PDF】如何批量识别扫描件PDF多个区域内容保存到Excel表格,基于WPF和腾讯OCR的详细解决方案

在很多实际业务场景中&#xff0c;需要对大量扫描件 PDF 中的特定区域内容进行识别并整理到 Excel 表格里&#xff0c;以下是一些常见的应用场景&#xff1a;物流运单扫描件 PDF 中包含发货人信息、收货人信息、货物信息等。批量识别这些区域内容到 Excel 表格&#xff0c;有助…...

Django开发入门 – 3.用Django创建一个Web项目

Django开发入门 – 3.用Django创建一个Web项目 Build A Web Based Project With Django By JacksonML 本文简要介绍如何利用最新版Python 3.13.2来搭建Django环境&#xff0c;以及创建第一个Django Web应用项目&#xff0c;并能够运行Django Web服务器。 创建该Django项目需…...

C# OpenCV机器视觉:OSTU算法实现背景差分的自适应分割

在一个热闹的科技公司里&#xff0c;阿强是一个负责图像分析的员工。他的日常工作就是从各种复杂的图像中提取出有用的信息&#xff0c;可这可不是一件轻松的事情哦 最近&#xff0c;阿强接到了一个艰巨的任务&#xff1a;要从一堆嘈杂的监控图像中分离出运动的物体&#xff0c…...

SIPp的参数及命令示例

以下是SIPp参数的分类表格整理&#xff0c;方便快速查阅和使用&#xff1a; SIPp 参数分类表格 分类参数描述默认值示例基本参数-sc指定XML场景文件&#xff08;客户端模式&#xff09;无-sc uac.xml-sd指定XML场景文件&#xff08;服务器端模式&#xff09;无-sd uas.xml-i本…...

【Mac排错】ls: command not found 终端命令失效的解决办法

【TroubleShooting on Mac】ls: command not found 终端命令失效的解决办法 A Solution to Solve “Command not found” of Terminal on Mac 一直在使用心爱的MacBook Pro的Terminal&#xff0c;并且为她定制了不同的Profile。 这样&#xff0c;看起来她可以在不同季节&…...

【OneAPI】通过网页预渲染让搜索引擎收录网页

API简介 网页预渲染&#xff0c;适用于动态网页以及单页面的SEO&#xff0c;支持网页缓存。 您无须更改代码即可让搜索引擎收录您的网页。只要将需要预渲染的页面转发的本接口即可。 如果您使用Nginx作为网页服务器&#xff0c;推荐使用以下配置&#xff1a; #您的网站locat…...

51单片机(国信长天)矩阵键盘的基本操作

在CT107D单片机综合训练平台上&#xff0c;首先将J5处的跳帽接到1~2引脚&#xff0c;使按键S4~S19按键组成4X4的矩阵键盘。在扫描按键的过程中&#xff0c;发现有按键触发信号后(不做去抖动)&#xff0c;待按键松开后&#xff0c;在数码管的第一位显示相应的数字:从左至右&…...

git命令行删除远程分支、删除远程提交日志

目录 1、从本地通过命令行删除远程git分支2、删除已 commit 并 push 的记录 1、从本地通过命令行删除远程git分支 git push origin --delete feature/feature_xxx 删除远程分支 feature/feature_xxx 2、删除已 commit 并 push 的记录 git reset --hard 7b5d01xxxxxxxxxx 恢复到…...

05-多数元素

给定一个大小为 n 的数组 nums &#xff0c;返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的&#xff0c;并且给定的数组总是存在多数元素。 方法一&#xff1a;哈希表法 通过哈希表来记录每个元素出现的次数&#xff0c;…...

一个简单的Windows TCP服务器实现

初始化 WSADATA wsaData; SOCKET serverSocket, clientSocket; struct sockaddr_in serverAddr { 0x00 }; struct sockaddr_in clientAddr { 0x00 }; int clientAddrLen sizeof(clientAddr);if (WSAStartup(MAKEWORD(2, 2), &wsaData) ! 0) {printf("WSAStartup f…...

salesforce 中 Account 转移给新 Owner 后如何仅转移 Case,而不转移 Opportunity

在 Salesforce 中&#xff0c;当更改 Account Owner 时&#xff0c;系统默认会将所有相关的 Opportunities&#xff08;商机&#xff09; 和 Cases&#xff08;案例&#xff09; 也一并转移给新的 Account Owner。如果你希望 仅转移 Case&#xff0c;而不转移 Opportunities&am…...

Spring Boot 中的日志配置

文章目录 Spring Boot 中日志配置的源码分析1. Spring Boot 日志框架的选择与自动配置2. 日志自动配置与默认行为3. 日志系统的核心组件&#xff1a;Logger 和 LoggerFactory4. 日志配置文件的解析配置日志级别配置日志输出格式和目标 5. 日志级别的控制自定义日志级别 6. 自定…...

[前端]CRX持久化

在 Chrome 扩展开发中&#xff0c;持久化保存数据通常使用 Chrome 的 storage API。storage API 提供了两种存储选项&#xff1a;local 和 sync。使用 local 存储的数据保存在本地浏览器中&#xff0c;只能在同一设备上访问。使用 sync 存储的数据可以在用户登录其 Google 帐户…...

绕组电感 - Ansys Maxwell 磁通链与电流

在本博客中&#xff0c;我将演示如何使用 Ansys Maxwell 中磁瞬态求解器的磁通链和电流结果来计算绕组电感。Ansys Maxwell 磁瞬态求解器在场计算中考虑了涡流效应&#xff0c;我将展示一种使用磁通链和电流结果来计算绕组电感的简单方法。 实际上&#xff0c;电感是非线性的…...

ComfyUI 安装教程:macOS 和 Linux 统一步骤

本教程将详细介绍如何在 macOS 和 Linux 上安装 ComfyUI。我们将从 安装 Anaconda 开始&#xff0c;到安装 PyTorch 和 ComfyUI&#xff0c;最后提供一些常见问题的解决方法。 macOS和linux安装步骤很相似 可以按照1️⃣安装anaconda2️⃣安装python3️⃣torch4️⃣comfyui Co…...

SMTP和POP3协议

SMTP和POP3协议 SMTP&#xff08;简单邮件传输协议&#xff09;和POP3&#xff08;邮局协议版本3&#xff09;是电子邮件系统中用于发送和接收邮件的核心协议。以下是它们的详细说明&#xff1a; 1. SMTP&#xff08;Simple Mail Transfer Protocol&#xff09; SMTP和POP3分…...

【C语言】#define和typedef的区别

文章目录 1.define特点 2.typedef特点 1.define #define 是预处理器指令&#xff0c;用来进行宏定义。它在编译之前由预处理器处理&#xff0c;主要用于定义常量、简单的函数宏或者代码片段的替换。 特点 文本替换&#xff1a;#define 主要用于文本替换&#xff0c;在编译前…...

2025清华:DeepSeek从入门到精通.pdf(附下载)

本文是一份关于如何深入理解和使用DeepSeek技术的全面指南&#xff0c;由清华大学新闻与传播学院新媒体研究中心元宇宙文化实验室的余梦珑博士后及其团队编撰。DeepSeek是一家中国科技公司&#xff0c;专注于通用人工智能&#xff08;AGI&#xff09;的研发&#xff0c;其开源推…...

Linux运维——用户管理

Linux用户管理 一、Linux用户管理要点二、常用命令2.1、groupadd2.2、groupdel2.3、groupmod2.4、groups2.5、useradd2.6、userdel2.7、passwd2.9、su2.10、sudo2.10.1、给普通用户授权 sudo2.10.2、 免密码授权 sudo 一、Linux用户管理要点 创建用户组 - 使用 groupadd删除用…...

Redis持久化的两种方式:RDB和AOF

redis中的数据存储在缓存中&#xff0c;如果没有持久化的策略&#xff0c;Redis一旦宕机&#xff0c;那么将会导致数据丢失&#xff1b;因此redis提供了以下两种持久化方式&#xff1a;RDB和AOF 一般来说&#xff0c;大部分公司对这两种方式都是同时开启的 一、RDB RDB策略全…...

百度高德地图坐标转换

百度地图和高德地图的侧重点不太一样。同样一个地名&#xff0c;在百度地图网站上搜索到的地点可能是商业网点&#xff0c;在高德地图网站上搜索到的地点可能是自然行政地点。 高德地图api 在高德地图中&#xff0c;搜索地名&#xff0c;如“乱石头川”&#xff0c;该地名会出…...

LIMO:上海交大的工作 “少即是多” LLM 推理

25年2月来自上海交大、SII 和 GAIR 的论文“LIMO: Less is More for Reasoning”。 一个挑战是在大语言模型&#xff08;LLM&#xff09;中的复杂推理。虽然传统观点认为复杂的推理任务需要大量的训练数据&#xff08;通常超过 100,000 个示例&#xff09;&#xff0c;但本文展…...

Windows逆向工程入门之汇编环境搭建

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​链接点击跳转博客主页 Visual Studio逆向工程配置 基础环境搭建 Visual Studio 官方下载地址安装配置选项(后期可随时通过VS调整) 使用C的桌面开发 拓展可选选项 MASM汇编框架 配置MASM汇编项目 创建新项目 选择空…...

Git安全回退历史版本

Git安全回退历史版本 方法特点git revert保留所有中间提交历史&#xff0c;生成显式的反向提交&#xff0c;适合精确撤销特定提交。直接提交快速生成一个回退提交&#xff0c;无需处理多个撤销操作&#xff0c;适合简单回退到某个旧版本。 git revert 仅回退一个版本 git r…...

消费电子产品中的噪声对TPS54202的影响

本文章是笔者整理的备忘笔记。希望在帮助自己温习避免遗忘的同时&#xff0c;也能帮助其他需要参考的朋友。如有谬误&#xff0c;欢迎大家进行指正。 一、概述 在白色家电领域&#xff0c;降压转换器的应用非常广泛&#xff0c;为了实现不同的功能就需要不同的电源轨。TPS542…...

ASP.NET Core 外部向SignalR的Hub发消息

实现 Hub类中的方法只应该用于消息的发布&#xff0c;而不应该用来写业务逻辑&#xff0c;SignalR中客户端给服务器端传递消息的超时时间为30s&#xff0c;如果对Hub类中的方法的调用执行时间超过30s&#xff0c;程序就会报错。可以在MVC控制器、托管服务等外部向客户端推送消…...

Ubuntu 多版本 gcc 配置常用命令备忘

用的频率不高&#xff0c;总忘记具体参数 1&#xff0c;安装多版本 gcc 以 gcc-11 和12 为例&#xff1a; sudo apt-get install gcc-11 gcc-12 sudo apt-get install gcc-11 gcc-12 2&#xff0c;配置多版本 gcc gcc 与 g 一起配置进数据库中&#xff1a; sudo update-a…...