深入探究 JVM 频繁 Full GC 的排查过程

1. 引言

在当今软件开发领域,Java语言以其跨平台性、面向对象、高性能等特点成为了广泛应用的首选之一。而Java应用程序的核心执行环境就是Java虚拟机(JVM),它负责将Java字节码翻译成机器码并执行,是Java程序运行的基础。在JVM的内存管理机制中,垃圾回收(GC)是一个至关重要的部分,负责释放不再被引用的对象占用的内存空间,以确保应用程序的稳定性和性能。

然而,在JVM的垃圾回收过程中,如果频繁发生 Full GC(Full Garbage Collection),即对整个堆内存进行清理,会对系统性能和稳定性产生严重的影响。Full GC通常会导致应用程序的停顿时间变长,给用户带来不好的体验,甚至在极端情况下可能导致应用程序的崩溃。

因此,对于频繁 Full GC 的排查过程成为了Java开发人员必须要面对和解决的一个重要问题。本文将深入探讨如何通过监控和日志分析、内存泄漏排查、代码审查与优化、JVM参数调优等一系列手段来解决频繁 Full GC 的问题,以及如何通过定期维护与监控来预防和应对这一问题。

2. 监控和日志分析

监控工具的选择与配置:

选择合适的监控工具是排查频繁 Full GC 的第一步。常用的监控工具包括JConsole、VisualVM、Grafana等。这些工具可以提供关于JVM运行状态、内存使用情况、垃圾回收行为等方面的详细信息。在选择监控工具时,需要考虑其对应用程序性能的影响以及监控信息的全面性和准确性。配置监控工具时,需要确保监控数据的采集频率和存储方式符合实际需求,同时也要注意对敏感信息的保护。

分析 GC 日志:

启用GC日志是分析JVM内存管理行为的重要手段之一。通过设置JVM参数,可以将GC日志输出到文件中,以便后续分析。GC日志中包含了每次垃圾回收的详细信息,包括GC类型、回收时间、回收前后的堆内存情况等。在分析GC日志时,可以通过工具如GCViewer、GCEasy等进行可视化分析,也可以手动解读日志内容来深入了解GC行为和可能存在的问题。

分析应用程序的内存使用情况:

除了监控JVM本身的内存使用情况,还需要分析应用程序的内存使用情况,包括堆内存、非堆内存、永久代(或者元空间)等。通过工具如HeapDump分析工具、VisualVM等,可以生成应用程序的内存快照,并查看各个对象的引用关系和内存占用情况。这有助于识别可能存在的内存泄漏问题或者内存占用过高的情况,从而有针对性地进行优化。

综上所述,监控工具和日志分析是排查频繁 Full GC 的关键步骤之一。通过选择合适的监控工具、启用GC日志以及分析应用程序的内存使用情况,可以深入了解JVM的内存管理行为,发现可能存在的问题,并采取相应的措施进行优化和修复。

3. 内存泄漏排查

内存泄漏的定义和识别:

内存泄漏是指程序中已不再使用的对象仍然占用内存,无法被垃圾回收机制释放,最终导致内存消耗过多,甚至导致系统崩溃。内存泄漏通常由于对对象的引用未正确释放而造成。识别内存泄漏通常需要观察系统的内存占用情况,当发现内存占用逐渐增加而未能回收时,就可能存在内存泄漏问题。

使用工具定位内存泄漏:

定位内存泄漏是解决频繁 Full GC 的关键一步。常用的工具包括MAT(Memory Analyzer Tool)、VisualVM等。这些工具可以生成内存快照,并分析对象的引用关系和内存占用情况,帮助开发人员快速定位内存泄漏的原因和位置。其中,MAT可以通过分析内存快照来找出存在内存泄漏的对象,VisualVM则可以实时监控内存使用情况,并定位内存泄漏的热点。

分析泄漏原因:

内存泄漏的原因多种多样,常见的包括对象生命周期过长、静态集合未清理、循环引用等。通过分析对象的引用链,可以找出造成内存泄漏的根本原因。例如,检查是否存在长期存活的对象引用,或者检查是否存在静态集合未被清理的情况。另外,还需要注意对象的生命周期,确保对象在不再使用时能够被正确释放。

综上所述,内存泄漏排查是解决频繁 Full GC 问题的重要一环。通过使用专业的工具定位内存泄漏,并分析泄漏的原因,可以有效地解决内存泄漏问题,提升系统的稳定性和性能。同时,还需要开发人员在编写代码时注意内存管理的规范,避免造成内存泄漏的情况发生。

4. 代码审查与优化

在排查频繁 Full GC 的过程中,进行代码审查和优化是至关重要的一步。优化代码可以减少对象的创建和销毁频率,降低内存压力,从而减少 Full GC 的发生频率。

检查代码中的常见内存泄漏问题:

  1. 静态集合:静态集合可能导致对象长期存活,无法被垃圾回收。应该避免使用静态集合,或者在不再需要时手动清空集合。

  2. 长期存活的对象引用:某些对象可能被长期引用而无法被回收,比如单例模式中的对象、线程池等。需要审查这些对象的生命周期,确保它们在不再需要时能够被正确释放。

优化代码以减少对象创建和销毁的频率:

  1. 对象池技术:通过对象池技术,可以重复利用对象,减少对象的创建和销毁开销,从而减轻GC的压力。

  2. 缓存数据:对于一些频繁使用的数据,可以将其缓存起来,避免重复创建和销毁,从而降低内存占用。

使用合适的数据结构和算法来减少内存占用:

  1. 选择合适的集合类:根据实际需求选择合适的集合类,避免使用过大或不必要的集合,如使用ArrayList时应注意容量的控制。

  2. 空间换时间:在某些情况下,可以通过牺牲部分内存空间来换取执行效率,比如使用HashMap代替ArrayList+查找,以提高查找效率。

综上所述,通过对代码进行审查和优化,可以有效地减少内存泄漏问题和对象创建销毁频率,从而降低系统的内存压力,减少频繁 Full GC 的发生。同时,选择合适的数据结构和算法也可以降低内存占用,提高系统的性能和稳定性。

5. JVM 参数调优

JVM参数调优是优化应用程序性能和减少频繁 Full GC 的关键步骤之一。合理地调整堆内存大小、选择合适的GC算法和收集器、调整新生代和老年代的比例等参数,可以有效地降低Full GC的频率,提升系统的性能和稳定性。

根据应用程序的特性调整堆内存大小和其他 JVM 参数:

  1. 堆内存大小(-Xms和-Xmx):通过调整堆内存的初始大小和最大大小,可以避免频繁的内存扩容和收缩,减少Full GC的发生。根据应用程序的特性和负载情况,合理地设置堆内存大小。

  2. 新生代和老年代的比例(-XX:NewRatio和-XX:SurvivorRatio):根据应用程序的对象创建和销毁模式,调整新生代和老年代的比例,使其更加适合应用程序的内存需求,减少Full GC的发生。

  3. 永久代/元空间大小(-XX:MaxPermSize或-XX:MaxMetaspaceSize):永久代(在JDK8之前)或元空间(在JDK8及之后)用于存放类的元数据和常量池等信息,过小的永久代/元空间可能导致类加载过程中出现内存溢出,从而触发Full GC。因此,根据应用程序的类加载情况,适当地调整永久代/元空间的大小。

选择合适的 GC 算法和收集器:

  1. GC算法:根据应用程序的特性和硬件环境选择合适的GC算法,如Serial GC、Parallel GC、CMS GC、G1 GC等。不同的GC算法适用于不同的场景,需要根据应用程序的内存使用情况和性能需求进行选择。

  2. GC收集器:在选择GC算法的基础上,进一步选择合适的GC收集器。比如,在JDK8及之后,G1 GC通常被认为是一种更加先进和适用于大型应用程序的收集器,它具有更好的吞吐量和低停顿时间。

调整新生代和老年代的比例,以及 Eden 区和 Survivor 区的大小:

  1. 新生代和老年代的比例(-XX:NewRatio和-XX:SurvivorRatio):通过调整新生代和老年代的比例,可以更好地满足应用程序的内存需求,减少Full GC的发生。

  2. Eden区和Survivor区的大小(-XX:InitialSurvivorRatio和-XX:MaxTenuringThreshold):通过调整Eden区和Survivor区的大小,可以更好地管理对象的存活周期,减少对象晋升到老年代的频率,从而降低Full GC的发生。

综上所述,通过合理地调整JVM参数,可以有效地降低Full GC的发生频率,提升系统的性能和稳定性。在调优过程中,需要根据应用程序的特性和负载情况,综合考虑各个参数的影响,进行适当的调整。

6. 避免过度使用 Finalizer

Finalizer是Java语言中的一个特殊方法,用于在对象被垃圾回收前执行一些清理操作。然而,过度使用Finalizer可能导致一系列问题,包括性能下降、内存泄漏、不可预测的行为等,因此在实践中应该谨慎使用Finalizer,甚至尽量避免。

Finalizer 的工作原理和影响:

  1. 工作原理:Finalizer方法由垃圾收集器在对象被回收前调用,允许对象执行一些清理操作,比如关闭文件、释放资源等。

  2. 影响:Finalizer的调用会导致对象的终结处理,这可能导致性能下降,尤其是在大量对象被回收时,Finalizer方法的执行会增加系统开销,降低系统的响应速度。此外,Finalizer的执行时机不确定,可能导致对象的资源无法及时释放,从而引发内存泄漏等问题。

减少或避免使用 Finalizer 来释放资源:

  1. 显式释放资源:在使用外部资源时,应该显式地释放资源,而不是依赖Finalizer来释放资源。比如,使用try-with-resources语句或手动释放资源。

  2. 使用弱引用或软引用:如果确实需要在对象被回收时执行一些清理操作,可以考虑使用弱引用或软引用,而不是依赖Finalizer。这样可以避免Finalizer的不可预测性和性能问题。

  3. 使用对象池技术:对于一些需要频繁创建和销毁的对象,可以考虑使用对象池技术,重复利用对象,减少对象的创建和销毁开销,从而避免Finalizer的调用。

  4. 避免在Finalizer中执行复杂操作:Finalizer方法的执行会增加系统开销,因此应该尽量避免在Finalizer中执行复杂的操作,比如IO操作、数据库连接等,以减少Finalizer的影响。

综上所述,过度使用Finalizer可能导致一系列问题,因此在实践中应该谨慎使用Finalizer,尽量避免依赖Finalizer来释放资源。通过显式释放资源、使用弱引用或软引用、使用对象池技术等手段,可以避免Finalizer可能带来的性能问题和内存泄漏等风险。

7. 外部资源管理

外部资源如文件句柄、数据库连接等在Java应用中占据重要地位,有效管理这些资源对于系统的稳定性和性能至关重要。在处理外部资源时,应该遵循一些最佳实践来确保资源的及时释放和系统的稳定性。

及时释放外部资源:

  1. 关闭文件句柄:在使用文件操作完成后,应该及时关闭文件句柄,以释放系统资源。通常可以使用try-with-resources语句来确保文件句柄在使用完成后自动关闭。

  2. 释放数据库连接:在使用数据库连接完成后,应该手动释放数据库连接,以避免连接泄漏和数据库资源耗尽的问题。可以在finally块中释放数据库连接,确保无论是否发生异常都能够释放连接。

使用 try-with-resources 或者手动释放资源:

  1. try-with-resources:try-with-resources语句是Java 7引入的一种自动资源管理方式,能够在try代码块结束后自动释放资源,减少代码的复杂度和错误处理的难度。

    try (FileInputStream fis = new FileInputStream("file.txt");FileOutputStream fos = new FileOutputStream("output.txt")) {// 执行文件操作
    } catch (IOException e) {// 异常处理
    }
    
  2. 手动释放资源:在Java 7之前,手动释放资源是一种常见的做法,可以在finally块中手动释放资源,确保资源得到及时释放。

    FileInputStream fis = null;
    try {fis = new FileInputStream("file.txt");// 执行文件操作
    } catch (IOException e) {// 异常处理
    } finally {if (fis != null) {try {fis.close();} catch (IOException e) {// 异常处理}}
    }
    

资源管理的最佳实践:

  1. 使用try-with-resources语句来管理资源:try-with-resources语句能够自动释放资源,简化了资源管理的代码。

  2. 及时释放资源:在使用完资源后,应该及时释放资源,避免资源泄漏和系统资源耗尽的问题。

  3. 异常处理:在资源释放的过程中,需要注意异常的处理,确保资源的正确释放并处理可能的异常情况。

  4. 使用连接池技术:对于一些需要频繁创建和销毁的资源,如数据库连接,可以考虑使用连接池技术,重复利用资源,减少资源的创建和销毁开销。

  5. 编写单元测试:编写单元测试来确保资源管理的正确性,尤其是在释放资源的过程中要确保没有资源泄漏和异常情况。

综上所述,有效管理外部资源对于系统的性能和稳定性至关重要。通过合理使用try-with-resources语句或手动释放资源,并遵循资源管理的最佳实践,可以有效地管理外部资源,提升系统的性能和稳定性。

8. 集成测试与性能测试

集成测试和性能测试是评估应用程序在实际使用环境中表现的关键步骤。通过这些测试,可以发现系统的瓶颈和性能问题,为进一步优化系统性能提供重要参考。以下是关于集成测试和性能测试的详细内容:

编写集成测试用例来模拟实际场景:

  1. 场景覆盖:编写集成测试用例时,应该覆盖系统中的各种典型和边界情况,确保测试能够全面覆盖系统的功能。

  2. 数据准备:准备测试数据是集成测试的重要环节,需要确保测试数据的真实性和多样性,以模拟真实的使用场景。

  3. 模拟外部依赖:在集成测试中,可能涉及到外部服务或依赖,可以使用模拟工具或框架来模拟这些外部依赖,保证测试的独立性和可控性。

运行性能测试以评估应用程序在不同负载下的表现:

  1. 负载生成:根据系统的预期使用情况和性能指标,设计合适的负载模型和测试场景,使用性能测试工具生成负载,模拟多种并发用户操作。

  2. 性能指标:在性能测试过程中,需要关注系统的各项性能指标,如响应时间、吞吐量、并发用户数、CPU利用率等,以便全面评估系统性能。

  3. 性能监控:在进行性能测试时,应该实时监控系统的运行情况和性能指标,及时发现问题并进行调整。

分析测试结果并针对性地进行优化:

  1. 性能分析:对性能测试结果进行分析,找出系统的瓶颈和性能问题,确定优化的方向和重点。

  2. 优化策略:根据性能分析的结果,制定相应的优化策略,可以从代码优化、架构调整、资源配置等方面入手。

  3. 重复测试:在进行优化之后,需要重新运行性能测试,验证优化效果,并进一步调整和优化系统。

集成测试和性能测试的注意事项:

  1. 自动化测试:尽可能地使用自动化测试工具和框架进行集成测试和性能测试,提高测试效率和可重复性。

  2. 场景模拟:在编写集成测试用例和设计性能测试场景时,要尽可能地模拟真实的使用场景和负载情况,以保证测试的真实性和可靠性。

  3. 持续集成:将集成测试和性能测试纳入到持续集成流程中,确保每次代码提交都能够进行全面的测试,及时发现问题并进行修复。

通过有效的集成测试和性能测试,可以全面评估系统的功能和性能,并找出系统的瓶颈和性能问题,为系统的优化和调优提供重要参考。

9. 定期维护与监控

定期维护和监控是保持应用程序高性能和稳定运行的关键。通过建立监控系统和定期维护,可以及时发现问题并进行优化,确保系统始终处于最佳状态。

建立监控系统,定期检查 JVM 运行状况和内存使用情况:

  1. 监控工具选择:选择适合的监控工具,如Prometheus、Grafana等,用于监控JVM的运行状态、内存使用情况、线程情况等指标。

  2. 指标定义:定义关键的监控指标,如内存使用率、CPU利用率、GC频率、线程数量等,以便及时发现异常情况。

  3. 报警设置:根据监控指标设置报警规则,当指标超过阈值时及时发送警报,以便运维人员及时响应和处理。

  4. 定期巡检:定期对监控系统进行巡检,检查监控指标是否正常,及时发现并解决监控系统本身的问题。

定期进行性能调优和代码优化:

  1. 定期审查:定期审查应用程序的代码和架构,寻找可能存在的性能瓶颈和优化空间。

  2. 性能分析:使用性能分析工具对系统进行性能分析,找出性能瓶颈,为优化提供依据。

  3. 优化策略:根据性能分析结果,制定相应的优化策略,可能涉及代码优化、资源调整、算法改进等。

  4. 版本更新:定期更新应用程序的版本和依赖库,以获取最新的功能和性能优化。

及时响应异常和报警信息:

  1. 报警处理:对于监控系统发出的报警信息,运维人员应该及时响应,快速定位问题,并采取相应的措施进行处理。

  2. 问题追踪:对于发生的异常情况和问题,需要进行详细的问题追踪和分析,找出根本原因,并采取措施防止问题再次发生。

  3. 持续改进:对于频繁发生的问题,需要进行持续改进和优化,以提高系统的稳定性和可靠性。

通过定期维护和监控,可以保证应用程序始终处于最佳状态,及时发现和解决问题,提高系统的稳定性和性能。

10. 结语

在本文中,我们深入探讨了排查频繁 Full GC 的过程和方法,这对于保证Java应用程序的性能和稳定性至关重要。通过对JVM的监控和日志分析,我们能够了解应用程序的内存使用情况,发现潜在的内存泄漏问题。同时,通过代码审查与优化,我们可以消除常见的内存泄漏源,并优化代码以减少内存占用。合理调优JVM参数,避免过度使用Finalizer,以及及时释放外部资源,都是提高应用程序性能和稳定性的关键步骤。

集成测试和性能测试是评估应用程序性能的重要手段,通过模拟实际场景和不同负载下的测试,我们可以更好地了解应用程序的表现,并对其进行优化。定期维护与监控则是保持应用程序高性能和稳定运行的关键。建立监控系统,定期进行性能调优和代码优化,及时响应异常和报警信息,都是确保应用程序始终处于最佳状态的重要步骤。

最后,我们强调了持续优化和监控的重要性,并鼓励在实践中不断学习和尝试新的方法。只有不断地改进和优化,我们才能保证应用程序始终保持高性能、高可用性和高稳定性,满足用户的需求并赢得用户的信任。愿本文能为您在排查频繁 Full GC 问题上提供一些有价值的参考和帮助。

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

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

相关文章

二手货wordpress企业网站主题模板

二手车wordpress主题模板 简洁的二手车wordpress主题模板,适合做二手车业务的公司官方网站使用。 https://www.jianzhanpress.com/?p3473 wordpress二手物资回收主题 绿色wordpress二手物资回收主题,用于二手物资回收公司WP建站使用。 https://www.…

自动化行业文件数据\资料防泄密软件——天锐绿盾|@德人合科技

天锐绿盾是一款自动化行业文件数据防泄密软件,由德人合科技提供。该软件采用动态加解密技术,能够有效防止公司内部数据泄密,同时支持各种文件格式加密,如CAD、OFFICE、PDF、图纸等。 PC端:https://isite.baidu.com/sit…

git如何保留提交记录的情况下迁移

Git仓库迁移方案 在日常的工作场景中,我们有时候会遇到需要更换Git仓库地址的需求。或者是从一个git仓库托管工具换到另一个git仓库托管工具。这个时候有两种方案: 方案一:不保留历史提交记录 如果你不需要保留原有的历史提交记录&#xf…

Linux RocketMQ 安装及卸载(附控制台搭建)

一、前言 在安装 RocketMQ 前需要确保 JDK 已安装并正确配置环境变量 二、下载安装 1.下载 下载 | RocketMQ 2.安装 # 打开存放目录 cd /usr/local # 创建目录 mkdir rocketMQ # 进入目录 cd rocketMQ # 把下载的压缩包上传到 rocketMQ 目录中 # 解压 $ unzip rocketmq-all-…

备战蓝桥杯 Day12(二维费用背包+分组背包)

二进制分解多重背包 269:【例9.13】庆功会 【题目描述】 为了庆贺班级在校运动会上取得全校第一名成绩,班主任决定开一场庆功会,为此拨款购买奖品犒劳运动员。期望拨款金额能购买最大价值的奖品,可以补充他们的精力和体力。 #inc…

高级RAG:揭秘PDF解析

原文地址:https://pub.towardsai.net/advanced-rag-02-unveiling-pdf-parsing-b84ae866344e 2024 年 2 月 3 日 附加内容:揭秘PDF解析:如何从科学pdf论文中提取公式 对于RAG,从文档中提取信息是一个不可避免的场景。确保从源头…

Flutter学习6 - Dart 类与对象

1、面向对象编程(Object-Oriented Programming, OOP)三大特征 (1)封装 封装是指将对象的状态(属性)和行为(方法)封装在一起,对外部隐藏对象的内部细节,只提…

#LLM入门|Prompt#1.1 第一部分_面向开发者的LLM入门教程_简介

Prompt工程:解锁大语言模型潜能的关键技巧 随着大语言模型(LLM)的兴起,Prompt工程已成为开发者利用LLM构建功能强大应用的关键技能。在这个新时代,Prompt不仅是指导LLM的输入形式,更是塑造其能力上限与下限…

Python 在Word中创建表格并填入数据、图片

在Word中,表格是一个强大的工具,它可以帮助你更好地组织、呈现和分析信息。本文将介绍如何使用Python在Word中创建表格并填入数据、图片,以及设置表格样式等。 Python Word库: 要使用Python在Word中创建或操作表格,需…

OpenCV 4基础篇| OpenCV图像基本操作

目录 1. 图像读取1.1 cv2.imread() 不能读取中文路径和中文名称1.2 cv2.imdecode() 可以读取中文路径和中文名称 2. 图像的显示2.1 openCV显示图像 cv2.imshow()2.2 matplotlib显示图像 plt.imshow() 3. 图像的保存 cv2.imwrite()4. 图像的复制4.1 img.copy()4.2 np.copy()4.3 …

【C++STL】STL容器详解

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

RabbitMQ 网络分区处置策略配置

概述 集群成员之间的网络连接故障会影响客户端操作的数据一致性和可用性&#xff08;如CAP定理&#xff09;。 由于不同的应用程序对一致性有不同的要求 并且可以容忍不同程度的不可用&#xff0c;可以使用不同的分区处理策略。 检测网络分区 节点确定其对等节点是否关闭&am…

个性化纹身设计,Midjourney带你探索独一无二的艺术之美

hello,大家好&#xff0c;欢迎回来。 在当今社会&#xff0c;纹身已经变得非常常见。 在寻求与众不同的个性化纹身时&#xff0c;你是否曾经为了找不到独特的设计而苦恼&#xff1f; 现在&#xff0c;Midjourney将为你打开一扇全新的艺术之门&#xff0c;引领你探索纹身设计…

高通 Android 12 Settings不显示版本号问题

1、最近项目遇到一个奇葩问题&#xff0c;编译系统版本号不见了&#xff1f; 2、一开始我想着可能是自己代码没有make clean结果编译几个小时&#xff0c;然后烧录固件发现还是未生效。 3、然后这时候我又去看git log review最近修改也没有太大发现&#xff08;待定&#xff…

docker安装flink

docker安装flink 5.1、拉取flink镜像&#xff0c;创建网络 docker pull flink docker network create flink-network5.2、创建 jobmanager # 创建 JobManager docker run \-itd \--namejobmanager \--publish 8081:8081 \--network flink-network \--env FLINK_PROPERTIES&…

第一篇:大纲

目录 第一篇&#xff1a;大纲 第二篇&#xff1a;CamX初认识(框架、代码结构介绍) 第三篇&#xff1a;CamX日志打印系统 第四篇&#xff1a;CamX确认当前选择的usecase、pipeline、sensormode 第五篇&#xff1a;CamX添加自定义node 第六篇&#xff1a;CamX添加自定义ven…

ArcgisForJS如何在线编辑ArcGIS Server发布的几何要素?

文章目录 0.引言1.ArcGIS创建几何要素2.ArcGIS Server发布几何要素3.ArcgisForJS在线编辑ArcGIS Server发布的几何要素 0.引言 ArcGIS For JS 是一种用于创建和编辑地理信息的 JavaScript 库&#xff0c;它允许用户在线编辑 ArcGIS Server 发布的几何要素。本文从ArcGIS创建几…

07 MyBatis之高级映射 + 懒加载(延迟加载)+缓存

1. 高级映射 例如有两张表, 分别为班级表和学生表 自然, 一个班级对应多个学生 像这种数据 , 应该如果如何映射到Java的实体类上呢? 这就是高级映射解决的问题 以班级和学生为例子 , 因为一个班级对应多个学生 , 因此学生表中必定有一个班级编号字段cid 但我们在学生的实体…

Yolov9全文翻译!

Yolo v9全文翻译 论文链接&#xff1a;&#x1f47f; YOLOv9: Learning What You Want to Learn Using Programmable Gradient Information 代码链接&#xff1a;&#x1f47f; https://github.com/WongKinYiu/yolov9/tree/main 大量图片来袭&#xff01;

为什么说抖店适合电商新手入局?门槛及运营玩法,今天一文详解!

大家好&#xff0c;我是电商小布。 现在&#xff0c;越来越多的人开始加入到了电商这个行业&#xff0c;原因就是看到了它发展的可能性。 而抖音小店这个项目&#xff0c;作为近几年发展势头非常猛的电商项目&#xff0c;成为了很多小伙伴们的首选。 为什么会这样呢&#xf…