【JVM原理详解】14-方法区演进-永久代到元空间
方法区演进永久代到元空间前几篇我们讨论了堆、栈等运行时数据区。还有一个区域长期被开发者闻之色变——方法区Method Area。它存储类信息、常量、静态变量等数据是JVM中争议最多的内存区域。从JDK 7的永久代PermGen到JDK 8的元空间Metaspace方法区经历了一次彻底的重构。本篇将剖析永久代的缺陷、元空间的改进、元空间的参数调优以及生产环境中方法区OOM的排查方法。方法区是什么定义与作用方法区是JVM规范中定义的一块内存区域用于存储类信息、常量、静态变量、即时编译后的代码等数据。它与堆一样是所有线程共享的但用途不同——堆存对象实例方法区存类的元数据。方法区存储的内容包括类型信息类的全限定名、父类、接口、修饰符字段信息字段名、类型、修饰符方法信息方法名、返回类型、参数、修饰符、字节码、异常表运行时常量池class文件常量池的运行时表示静态变量类级别的变量JDK 7后移到堆中JIT编译代码即时编译器编译后的本地代码┌──────────────────────────────────────┐ │ 方法区 (Method Area) │ ├──────────────────────────────────────┤ │ 类型信息 (Class Metadata) │ │ ┌────────────────────────────────┐ │ │ │ 类名, 父类, 接口, 修饰符 │ │ │ │ 字段表, 方法表 │ │ │ │ 类加载器引用 │ │ │ └────────────────────────────────┘ │ │ │ │ 运行时常量池 (Runtime Constant Pool) │ │ ┌────────────────────────────────┐ │ │ │ 字面量, 符号引用解析后的直接引用 │ │ │ └────────────────────────────────┘ │ │ │ │ 静态变量 (JDK 7 移至堆) │ │ JIT编译代码缓存 │ └──────────────────────────────────────┘JVM规范 vs 实现重要区分方法区是JVM规范中的概念永久代和元空间是HotSpot JVM的具体实现。概念层级名称说明JVM规范方法区抽象定义规定存储内容和行为HotSpot JDK 7及以前永久代PermGen方法区的实现位于堆内HotSpot JDK 8及以后元空间Metaspace方法区的实现位于本地内存JVM规范对方法区的实现方式没有任何限制——可以放在堆中可以放在本地内存甚至不分配连续内存。其他JVM实现如J9、Zing各有自己的方法区实现。永久代PermGen的缺陷永久代的设计在JDK 7及以前HotSpot用永久代实现方法区。永久代位于JVM堆内存中与新生代、老年代并列通过-XX:PermSize和-XX:MaxPermSize控制大小。JDK 7 堆内存结构 ┌─────────────────────────────────────────┐ │ 新生代 │ 老年代 │ 永久代 │ │ (EdenS0S1)│ │ (PermGen) │ └─────────────────────────────────────────┘# JDK 7 设置永久代大小java-XX:PermSize128m-XX:MaxPermSize256m-jarapp.jar永久代的核心问题永久代有几个致命缺陷最终导致它被废弃1. 大小固定难以预估永久代大小在JVM启动时固定-XX:MaxPermSize无法自动扩展。问题是方法区需要多大空间取决于运行时加载了多少类这在启动时很难准确预估。设小了java.lang.OutOfMemoryError: PermGen space设大了浪费内存这在动态类加载场景如Spring AOP的CGLIB代理、Groovy脚本、JSP重编译下尤为突出。一个典型的例子是频繁热部署的Web应用——每次重新部署都会加载新的类加载器和类旧的类如果未卸载永久代不断增长直至OOM。2. 与堆的GC耦合永久代与堆物理上连续GC需要同时考虑。Full GC时会回收永久代中无用的类信息但类卸载条件苛刻类加载器已卸载、类无实例、类无引用导致永久代往往只增不减。3. 字符串常量池的内存压力JDK 6及以前字符串常量池String Pool在永久代中。String.intern()大量使用时永久代容易溢出。JDK 7将字符串常量池移到了堆中缓解了这个问题但永久代仍存放其他常量。4. 性能调优困难永久代的GC效率低且与老年代GC耦合。永久代满时触发Full GC整个应用暂停影响吞吐和延迟。永久代的OOM复现// 适用: JDK 7 (需限制永久代大小)// 运行: java -XX:PermSize8m -XX:MaxPermSize8m PermGenOOMimportjava.util.ArrayList;importjava.util.List;publicclassPermGenOOM{publicstaticvoidmain(String[]args){ListClass?classesnewArrayList();try{while(true){// 使用CGLIB等库不断生成新类// 这里用URLClassLoader加载同一类的不同副本模拟URLClassLoaderclnewURLClassLoader(newURL[]{newURL(file:/path/to/classes/)});Class?clazzcl.loadClass(SomeClass);classes.add(clazz);// 保持引用防止类卸载}}catch(Throwablee){e.printStackTrace();// JDK 7: java.lang.OutOfMemoryError: PermGen space}}}元空间Metaspace的改进元空间的设计JDK 8彻底移除了永久代方法区的实现改为元空间Metaspace。元空间与永久代最大的区别是元空间使用本地内存Native Memory而非JVM堆内存。JDK 8 内存结构 ┌──────────────────────────────────────────┐ │ JVM 进程内存 │ │ ┌──────────────────┐ ┌──────────────┐ │ │ │ Java堆 │ │ 元空间 │ │ │ │ (新生代老年代) │ │ (本地内存) │ │ │ └──────────────────┘ └──────────────┘ │ │ │ │ ┌──────────────────┐ │ │ │ 代码缓存 │ │ │ │ (JIT编译代码) │ │ │ └──────────────────┘ │ └──────────────────────────────────────────┘元空间的优势1. 使用本地内存突破堆限制元空间不在JVM堆中而是直接使用操作系统的本地内存。这意味着元空间的大小只受限于可用本地内存不必再为永久代预留固定大小。永久代 (JDK 7): 堆 新生代 老年代 永久代 永久代大小受限于 -XX:MaxPermSize 元空间 (JDK 8): 堆 新生代 老年代 元空间 独立的本地内存 元空间大小受限于 -XX:MaxMetaspaceSize 或系统可用内存2. 自动扩容元空间默认可以动态扩容直到达到MaxMetaspaceSize或系统内存耗尽。JVM根据加载的类数量自动调整元空间大小无需人工预估。3. 类卸载改进元空间的类元数据存放策略更合理——类元数据与类加载器关联。当类加载器被卸载时其加载的所有类的元数据可以一起释放。这改善了动态类加载场景下的内存回收。4. 字符串常量池已在堆中JDK 7将字符串常量池从永久代移到了堆中。JDK 8移除永久代后字符串常量池仍在堆中与方法区元空间无关。只有类元数据、运行时常量池等在元空间。元空间的内部结构元空间内部进一步划分为几个区域元空间 (Metaspace) ├── Klass Metaspace │ └── 存放类的Klass指针 (Compressed Class Pointer) │ 大小由 -XX:CompressedClassSpaceSize 控制 (默认1GB) │ ├── Non-Klass Metaspace │ ├── 常量池 │ ├── 方法信息 │ ├── 字段信息 │ └── 其他元数据 │ └── (CCS: Compressed Class Space, 指针压缩的类空间)当开启指针压缩-XX:UseCompressedOops64位JVM默认开启时类的Klass指针存放在独立的压缩类空间CCS其他元数据存放在非类元空间。这优化了对象头中的类指针大小从8字节压缩到4字节。元空间参数详解-XX:MetaspaceSize# 设置元空间初始高水位线为256MBjava-XX:MetaspaceSize256m-jarapp.jarMetaspaceSize不是初始大小而是触发Full GC的阈值。元空间从很小的初始值开始随着类加载增长。当元空间使用量达到MetaspaceSize时JVM触发Full GC进行类卸载然后重新评估阈值通常提高。如果应用加载的类较多建议将MetaspaceSize设置为略高于稳定状态的类元数据量避免应用启动初期的无谓Full GC。-XX:MaxMetaspaceSize# 限制元空间最大为512MBjava-XX:MaxMetaspaceSize512m-jarapp.jarMaxMetaspaceSize限制元空间能增长到的最大值。默认值是无限制直到系统内存耗尽。生产环境强烈建议设置这个上限防止类加载泄漏导致整个进程被OOM Killer杀死。-XX:CompressedClassSpaceSize# 设置压缩类空间大小为1GB (默认)java-XX:CompressedClassSpaceSize1g-jarapp.jar压缩类空间是元空间中存放Klass指针的区域。这个空间是预留的虚拟内存不一定实际占用但如果加载的类非常多可能触发OutOfMemoryError: Compressed class space。-XX:MinMetaspaceFreeRatio / -XX:MaxMetaspaceFreeRatio# 元空间GC后, 空闲比例低于20%时扩容-XX:MinMetaspaceFreeRatio20# 元空间GC后, 空闲比例高于70%时收缩-XX:MaxMetaspaceFreeRatio70这两个参数控制元空间的扩容/收缩行为让元空间在内存使用和GC频率之间平衡。综合配置示例# 典型的生产环境元空间配置java-XX:MetaspaceSize256m\-XX:MaxMetaspaceSize512m\-XX:CompressedClassSpaceSize256m\-jarapp.jar方法区OOM排查元空间OOM的表现// 适用: JDK 8// 运行: java -XX:MaxMetaspaceSize32m MetaspaceOOMimportnet.sf.cglib.proxy.Enhancer;publicclassMetaspaceOOM{publicstaticvoidmain(String[]args){try{while(true){// 不断生成CGLIB代理类 (每个代理类是一个新类)EnhancerenhancernewEnhancer();enhancer.setSuperclass(Object.class);enhancer.setCallback((method,obj,args1)-null);enhancer.create();}}catch(Throwablee){e.printStackTrace();// java.lang.OutOfMemoryError: Metaspace}}}元空间OOM的错误信息java.lang.OutOfMemoryError: Metaspace at java.lang.ClassLoader.defineClass1(Native Method) ...常见OOM原因动态代理类未卸载CGLIB、Spring AOP生成的代理类如果类加载器未卸载这些类会持续占用元空间。常见于频繁热部署的场景。JSP重编译每个JSP编译为一个Servlet类修改JSP触发重编译。如果旧版本未卸载类数量持续增长。Groovy等动态语言Groovy脚本在运行时编译为Java类大量脚本执行可能撑爆元空间。类加载器泄漏自定义类加载器未正确关闭引用链阻止类卸载。常见于Tomcat redeploy、OSGi bundle更新。排查步骤第一步确认OOM类型查看错误信息OutOfMemoryError: Metaspace→ 元空间不足OutOfMemoryError: Compressed class space→ 压缩类空间不足第二步查看元空间使用情况# jstat查看元空间使用 (JDK 8)jstat-gcmetacapacitypid# 输出: MCMN MCMX MC CCSMN CCSMX CCSC YGC FGCT FGCT# 0.0 1056768.0 256000.0 0.0 1048576.0 32768.0 12 3 0.45# MC: 当前元空间使用 (KB)# CCSC: 压缩类空间使用 (KB)# MCMX: 元空间最大值# jcmd查看元空间详情jcmdpidGC.class_stats第三步定位类加载泄漏# 使用jcmd查看类加载统计jcmdpidCompiler.codecache jcmdpidVM.classloaders# 使用jmap查看类加载器信息 (JDK 8)jmap-clstatspid# 输出每个类加载器加载的类数量# 使用Arthas诊断[arthas1234]$ classloader# 查看类加载器[arthas1234]$ classloader-t# 类加载器树[arthas1234]$ dashboard# 元空间使用概览[arthas1234]$ heapdump /tmp/heap.hprof# 导出堆快照第四步分析堆快照用MATMemory Analyzer Tool分析heap dump打开histogram视图按Class排序查看是否有大量同名类如com.example.Service$$EnhancerByCGLIB$$xxxxx查看Dominator Tree找到保持类加载器引用的对象使用Path to GC Roots查看引用链常见的引用链模式Thread → ApplicationContext → ClassLoader → Class → Metaspace ↑ ↑ 容器持有应用上下文 类加载器持有其加载的所有类热部署时旧应用的类加载器因被某个对象如线程、日志框架、第三方库的静态引用持有而无法卸载导致旧类无法释放。解决方案增大MaxMetaspaceSize临时缓解不解决根本问题java-XX:MaxMetaspaceSize1g-jarapp.jar修复类加载器泄漏找到并切断引用链。常见做法检查日志框架Log4j、Logback是否持有旧类加载器检查ThreadLocal是否在销毁时清理检查线程池是否在应用卸载时关闭检查驱动注册如JDBC Driver是否deregister避免过度使用动态代理评估是否真的需要为每个接口生成代理考虑缓存代理类。关闭JSP自动重编译生产环境关闭JSP开发模式developmentfalse。代码示例观察元空间类加载与元空间增长// 适用: JDK 8/11/17// 运行: java -XX:MaxMetaspaceSize64m -Xlog:classload MetaspaceGrowthDemoimportjava.net.URL;importjava.net.URLClassLoader;publicclassMetaspaceGrowthDemo{publicstaticvoidmain(String[]args)throwsException{// 循环创建类加载器并加载类for(inti0;i100;i){URLClassLoaderclnewURLClassLoader(newURL[]{newURL(file:/path/to/classes/)});Class?clazzcl.loadClass(com.example.SomeClass);System.out.println(已加载: clazz.getName());// 不保持引用, 允许类卸载cl.close();}System.out.println(完成);}}配合-Xlog:classloadJDK 11/17或-verbose:classJDK 8可以观察类加载行为配合jstat -gcmetacapacity观察元空间增长。实践要点生产环境必须设置MaxMetaspaceSize默认无限制的元空间在类加载泄漏时会导致整个进程被OOM Killer杀死。设置一个合理上限如512MB-1GB让泄漏以可控的方式暴露为OutOfMemoryError。MetaspaceSize的合理设置将其设置为应用稳定运行时元空间使用量的1.2-1.5倍。这样应用启动后不会因元空间增长触发无谓的Full GC。可以通过jstat -gcmetacapacity观察稳定值。热部署的类加载泄漏排查Tomcat/Jetty等容器热部署后如果元空间持续增长且不回收几乎可以确定是类加载器泄漏。使用jmap -clstats对比部署前后的类加载器数量找出泄漏的类加载器。压缩类空间OOM如果遇到Compressed class spaceOOM可以尝试增大-XX:CompressedClassSpaceSize关闭指针压缩-XX:-UseCompressedOops但会增加对象头大小通常不建议减少加载的类数量JDK版本差异JDK 8是永久代到元空间的过渡版本部分参数如-XX:PermSize在JDK 8中会被警告但忽略。JDK 11/17完全移除了永久代相关参数。从JDK 8升级时务必检查启动脚本中的PermSize/MaxPermSize参数。GraalVM的元空间差异GraalVM Native Image将类元数据在编译期固定运行时几乎不加载新类元空间概念基本不适用。这与传统HotSpot JVM差异很大。元空间碎片元空间使用块分配器管理内存频繁加载/卸载类可能产生碎片。JDK 12引入了元空间碎片整理机制JEP 381但极端场景下仍需关注。小结方法区是JVM规范定义的存储类元数据、常量、静态变量的区域永久代和元空间是HotSpot的两种实现。永久代的缺陷大小固定难以预估、与堆GC耦合、字符串常量池内存压力、性能调优困难导致动态类加载场景频发PermGen spaceOOM。元空间的改进使用本地内存突破堆限制、支持自动扩容、类元数据与类加载器关联改善卸载、字符串常量池移至堆中。关键参数-XX:MetaspaceSizeGC阈值、-XX:MaxMetaspaceSize上限生产必设、-XX:CompressedClassSpaceSize压缩类空间。OOM排查jstat -gcmetacapacity看使用量、jmap -clstats/jcmd VM.classloaders看类加载器、MAT分析引用链重点排查动态代理和类加载器泄漏。下一篇聚焦方法区中一个特殊的存在——运行时常量池理清Class常量池、运行时常量池、字符串常量池三者的关系与差异。更多内容JVM调优实战

相关新闻

【信息科学与工程学】【数据中心】第三十三篇 云数据中心综合解决方案探讨10

【信息科学与工程学】【数据中心】第三十三篇 云数据中心综合解决方案探讨10

编号 类型 问题 多场融合领域 问题的数学分析 数学方程式/算法模型+逐步推理思考的数学方程式、求解及计量过程 参数列表 时序数学方程和稳态/非稳态分析 关联知识 计算工具/加工工艺和装备设备 1491 单云多Region多AZ 计算 跨AZ的EC2实例基于Graviton4的Web服务器性…

2026/7/26 0:47:38阅读更多 →
Django计算机毕设之基于 Web 的智能网上购物商城系统 商品上架销售与用户购物平台设计(完整前后端 代码+说明文档+LW,调试定制等)

Django计算机毕设之基于 Web 的智能网上购物商城系统 商品上架销售与用户购物平台设计(完整前后端 代码+说明文档+LW,调试定制等)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/26 0:41:37阅读更多 →
腾讯混元Hy3深度解析:295B参数只激活21B,推理效率怎么做到提升40%的

腾讯混元Hy3深度解析:295B参数只激活21B,推理效率怎么做到提升40%的

7月6日腾讯混元Hy3正式发布,7月20日宣布限时免费延长到8月5日。说实话,295B参数、Apache 2.0开源、API定价输入1元/输出4元/百万token——这些数字单独拿出来都不算特别惊人,但放在一起看,你会发现腾讯这次打了一套组合拳。 我最感…

2026/7/26 0:41:37阅读更多 →
数字孪生与AI视频分析在智慧监所的应用实践

数字孪生与AI视频分析在智慧监所的应用实践

1. 项目背景与核心价值在现代化监所管理领域,传统的人工巡查与分散式监控系统已难以满足高安全性、高透明度的管理需求。我们团队研发的"镜像视界空间视频智能驱动平台"本质上是一个融合三维数字孪生、AI行为分析、物联网感知技术的空间智能中枢。这个系统…

2026/7/26 2:05:49阅读更多 →
论文AI率检测与优化工具实测及降AI率指南

论文AI率检测与优化工具实测及降AI率指南

1. 论文AI率检测与优化的核心挑战去年帮学弟修改毕业论文时遇到个棘手问题:查重系统显示他的论文"AI生成率高达99%"。这并非个例,随着AI写作工具的普及,国内外高校和期刊编辑部纷纷引入AI检测机制。Turnitin、iThenticate等主流查重…

2026/7/26 2:05:49阅读更多 →
电力安全三维数字化管理:技术架构与应用实践

电力安全三维数字化管理:技术架构与应用实践

1. 项目背景与核心价值电力行业作为国民经济命脉,其安全生产管理一直是行业发展的重中之重。传统安全管理模式存在"事件还原难、处置过程模糊、责任界定不清"三大痛点。当发生安全事故时,往往面临:现场信息采集不完整,关…

2026/7/26 2:05:49阅读更多 →
Spring Boot+Vue项目Docker容器化实战指南

Spring Boot+Vue项目Docker容器化实战指南

1. 项目概述最近在帮朋友公司重构一个前后端分离的管理系统,技术栈选用了Spring Boot Vue的组合。考虑到后续的部署维护成本,决定采用Docker容器化方案。这种部署方式在实际生产环境中已经非常普遍,但新手在初次尝试时往往会遇到各种"坑…

2026/7/26 2:05:49阅读更多 →
船舶轨迹跟踪控制:神经网络与自适应滑模的融合方案

船舶轨迹跟踪控制:神经网络与自适应滑模的融合方案

1. 项目背景与核心挑战船舶轨迹跟踪控制一直是航海自动化领域的核心课题。去年在IEEE Transactions on Control Systems Technology上读到一篇关于无人船自适应控制的论文时,我发现传统PID控制在应对复杂海况时存在明显局限性——当遇到突发风浪干扰或系统参数突变时…

2026/7/26 2:05:49阅读更多 →
Stable Diffusion大模型技术解析与实战指南

Stable Diffusion大模型技术解析与实战指南

1. 大模型技术解析Stable Diffusion大模型作为当前AI绘画领域的核心技术突破,其核心架构基于潜在扩散模型(Latent Diffusion Model)。与传统的直接在像素空间操作的扩散模型不同,这种设计将计算复杂度降低了约64倍。模型包含三个关…

2026/7/26 2:03:48阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/26 0:01:28阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/26 0:01:28阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/26 0:01:28阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/26 0:01:28阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/26 0:01:28阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/26 0:01:28阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/25 23:03:25阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/25 19:03:04阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/25 19:03:04阅读更多 →