Mac下JMeter入门:从Java环境到性能压测全流程

"Mac下Jmeter的入门级操作"——说实话,第一次在Mac上打开JMeter的人,十个有九个会卡在安装或Java版本上,剩下那一个卡在界面看不懂。作为一个踩过不少坑的测试老兵,我来把从零开始到跑通第一个压测脚本的全过程捋一遍,能帮你省下至少半天查资料的时间。

JMeter是Apache家的开源性能测试工具,基于Java开发,所以理论上只要有Java环境就能跑。但Mac环境跟Windows有差异,加上JMeter本身的配置项不少,很多新手上来就被目录结构搞晕了。这篇文章适合完全没接触过JMeter的小白,也适合在Windows上用过、刚切到Mac的人。我会从环境准备讲到跑通脚本,再到分析测试结果,每一步都给出可以直接抄的配置和命令。

1. 装好JMeter之前,先把Java环境捋清楚

1.1 JDK版本怎么选,直接决定JMeter能不能启动

Mac上装JMeter,第一步其实是装JDK。很多人栽跟头就栽在版本上——JMeter 5.x系列要求JDK 8及以上,但JDK 17开始有些旧版JMeter会启动失败或报模块错误。我个人的建议是:如果你用的是JMeter 5.4以上,直接装JDK 11或17都行;如果还在用5.1、5.2这种老版本,老老实实用JDK 8。

在Mac上查看当前Java版本很简单,打开终端输入:

java -version

如果提示找不到命令,说明还没装JDK。安装JDK我建议直接用Homebrew,省得去官网手动下载再配环境变量:

brew install openjdk@11

装完之后需要做个软链,让系统找到Java命令:

sudo ln -sfn /opt/homebrew/opt/openjdk@11/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk-11.jdk

这里有个关键点需要你留意:不同芯片的Mac,Homebrew的安装路径不一样。Intel Mac是/usr/local/opt/,M系列芯片是/opt/homebrew/opt/。如果你按网上的教程执行了软链但java -version还是报错,先确认你是哪种机型,再去对应路径下找openjdk目录。

1.2 用Homebrew安装JMeter,还是手动下载

两者的选择不是一个非此即彼的问题,关键看你后续想不想折腾扩展包。Homebrew方式最省事:

brew install jmeter

装好后直接终端输入jmeter就能启动图形界面。但Homebrew版本有个小坑:它默认不带某些可选插件,比如JMeter Plugins Manager,后面如果你需要像jpgc系列插件做阶梯加压,还得手动补。

手动下载方式更灵活。从Apache官网下载apache-jmeter-5.x.tgz压缩包,解压后放到你想要的目录,比如/Users/你的用户名/Applications/。然后编辑用户目录下的.bash_profile或.zshrc:

export JMETER_HOME=/Users/你的用户名/Applications/apache-jmeter-5.6.2 export PATH=$JMETER_HOME/bin:$PATH

注意,M系列Mac默认用的是zsh,配置文件是.zshrc;老一点的系统用bash,配置文件是.bash_profile。改完文件后执行source ~/.zshrc使其生效。

提示:如果你只是临时用一下,不想改配置文件,可以直接进到JMeter解压目录的bin/文件夹下,运行sh jmeter或双击jmeter脚本启动。什么都不需要配置,JMeter自带参数。

2. 第一次打开JMeter,界面和核心概念必须搞懂

2.1 JMeter的目录结构,不只是bin目录

JMeter解压后,有几个目录你需要心中有数:

  • bin/:存放启动脚本(jmeter、jmeter.sh)、配置文件(jmeter.properties、user.properties)等。
  • lib/:存放所有依赖JAR包,自定义插件放到lib/ext/下(后续装插件就丢这里)。
  • docs/:本地文档。
  • extras/:一些辅助脚本和构建文件。

配置文件我重点说下jmeter.properties,里面全是JMeter的行为开关。最常改的几个参数包括:

# 界面语言,强行设定为中文 language=zh_CN # 响应数据默认编码,解决乱码 sampleresult.default.encoding=UTF-8

初学者可以先不用动这个文件,直接在GUI里通过"选项 → 语言"切换界面语言。但如果想彻底解决中文乱码,后面我还会再聊。

2.2 测试计划、线程组、Sampler、监听器之间的关系

打开JMeter后,左边是一个树形导航,右边是配置面板,这个"树"就是整个测试计划的骨架。你需要理解四个核心组件的定位:

  • 测试计划(Test Plan):最大的容器。你所有配置都在它下面。可以在这里设置用户自定义变量,比如服务器地址、端口号、账号密码。
  • 线程组(Thread Group):模拟一群用户。你可以理解为"并发用户池",它决定了用户数、多长时间内发起、执行几轮。
  • Sampler:真正干活的东西,负责发请求。最常用的是HTTP请求采样器,还有JDBC请求、TCP取样器、JSR223取样器等。
  • 监听器(Listener):负责展示结果。查看结果树能看到每个请求的详细响应,聚合报告能看到平均响应时间、吞吐量这些关键指标。

它们的关系可以用一个生活类比:测试计划是一张餐厅菜单,线程组是一群饥饿程度不同的顾客,Sampler是服务员递出去的一张张点菜单,监听器则是厨房门口的电子屏,实时显示每桌菜做了多久、有没有做错。

3. 动手做一个最简单的接口压测,5分钟跑通

3.1 从创建测试计划到添加线程组

打开JMeter后,默认就有一个测试计划。右键测试计划 → 添加 → 线程(用户) → 线程组,把线程组加进去。打开线程组配置面板,我们先用一组很保守的参数:

  • 线程数:10
  • Ramp-up时间(秒):5
  • 循环次数:2

意思就是:在5秒内陆续启动10个线程,每个线程执行2次请求,总共产生20次请求。先不追求高并发,重点是确认脚本流程走得通。

3.2 配置HTTP请求采样器,端点怎么填

右键线程组 → 添加 → 取样器 → HTTP请求,然后配置这些字段:

  • 协议:http(如果你测试的服务是HTTPS,改成https)
  • 服务器名称或IP:localhost,或者你测试环境的域名
  • 端口号:8080,Spring Boot默认端口就是8080
  • 路径:/api/users,按你实际接口路径填
  • HTTP请求方法:GET、POST等,按接口需求选
  • 参数:如果是GET请求,可以直接在路径后面拼?id=1;如果是POST请求,切换到"消息体数据"标签,填入JSON字符串

举一个我实际用过的例子,假设被测服务是本地的某个模拟项目X,提供一个用户登录接口,请求体是JSON:

{"username": "admin", "password": "123456"}

那HTTP请求采样器就这么配:服务器名填localhost,端口填8080,HTTP请求方法选POST,路径填/api/login,消息体数据里粘贴上面的JSON。注意需要在"HTTP请求"的"参数"标签旁边找到消息体数据标签,如果没看到,可能是JMeter版本问题,或者需要先点一下参数标签旁边的另一个标签。

3.3 添加查看结果树和聚合报告,第一次运行

右键线程组 → 添加 → 监听器 → 查看结果树,再添加一个聚合报告。点击顶部工具栏的绿色三角形按钮(或者按Cmd + R),测试就会跑起来。

跑完之后,查看结果树会列出每个请求的状态,绿色表示成功,红色表示失败。点开一条请求,能看到请求头、请求体、响应头、响应数据。聚合报告则给出了更宏观的指标:

指标含义关注点
Samples总请求数确认执行数量和预期一致
Average平均响应时间(毫秒)越低越好,反应了服务端处理能力
Min / Max最小/最大响应时间结合平均值看抖动,如果Max远大于Average,说明存在慢请求
Std. Dev.标准差值越大表示响应时间波动越大,性能越不稳定
Error %错误率压测红线指标之一,一般要求低于0.1%
Throughput吞吐量(每秒请求数)系统能支撑的QPS

如果你看到结果是红色,不要慌,先在查看结果树里看下响应体的内容。最常见的失败原因是:URL配错了、服务没启动、缺少必要的请求头。比如POST的JSON接口往往需要加Content-Type: application/json请求头,你可以在HTTP请求下右键添加"配置元件 → HTTP信息头管理器",然后添加一行:

Content-Type: application/json

4. 线程组参数背后的门道,别只会填数字

4.1 线程数、Ramp-Up时间、循环次数怎么配才算合理

这三个参数是压测设计里最容易出错的地方。

  • 线程数:模拟的用户数量。但注意,它不等于"QPS",因为一个用户可能在一个长时间接口上等待很久,吞吐量反而上不去。
  • Ramp-Up时间:所有线程启动完成需要的时间。作用是"渐进加压",避免瞬间把服务打挂。比如线程数100,Ramp-Up设为10秒,就是平均每秒启动10个线程。
  • 循环次数:每个线程执行请求的轮数。如果勾选了"永远",测试就会一直跑,需要手动停止。

真实压测时,我习惯用这样的思路:先小线程数、短时间跑通脚本,再用目标并发数的50%做预热,最后在监控端盯CPU和内存的前提下逐步加压到目标值。线程数 × 循环次数就是总请求数,而如果要测持续时间,就不设循环次数,勾选底部的"调度器",设置持续时间(秒),比如600秒,这样就能做10分钟稳定性压测。

4.2 调度器的使用场景

调度器是JMeter里一个很多人忽略的选项。勾选后可以设置两个参数:持续时间(秒)和启动延迟(秒)。

  • 持续时间:整个测试执行多久,常用于稳定性测试。
  • 启动延迟:测试开始后延迟多久再启动线程,常用于配合其他准备动作。

举例:你想测试一个系统在高负载下运行30分钟是否有内存泄漏,就把线程数设成50、循环次数勾选"永远"、勾选调度器、持续时间填1800。跑完后JMeter自动停止,聚合报告会给出30分钟内的平均指标,非常有说服力。

5. 断言让测试结果真正有说服力

5.1 响应断言的基本配置

查看结果树只是"把结果显示出来",它不判断对错——只要拿到HTTP响应,哪怕是500错误,JMeter也认为这是一个"成功"的请求。所以必须加断言。

右键HTTP请求 → 添加 → 断言 → 响应断言,然后配置:

  • 响应文本:勾选响应文本,在右侧文本框中输入期望出现的字符串,比如"code": 0或者"token"。
  • 如果响应是JSON,建议先确认里面一定包含某个字段,再写断言。比如登录接口返回一个token字段,就在断言里写"token",注意包含双引号更精确。
  • 匹配规则:选择包含,意思是响应文本里只要出现这个字符串就通过。

再配合监听器断言结果,就能直观看到哪些请求断言通过了、哪些没通过。举个例子,接口返回{"code": 500, "msg": "error"},但HTTP状态码是200,如果没有断言,JMeter会认为请求成功,最后报告的错误率是全绿的虚假数据。有了断言,发现返回内容里没有"code": 0,才能判定实际业务失败。

5.2 断言失败时如何定位问题

断言失败时,查看结果树会显示红色的请求。点开响应数据看两个点:

第一,响应体的结构。是不是加了断言字符串但人家根本不在返回里?注意大小写、空格、转义字符,JSON中的中文有时候需要精确匹配。

第二,响应头。有些接口失败时返回的不是业务JSON,而是405、403等HTTP错误页面,这时候断言响应文本仍然可能会意外通过——因为它匹配了错误页面里的某个词。所以更严谨的做法是多加几个断言条件,比如同时断言响应代码是200。

6. Mac下JMeter常见问题与排查实录

6.1 启动报错"unable to load class"和Java版本不兼容

很多人在Mac上启动JMeter时,终端弹出类似java.lang.UnsupportedClassVersionError或unable to load class的错误。原因几乎都是本机JDK版本与JMeter的编译版本不匹配。

解决办法有两步。先java -version确认版本;如果版本过高(比如JDK 20),下载JDK 11或换成新版JMeter(6.0以上对JDK 17支持良好)。如果你需要同时存在多个JDK版本,可以不改全局环境,而是在启动jmeter时指定JAVA_HOME:

JAVA_HOME=$(/usr/libexec/java_home -v 11) sh jmeter

这个命令在Mac上非常实用,它会动态找到JDK 11的路径作为JAVA_HOME启动JMeter,不影响其他应用的Java环境。

6.2 中文乱码,这个是最常见的Mac问题

Windows下往往默认GBK编码,Mac下默认UTF-8,但JMeter老版本在解析CSV参数文件或者显示响应中文时依然会出现乱码。处理方式分两类:

第一类是响应数据乱码,在jmeter.properties里找到:

sampleresult.default.encoding=UTF-8

去掉注释,确保值改成UTF-8,重启JMeter生效。

第二类是CSV文件参数乱码,比如你用CSV数据文件做参数化,文件里的中文在请求里变成乱码。解决方法是把CSV文件另存为UTF-8编码,尤其注意用"带BOM的UTF-8"格式另存时必须谨慎。我遇到过的实际案例是:Excel另存CSV时默认编码是ANSI(系统默认GBK),JMeter读取就乱码。Mac上我用Numbers或文本编辑另存为UTF-8后,乱码就消失了。

6.3 端口被占用和内存溢出

如果你测试的接口跑在8080端口,但JMeter本机上也开了其他服务占用了8080,请求就会失败。排查命令:

lsof -i :8080

找到占用进程的PID,然后kill -9 PID。另外,JMeter本身的GUI模式很吃内存,如果压测时发现卡顿或报OutOfMemoryError,需要调大JMeter堆内存。在bin/jmeter脚本里找到:

HEAP="-Xms1g -Xmx2g"

按需改成:

HEAP="-Xms2g -Xmx4g"

但提醒一句,GUI模式本身就会影响测试准确性,大量压测一定要用命令行模式。

7. 命令行模式压测和几个提高效率的小技巧

7.1 为什么压测一定要用命令行模式

GUI模式跑压测有两个致命的坑:一是图形界面本身消耗CPU和内存,影响本机压力;二是高并发下界面很容易无响应,数据丢失。

正确做法是用命令行跑。先在GUI里设计好测试计划,保存为login_test.jmx,然后到终端执行:

jmeter -n -t /path/to/login_test.jmx -l /path/to/result.jtl -e -o /path/to/result_report

参数含义拆解:

  • -n:非GUI模式。
  • -t:指定测试计划文件。
  • -l:保存原始结果到.jtl文件。
  • -e:在测试结束后生成HTML报告。
  • -o:HTML报告输出目录(需不存在或为空)。

跑完之后,打开生成目录里的index.html,能看到响应时间分布、吞吐量、活跃线程数随时间变化的图表,这份报告可以直接作为性能分析的数据源。

7.2 CSV参数化,让脚本模拟真实用户

压测如果想要更贴近真实业务,应该使用多组不同数据,而不是所有用户都用同一个账号并发。准备一个users.csv文件:

username,password user01,123456 user02,123456 user03,123456

在线程组下添加"配置元件 → CSV数据文件设置",配置文件名、变量名称填username,password,分隔符填,, 线程共享模式选所有线程。然后HTTP请求里,用户名和密码用${username}和${password}替代。这样每个线程就会按顺序读取CSV里的不同数据,避免了所有用户共用同一账号导致的服务端session串号或缓存命中等失真问题。

7.3 用好Plugins Manager,进阶压测者的利器

自带JMeter的监听器其实比较"素",如果你想要更专业的TPS图、响应时间百分位图,需要装插件。方法是在JMeter官网下载的发行包里,把plugins-manager.jar放到lib/ext目录,重启JMeter后,在选项菜单里打开Plugins Manager,勾选需要的插件包(比如jpgc - Standard Set)。安装完成后,新增的监听器会出现在对应的菜单里。

实测下来,jp@gc - Transactions per Second和jp@gc - Response Times Over Time这两张图在调优接口时非常直观。前者能看到每秒事务数在加压过程中的波动曲线,后者能看出不同时段的响应时间分布,配合瓶颈分析效率能提升不少。

我个人在这几年压测里最深的体会是:JMeter的门槛真的不高,但真正决定压测价值的,是对业务场景的理解和压测数据的解读能力。脚本只是工具,你设计了多少用户、在什么场景下加压、怎么判断失败、怎么解读吞吐量曲线,这些才是用户压测报告里最有分量的部分。Mac下跑JMeter遇到问题时,先按这个顺序排查:Java版本是否匹配、编码是否正确、端口是否被占、内存够不够。把这四个问题记在心里,你就能少走一大半弯路。

相关新闻

5分钟粒度时间序列预测:ARIMA全流程实战与坑点解析

5分钟粒度时间序列预测:ARIMA全流程实战与坑点解析

数据准备:5分钟数据的“脏活累活” 2.1 采集与落库,先解决有没有的问题 2.2 缺失值处理,别让“空洞”骗了模型 2.3 异常值甄别,业务噪声与真实波动的边界 2.4 重采样与对齐,把时间轴捋直了 数据是一切时序建模的地…

2026/10/20 16:43:46 阅读更多 →
降AIGC软件横评:9类工具原理、避坑与实操流程

降AIGC软件横评:9类工具原理、避坑与实操流程

最近这段时间,被问得最多的问题就是“到底有没有靠谱的降AIGC软件”。经常是头像一换,那边甩过一张截图,问“这种标红要怎么办”。尤其专科生群体,课程报告、实训总结、毕业设计说明一摊开,全是AI生成常见句式&#xf…

2026/10/20 16:43:46 阅读更多 →
Apache Pulsar 2.9.1 部署实战:从解压到集群调优的完整指南

Apache Pulsar 2.9.1 部署实战:从解压到集群调优的完整指南

简介:Apache Pulsar 2.9.1 的二进制发行包,面向需要搭建高吞吐消息队列与实时流处理管道的后端开发、架构师和云原生运维人员,解决分布式消息中间件选型与自建集群时的环境前置问题。压缩包约 321.53MB,为 tar.gz 格式&#xff0c…

2026/10/20 16:43:46 阅读更多 →

最新新闻

Ubuntu下PostgreSQL安装配置与Navicat连接指南

Ubuntu下PostgreSQL安装配置与Navicat连接指南

做后端开发或者数据相关工作的朋友,应该都经历过这么一幕:好不容易在 Ubuntu 上把 PostgreSQL 装好了,却发现命令行操作没问题,客户端工具却怎么都连不上;或者反过来,Navicat 装好了,连接时报一…

2026/10/20 17:33:06 阅读更多 →
uniCloud Serverless 实战:英语学习小程序全链路开发

uniCloud Serverless 实战:英语学习小程序全链路开发

简介:这是一套面向英语学习者与小程序开发者的完整项目源码,基于uniapp与uniCloud Serverless架构构建,可直接在微信环境中运行。项目集生词本记录、拍照识别单词、内置词典查询、AI语音翻译、跟读打分评测于一体,并针对考研人群补…

2026/10/20 17:33:06 阅读更多 →
WiFi指纹室内定位实战:从原理到Demo搭建

WiFi指纹室内定位实战:从原理到Demo搭建

1. 室内定位的现实困境与WiFi方案的破局点实话实说,第一次接手“基于WiFi的室内定位”这个方向时,我心里是打鼓的。日常大家用GPS导航已经习惯了,掏出手机就能知道自己在哪,但一旦走进大型商场、地下车库、机场航站楼,…

2026/10/20 17:33:06 阅读更多 →
大模型后端长对话记忆架构全解析:从无状态到有状态

大模型后端长对话记忆架构全解析:从无状态到有状态

做后端的人都有过这种体验:用户和AI助手聊了三十轮,前二十轮里明明已经把需求背景、偏好、禁忌都交代清楚了,结果聊到第三十一轮,AI突然反问一句“您刚刚提到的那个项目背景,方便再描述一下吗?”当场血压就…

2026/10/20 17:33:06 阅读更多 →
D435相机+OpenCV快速上手:彩色图与深度图实时显示全攻略

D435相机+OpenCV快速上手:彩色图与深度图实时显示全攻略

最近不少做视觉入门的朋友卡在第一关——把D435相机的画面真正“看”到屏幕上。很多人买了一台Intel D435深度相机,兴冲冲插上USB线,结果CPU占用飙高、程序报错、画面黑屏,折腾一晚上就劝退了。其实用D435搭配OpenCV显示彩色图和深度图&#…

2026/10/20 17:33:06 阅读更多 →
自考论文降AI率实战:智能体改写与人工复核全流程

自考论文降AI率实战:智能体改写与人工复核全流程

自考论文写到提交前,最让人血压升高的往往不是查重率,而是学校突然要求提交一份AI检测报告。A同学就是这种状况:论文初稿在查重系统里已经降到合格线,结果学院的通知里多了一句“AI疑似率不得超过20%”。他拿自己的稿子去测了一下…

2026/10/20 17:32:04 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →