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)算法。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

用Python编写经典《贪吃蛇》小游戏

文章目录 环境准备依赖库 实现思路核心模块设计 代码框架运行效果优化建议总结通过本框架可实现基础版贪吃蛇游戏&#xff0c;关键点在于&#xff1a;典型问题解决方案&#xff1a; 环境准备 依赖库 主要依赖 Python 3.6pygame 2.1.2 # 用于图形界面渲染 安装命令 pip ins…

防洪先锋,应急防洪墙助力灾害应急响应|深圳鼎跃

在全球极端天气频发的背景下&#xff0c;洪涝灾害日益成为威胁人类安全的重要因素。传统的防洪措施如堤坝、沙袋虽有一定效果&#xff0c;但在突发性洪水面前往往难以迅速部署。 应急防洪墙是一种模块化、可移动的临时防洪结构&#xff0c;通过拼插、折叠或液压驱动快速形成刚性…

从Word里面用VBA调用NVIDIA的免费DeepSeekR1

看上去能用而已。 选中的文字作为输入&#xff0c;运行对应的宏即可&#xff1b;会先MSGBOX提示一下&#xff0c;然后相关内容追加到word文档中。 需要自己注册生成好用的apikey Option ExplicitSub DeepSeek()Dim selectedText As StringDim apiKey As StringDim response A…

高通android WIFI debug

参考高通文档&#xff1a;80-76240-16_REV_AA_Wi-Fi_Debug_Techniques 大纲 一、 WLAN Debug Logs –logcat ■ Logcat log logcat is a command-line tool that dumps the log of system messages, ■ Including stack traces when the device throws an error. ■ Need t…

Python:凯撒密码

题目内容&#xff1a; 凯撒密码是古罗马恺撒大帝用来对军事情报进行加密的算法&#xff0c;它采用了替换方法对信息中的每一个英文字符循环替换为字母表序列该字符后面第三个字符&#xff0c;对应关系如下&#xff1a; 原文&#xff1a;A B C D E F G H I J K L M N O P Q R …

基于STM32的智能鱼缸水质净化系统设计

&#x1f91e;&#x1f91e;大家好&#xff0c;这里是5132单片机毕设设计项目分享&#xff0c;今天给大家分享的是智能鱼缸水质净化系统。 目录 1、设计要求 2、系统功能 3、演示视频和实物 4、系统设计框图 5、软件设计流程图 6、原理图 7、主程序 8、总结 1、设计要求…

STM32系统架构介绍

STM32系统架构 1. CM3/4系统架构2. CM3/4系统架构-----存储器组织结构2.1 寄存器地址映射&#xff08;特殊的存储器&#xff09;2.2 寄存器地址计算2.3 寄存器的封装 3. CM3/4系统架构-----时钟系统 STM32 和 ARM 以及 ARM7是什么关系? ARM 是一个做芯片标准的公司&#xff0c…

美甲美睫门店拓客营销小程序开发

一套针对美甲美睫门店开发的营销拓客小程序 小程序支持线上线下服务预约、客户管理、多种客户营销方式以及员工管理、门店管理、门店营销活动创建开展等等。 用户端&#xff1a;服务预约、次卡、时卡办理&#xff0c;会员办理、会员升级、会员权益&#xff0c;复购攒积分&…

deepseek+“D-id”或“即梦AI”快速生成短视频

1、deepseek生成视频脚本 1.1、第一步&#xff1a;使用通用模板提出需求&#xff0c;生成视频脚本 对话输入示例脚本1&#xff1a; 大年初五是迎财神的日志&#xff0c;帮我生成10秒左右的短视频&#xff0c; 体现一家3口在院子里欢庆新年&#xff0c; 孩子在院子里放鞭炮烟…

【STM32】ADC|多通道ADC采集

本次实现的是ADC实现数字信号与模拟信号的转化&#xff0c;数字信号时不连续的&#xff0c;模拟信号是连续的。 1.ADC转化的原理 模拟-数字转换技术使用的是逐次逼近法&#xff0c;使用二分比较的方法来确定电压值 当单片机对应的参考电压为3.3v时&#xff0c;0~ 3.3v(模拟信…

从零到一:基于Rook构建云原生Ceph存储的全面指南(上)

文章目录 一.Rook简介二.Rook与Ceph架构2.1 Rook结构体系2.2 Rook包含组件1&#xff09;Rook Operator2&#xff09;Rook Discover3&#xff09;Rook Agent 2.3 Rook与kubernetes结合的架构图如下2.4 ceph特点2.5 ceph架构2.6 ceph组件 三.Rook部署Ceph集群3.1 部署条件3.3 获取…

如何在本地部署deepseek?

1、打开ollama官网&#xff0c;点download&#xff08;下载需要翻墙 https://ollama.com/ 2、双击下载好的OllamaSetup.exe&#xff0c;一直点下一步即可。 3、winR 输入cmd&#xff0c;打开命令提示符&#xff0c;输入ollama。有以下提示即安装完成。 4、可以根据 nvidia-…

团结引擎 OpenHarmony 平台全面支持 UAAL,实现引擎能力嵌入原生应用

团结引擎1.4版本已于近日正式发布&#xff01;在这一版本中&#xff0c;OpenHarmony 平台迎来了一个具有里程碑意义的更新&#xff1a;全面支持 Used as a Library&#xff08;UAAL&#xff09;。UAAL 这一技术方案&#xff0c;具有将引擎嵌入原生应用的独特能力&#xff0c;其…

【DeepSeek】在本地计算机上部署DeepSeek-R1大模型实战(完整版)

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈人工智能与大模型应用 ⌋ ⌋ ⌋ 人工智能&#xff08;AI&#xff09;通过算法模拟人类智能&#xff0c;利用机器学习、深度学习等技术驱动医疗、金融等领域的智能化。大模型是千亿参数的深度神经网络&#xff08;如ChatGPT&…

【Elasticsearch】Elasticsearch检索方式全解析:从基础到实战(二)

接着上一篇文章&#xff1b;我们继续来研究es的复杂检索 文章目录 (1) bool用来做复合查询&#xff08;2&#xff09;Filter【结果过滤】&#xff08;3&#xff09;term&#xff08;4&#xff09;Aggregation&#xff08;执行聚合&#xff09; (1) bool用来做复合查询 复合语…

如何使用DiskGenius做备份并且恢复?

如何使用DiskGenius做备份并且恢复&#xff1f; 前言 前言 此操作适用于将1台旧电脑的数据迁移到新电脑上 一、进入PE使用DG分区进行备份镜像 二、分区备份 1选择要操作的硬盘——2选择操作分区——3备份分区 1选择文件路径&#xff08;保存pmf文件的位置选择存到U盘中&…

ZZNUOJ(C/C++)基础练习1091——1100(详解版)⭐

目录 1091 : 童年生活二三事&#xff08;多实例测试&#xff09; C C 1092 : 素数表(函数专题&#xff09; C C 1093 : 验证哥德巴赫猜想&#xff08;函数专题&#xff09; C C 1094 : 统计元音&#xff08;函数专题&#xff09; C C 1095 : 时间间隔&#xff08;多…

【Spring AI】基于SpringAI+Vue3+ElementPlus的QA系统实现一

整理不易&#xff0c;请不要吝啬你的赞和收藏。 1. 前言 这是 SpringAI 系列的第二篇文章&#xff0c;这篇文章将介绍如何基于 RAG 技术&#xff0c;使用 SpringAI Vue3 ElementPlus 实现一个 Q&A 系统。本文使用 deepseek 的 DeepSeek-V3 作为聊天模型&#xff0c;使用…

【Vue】在Vue3中使用Echarts的示例 两种方法

文章目录 方法一template渲染部分js部分方法一实现效果 方法二template部分js or ts部分方法二实现效果 贴个地址~ Apache ECharts官网地址 Apache ECharts示例地址 官网有的时候示例显示不出来&#xff0c;属于正常现象&#xff0c;多进几次就行 开始使用前&#xff0c;记得先…