JVM 核心知识全解析:从类加载到垃圾回收的深度认知

什么是JVM?
  • JVM全称(Java Virtual Machine),中译为:Java虚拟机
    • 本质:是一个运行在计算机上的程序
  • 职责:运行Java字节码文件(因为计算机只能认识机器码文件,所以需要JVM将自字节码转为机器码)
  • 功能:
    • 解释和运行:字节码转机器码
    • 内存管理:自动为对象/方法分配内存,垃圾回收
    • 即时编译:对热点代码进行优化
常见的JVM

JVM的组成部分

类加载器:加载class文件

运行时数据区域:管理内存

执行引擎:垃圾回收器/即时编译器/解释器

本地接口:java使用native修饰的方法

字节码文件的组成
  • 打开方式:
    • 字节码是以二进制存储,不能直接使用文本软件打开
    • 使用软件:jclasslib-bytecode-viewer

MAC安装命令: brew install jclasslib-bytecode-viewer

  • 组成(5部分)
    • 基础信息:存储java版本号,访问标识
    • 常量池:存储字符串常量/类或接口名/字段名
    • 字段:存储变量名/变量类型/标识
    • 方法:存储方法原代码指令
    • 属性:存储类的属性

字节码文件组成详解(基本信息/常量池/方法)
  • 基本信息包含:Magic魔数/副版本号/主版本号/访问标识/类等
    • Magic魔数(固定字符):是字节码文件的前几个字节,用于确定文件的文件类型

- 主副版本号:主(大版本号 )使用当前的主版本号-44得到真正的jdk版本号* 例如:主版本号为:52,减完后得到jdk1.8
- 副版本号:为主版本号相同时,区分不同版本的标识
- 版本号的作用:判断当前字节码的版本和运行时jdk是否相兼容* 例如:报错:<font style="color:#DF2A3F;">字节码文件为jdk8,运行时jdk为6</font>

- 版本号不同的解决方案:
- ![](https://i-blog.csdnimg.cn/img_convert/bea7ceac8c7c3c4f26ef36121acd028b.png)
字节码文件的组成-常量池
  • 常量池作用:避免相同的内容重复定义
字节码文件的组成-方法
  • 字节码指令
  • 字节码执行过程:

iconst_0 # 现将o放入到操作数栈中,
istore_1 #0从操作数栈弹出,存储到局部变量表中下标为1的位置中
注意:下标为0中存储args数组
iload_1 # 将局部变量中的下标为1的内容复制到栈中
iinc1 by 1 将下标为1的值变为1
istore_1 # #0从操作数栈弹出,存储到局部变量表中下标为1的位置中
return 返回
总结:最后的结果还是为0
字节码文件-练习题:

 0 iconst_01 istore_12 iconst_03 istore_24 iconst_05 istore_36 iinc 1 by 19 iload_2
10 iconst_1
11 iadd
12 istore_2
13 iinc 3 by 1
16 return
字节码文件常用工具
  1. 命令:javap -v

  1. jclasslib插件
    1. 注意点:想看哪一个文件,先点击文件后在点击视图打开jclasslib
    2. 注意点:修改后的文件,需要重新编译后才会有对应的字节码文件

  1. 阿里arthas
    1. jad命令可以将class文件还原java文件

类的生命周期
  • 类的生命周期描述了一个类加载/使用/卸载的整个过程
  • 概述:
    • 生命周期分为5个阶段:加载(Loading)》连接(Linking)〉初始化(Init)》使用(Using)〉卸载(Unloading)
    • 注意:连接可以在分为三个阶段为:验证》准备〉解析
类的加载阶段
  • 第一步:类加载器根据类的全限定名通过不同渠道以二进制方式获取字节码信息
  • 第二步:加载类完成后,JVM会将字节码信息存到内存中的方法区中
    • 生成一个instanceKlass对象,保存了类的所有信息(例如:基本信息,常量池/字段/方法等)
  • 第三步:JVM还有在堆中生成一份与方法区数据类似的java.lang.Class对象
  • 总结:类加载器根据类的类名会将类的字节码信息存入到内存中,并在方法区的对区分别分配一个对象,保存类的信息
  • 注意:方法区和堆区的对象是有关联的
类的连接阶段

  1. 验证阶段
    1. 举例:
      1. 魔数校验

    2. 元信息校验(类必须有父类)3. 主版本号校验

  1. 准备阶段
    1. 准备阶段:在堆区分配一块空间给Student对象,并对属性value赋默认值0

注意点:如果使用final修饰的话,在准备阶段就是赋值

  1. 解析阶段
  • 作用:将常量池中的符号引用转为直接引用
类加载器的初始化阶段
  1. 行为:会执行静态代码块中的代码,并为静态变量赋值
  2. 使用的字节码命令:clinit
  3. 示例:
    1. 先赋值2,在赋值1,最后value中的值为:1

  1. 类初始化的几种方式
  • 访问一个类的静态变量或者静态方法,
public class Test {public static void main(String[] args) {int i = Test1.i;System.out.println(i);}
}
class Test1{public static int i=0;static{System.out.println("init");}
}

  • 调用Class.forName(String className)
public class Test {public static void main(String[] args) throws ClassNotFoundException {Class.forName("Test1");}
}
class Test1{static{System.out.println("init");}
}
  • new一个该类的对象时
  • 执行Main方法的当前类
public class Test {static {System.out.println("init Test");}public static void main(String[] args) throws ClassNotFoundException {Test1 test = new Test1();}
}
class Test1{static{System.out.println("init Test1");}
}

  1. 面试题(静态代码块先执行,在执行main方法,在执行构造方法和构造器方法)
    1. 答案:DACBCB

  1. clinit不会出现的情况:

  1. 面试题2

  1. 练习题1

  1. 练习题2

  1. 总结

类加载器ClassLoader
  1. 用途:将二进制流》加载〉本地接口调用》生成方法区和堆区的对象
  2. 应用场景:
    1. SPI机制
    2. 类的热部署
    3. Tomcat类的隔离
    4. 面试题:双亲委派机制,如何打破双亲,自定义类加载
类加载器的分类
  1. 两类
    1. java虚拟机低层实现
      1. 例如:hotspot使用C++
    2. java代码实现
      1. 根据需要自定义
  2. 特点:需要继承ClassLoder

类加载器-启动类加载器Bootstrap
  1. String类是由启动类加载器加载的,但是在使用String.class.getClassLoader()方法时,返回的结果为null,因为,类加载器存在于jvm中,所以获取不到。
  2. 命令:sc -d java.lang.String

class-loader 为空

  1. 如何使用启动类加载器加载自定义的jar包

  1. 练习:使用方法二:

类加载器-扩展类加载器(Extension Class Loader)
  • 默认加载Java安装目录/jre/lib/ext下的类文件
package cn.varin.Test;import jdk.nashorn.internal.runtime.ScriptEnvironment;import javax.script.ScriptEngineManager;
import java.io.IOException;public class Test {public static void main(String[] args)  {ClassLoader classLoader = ScriptEnvironment.class.getClassLoader();System.out.println(classLoader);}}

  • 将自己编写的扩展jar包,添加到ext包下

类加载器-应用程序加载器(Application Class Loader)
  • 程序员自己创建的类和第三方类会使用Application加载
package cn.varin.Test;import jdk.nashorn.internal.runtime.ScriptEnvironment;import javax.script.ScriptEngineManager;
import java.io.IOException;public class Test {public static void main(String[] args)  {ClassLoader classLoader = Person.class.getClassLoader();System.out.println(classLoader);}}
class Person{private String name;private int age;
}

双亲委派机制
  1. 核心:解决一个类到底是由谁加载的问题
  2. 作用:
    1. 保证类加载的安全性
    2. 避免重复加载
  3. 解释:

1. 示例1:假设cn.varin.Person对象加载,它会先找Application,如果没有找到加载,继续找Ext,没有再继续找 Boot,找到,返回
2. 示例2:加载cn.varin.Person对象都没有被三个加载器加载过,它会从boot找,是否在路径中,没有的话,继续找Ext,没有的话,继续找Application,找到,返回

问题:如果一个类重复出现在三个类加载器中,谁来加载

答案:启动类加载器加载,根据双亲委派机制,它的优先级最高

问题2:在自己的项目中创建一个java.lang.String类,会被加载吗

答案:不能,会返回启动类加载器加载在rt包中的String类

package cn.varin.Test;import jdk.nashorn.internal.runtime.ScriptEnvironment;import javax.script.ScriptEngineManager;
import java.io.IOException;public class Test {public static void main(String[] args) throws ClassNotFoundException {ClassLoader classLoader = Test.class.getClassLoader();System.out.println(classLoader);Class<?> aClass = classLoader.loadClass("java.lang.String");System.out.println(aClass.getClassLoader());}}
#  结果为:Applicationnull
面试题:类的双亲委派机制是什么?

当一个类加载器区加载某一个类的时候,会自底向上的查询父类是否加载过,

如果加载过,直接返回,

如果没有加载过,会自顶向下查询路径进行加载。

app 的父为:Ext

Ext 的父为:Boot

打破双亲委派机制
  1. 打破双亲委派机制的三种方式
    1. 自定义类加载器
    2. 利用上下文类加载器
    3. 使用Osg框架的类加载器
  2. 需要打破双亲委派机制的场景
    1. 有两个应用需要运行,但是两个应用中的某一个类的全路径名是相同的,假设A加载了,B再加载,类加载器会认为是A类
打破双亲委派机制-自定义类加载器

实现方法:重写findClass方法,这样就不会破坏双亲委派机制

打破双亲委派机制-线程上下问加载器

利用上下文类加载器加载类,比如:JDBC和JNDI

  • 快速获取到线程上下文类加载器
Thread.currentThread().getContextClassLoader()
  • 总结

  • 思考:JDBC案例是否真正的打破了双亲委派

打破双亲委派机制-Osgi模块化(了解)
JDK9之后的类加载器
  1. 区别一

  1. 区别二:扩展类加载器

  1. 区别三:应用程序类加载器

类加载器小结
  1. 类加载器的作用

  1. 有几种类加载器?

  1. 什么是双亲委派机制

  1. 怎么打破双亲委派机制

运行时数据区域

运行时数据区是:jVM在运行Java程序过程中管理的内存区域

  • 分类:

运行时数据区域-程序计数器

程序计数器:

作用一:用于存放下一条指令需要执行的地址

作用二:在多线程执行下,程序计数器可以记录CPU切换前每个线程解释执行到那一条指令

问题:程序计数器会发生内存溢出吗:

答案:不会,因为每个线程只存储了一个固定长度的地址,是不会发生内存溢出的。

运行时数据区域-栈
  1. 分为了:
    1. Java虚拟机栈
      1. 保存在Java中实现的方法
    2. 本地方法栈
      1. 保存方法中有native关键字的
      2. 源代码保存在c++中
运行时数据区域-栈-Java虚拟机栈
  1. 存储顺序:先进后出
  2. 栈帧的组成:
    1. 局部变量表:
      1. 方法执行过程中存放所有的局部变量
      2. 保存的内容:有实例的this对象,方法的参数,方法体中声明的局部变量。

例题:

答案:6个

2. 操作数栈:1. 存放临时数据,例如:常量
3. 栈数据1.  存储:动态链接,方法出口,异常表
  • 设置修改栈的大小

    • 注意点:

运行时数据区-堆
  1. 堆内存是空间最大的一块内存区域,创建出来的对象都存在于堆上
  2. 堆空间可以分为:use+total+max
    1. use:使用空间
    2. total(默认是系统内容的六十四分之一):剩余空间(可以动态增加, )
    3. max(默认分配系统内存的四分之一):最大可用空间
  3. 手动设置total和max

运行时数据区域-方法区
  1. 存储 :
    1. 类的基本信息
    2. 运行时常量池
    3. 字符串常量池
  2. jdk7把方法区存储在堆区域中的永久代空间
  3. jdk8将方法区存放在元空间中,云空间位于内存中,只要不超过内存,可以一直存
运行时数据区域-方法区-字符串常量池
  1. 代码示例

String s1 = new String(“1”);

String s2 = “1”;

解释:s1中的字符串是通过new对象创立的,内容会存储在堆中

s2中的字符串是直接创立的,会存储在方法区的字符串常量池中

s1和s2都是存储在栈中,

  • 运行时常量池和字符串常量池的区别

  • 练习题1:

  • false和true
  • 练习题2

  • 练习题3

  • 总结
  • 在jdk7及以后版本中,静态变量是存储在堆的Class对象中,脱离了永久代
直接内存
  1. 直接内存的作用:
    1. 适应NIO机制
    2. 提升IO操作效率

3. 在jdk8后,直接保存方法区中的数据
  1. 直接内存设置

运行时数据区域总结
  1. 运行时数据区分为几部分,每一部分的作用是什么?

两大部分:

线程不共享:

程序计数器:记录当前要执行的字节码指令的地址(不会出现内存溢出)

Java虚拟机栈:

本地方法栈:

Java虚拟机栈和本地方法栈都是采用栈式存储,用于保存方法调用的基本数据(局部变量,操作数等)(会出现内存溢出)

线程共享:

方法区:主要存储类的元信息,以及常量池(会出现内存溢出)

堆区: 存放创建出来的对象(会出现内存溢出 )

  1. 不同JDK版本直接的运行时数据区的区别是什么?

jdk6:

jdk7:

jdk8:

自动垃圾回收
  1. 范围:负责对堆上的内存进行回收(回收不再使用的对象)

  2. 优点:降低程序员实现难度

自动垃圾回收-方法区回收
  1. 回收条件

  1. 扩展:System.gc()
    1. 作用:手动出发垃圾回收器
自动垃圾回收-堆区回收判断-引用计数法
  1. 如何判断堆上的对象有没有被引用:使用引用计数法
  2. 每一个对象有一个引用计数器:当对象被引用时+1,取消引用-1
  3. 存在缺陷:
    1. 可能产生循环引用
自动垃圾回收-堆区回收判断-可达性分析算法
  1. 可达性分析将对象分为两类:
    1. 垃圾回收的根对象(GC root) :
    2. 普通对象
  2. 回收原理:可达性分析中,存在一个不可回收的GC Root对象, 该对象会引用其他对象,可达分析通过判断,如果从GC Root开始找,没有找到的对象就是可以回收的。›

  • GC Root对象种类
  1. 线程Thread对象,
  2. 系统类加载器加载的Java.lang.Class对象
  3. 监视器对象,用来保存同步锁synchroized关键字的对象
  4. 本地方法调用时使用的全局对象
  • 可达性分析法中的引用属于强引用
自动垃圾回收-软引用

软引用:如果一个对象只有软引用,当程序内存不足时,就会将软引用中的数据进行回收

常用于:缓存中

如何实现软引用:提供SoftReference类实现

案例分析:

当先A对象属于一个强引用,不会不回收

此时:A对象为一个软引用,可能被回收

  • 注意点:
    • SoftReferenc对象也需要被GC对象强引用,否则也会被回收
自动垃圾回收-弱引用(WaekReference)
  1. 弱引用和软引用类似,不同点就是**软引用是在内存不足时才会回收,但是弱引用不需要看内存够不够直接回收**。
自动垃圾回收-虚引用和终结器引用
  1. 虚引用作用:当对象被垃圾回收器回收时可以接收到对应的通知
  2. 终结器引用:

垃圾回收算法的评价标准

核心思想:找到内存中存活的对象 ,把不再存活的对象释放

常见的垃圾回收算法:

标记-清除算法

复制算法

标记-整理算法

分代GC

评价标准:

STW(stop the world):停止所有的用户线程的时间

吞吐量(越高效率越好):执行用户代码时间➗(执行用户代码时间+GC使劲)

最大暂停时间:在垃圾回收时,STW时间的最大值

垃圾回收算法-标记清除算法

2个阶段:

  1. 标记阶段:将所有存活的对象标记(使用可达性分析法)
  2. 清除阶段:从内存中删除没有被标记的对象

优点:实现简单,第一阶段将存活的标记为1,第二阶段删除非1的对象

缺点:

碎片化:对象删除后,出现多个很小的可用单元;

分配速度慢

垃圾回收算法-复制算法

执行过程:

准备2块空间(from和To),只使用from空间,

在垃圾回收阶段,将存活的对象复制到to中

回收结束后,将from和to的名称互换。

优点:吞吐量高,不会产生碎片化

缺点:内存使用效率低(每次只能使用一般的空间)

垃圾回收算法-标记-整理算法

2个阶段:

  1. 标记阶段:将所有存活的对象标记(使用可达性分析法)
  2. 整理阶段:将存活的对象移动到堆的一端,清除掉间空隙和碎片

优点:内存使用效率高,不会产生碎片化

缺点:整理阶段效率不高

垃圾回收算法-分代GC
  1. 分区
    1. 年轻代(yong区):使用复制算法
      1. 分为:
        1. 伊甸园区
        2. s0:from
        3. s1:to
    2. 老年代(old区)
  2. 年轻代到老年代:年轻代没执行一次GC,会在存活对象标记一个属性并加一,到属性值达到某一个值,就会转移到老年代
  3. 为什么要分为年轻代和老年代?
    1.
垃圾回收算器
  1. 垃圾回收器的种类

组合:

G1垃圾回收器

垃圾回收器的选择

自动垃圾回收总结
  1. Java中有那几块内存需要进行垃圾回收

    1. 在运行时数据区总堆中的数据需要垃圾回收器进行回收
  2. 有哪几种常见的引用类型

  1. 有哪几种常见的垃圾回收算法

    1. 标记清除:标记可用的,没用的清除
    2. 复制算法:分两块空间,将可用的复制同一块区域中,清除掉另一块,并交换名字
    3. 标记整理:将可用的标记并放到另一端后,将另一端清除
    4. 分代GC:分为年轻代和老年代,可以用多中回收算法
  2. 常见的垃圾回收器有哪些?

    1. serial和serial old:单线程回收,使用单核CPU场景
    2. parNew和CMS:暂停时间较短,适用于大型互联网应用中与用户交互的部分
    3. parallel Scavenge和Parallel old:吞吐量高,适用于后台进行大量数据操作
    4. G1:适用于较大的堆,具有可控的暂停时间

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

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

相关文章

Keepalived 负载均衡

Keepalived 负载均衡 Keepalived 可以与 LVS&#xff08;Linux Virtual Server&#xff09;结合&#xff0c;提供强大的四层负载均衡功能。它通过 IPVS&#xff08;IP Virtual Server&#xff09;内核模块实现高性能的负载分发。 核心组件 Virtual Server&#xff1a;虚拟服务器…

拷打DeepSeek实现自动生成差分电荷计算文件和后处理

差分电荷&#xff08;charge density difference&#xff09;是材料模拟中分析电子结构变化的直观工具。 它把成键后的真实电荷密度减去成键前各碎片叠加的电荷密度&#xff0c;得到一张“电子迁移地图” 于是可以一眼看出化学键形成时电子从哪里来到哪里去&#xff0c;表面吸…

AI问答-Nuxt4:什么时候发布的,有哪些特性,和Nuxt3相比 有哪些优势 / Nuxt4 / Nuxt-v4

Nuxt 4于2025年7月至8月期间正式发布&#xff0c;作为Nuxt框架的重大版本更新&#xff0c;其核心聚焦于稳定性提升、开发者体验优化及性能增强&#xff0c;与Nuxt 3相比&#xff0c;优势体现在项目结构、数据获取、类型系统、开发工具链等多个层面。一、Nuxt 4 发布时间线测试阶…

isinstance()和insubclass()

​​isinstance() 和 issubclass() 的功能与用法​​​​1. isinstance(obj, classinfo)​​​​功能​​&#xff1a;检查对象 obj 是否是 classinfo 类&#xff08;或其子类&#xff09;的实例。 ​​返回值​​&#xff1a;True 或 False。 ​​用法​​&#xff1a;class A…

判断QMetaObject::invokeMethod()里的函数是否调用成功

今天&#xff0c;在Qt编程&#xff0c;碰到一个需要使用invokeMethod方式来获取函数是否执行成功的情况。     invokeMethod()即可以同步调用&#xff0c;也可以异步调用。若调用者、被调用者&#xff0c;都在同一个线程&#xff0c;则是同步调用&#xff1b;若调用者、被调用…

【linux】特殊权限

us对文件&#xff1a;用户执行该文件时&#xff0c;会以文件所有者的权限运行chmod us filename # 符号模式 chmod 4755 filename # 数字模式&#xff08;4表示SetUID&#xff09;典型应用&#xff1a;/usr/bin/passwd&#xff08;允许普通用户修改自己的密码&#xff0c;…

OpenCV:指纹识别

目录 一、核心算法 1&#xff1a;SIFT 特征提取&#xff08;尺度不变特征变换&#xff09; 1.1 算法原理&#xff08;4 步核心流程&#xff09; 1.2 重点代码实现与参数解析 1.3 关键输出解读 二、核心算法 2&#xff1a;FLANN 特征匹配&#xff08;快速最近邻搜索&#x…

快速排序:高效的分治排序算法

快速排序因其平均时间复杂度$O(n\log n)$而成为广泛应用的高效排序算法。其核心是分治法: 选择基准 (Pivot):从待排序序列中选取一个元素(如第一个元素$arr[0]$)。 分区 (Partition):将序列重新排列,所有小于基准的元素置于其前,大于或等于的置于其后。基准元素最终位于…

网络编程之UDP广播与粘包问题

一&#xff0c;广播简介从上述讲的例⼦中&#xff0c;不管是TCP协议还是UDP协议&#xff0c;都是”单播”, 就是”点对点”的进⾏通信&#xff0c;如果要对网络里面的所有主机进⾏通信&#xff0c;实现”点对多”的通信&#xff0c;我们可以使用UDP中的⼴播通信。 理论上可以像…

教育领域大模型生成题目安全研究报告

教育领域大模型生成题目安全研究报告 一、研究背景与意义 随着大语言模型&#xff08;LLM&#xff09;在教育领域的深度应用&#xff0c;自动生成题目已成为提升教学效率、实现个性化教学的关键技术手段&#xff0c;广泛应用于课堂练习、作业布置、考试命题等场景。然而&…

Android安卓项目调试之Gradle 与 Gradle Wrapper的概念以及常用gradle命令深度详解-优雅草卓伊凡

Android安卓项目调试之Gradle 与 Gradle Wrapper的概念以及常用gradle命令深度详解-优雅草卓伊凡好的&#xff0c;我们来详细梳理一下 Android 开发中 Gradle 的常用配置和调试命令。这对于每一位 Android 开发者来说都是必须掌握的核心技能。第一部分&#xff1a;Gradle 与 Gr…

Maven入门_简介、安装与配置

ZZHow(ZZhow1024) 参考课程&#xff1a; 【尚硅谷新版Maven教程】 [https://www.bilibili.com/video/BV1JN411G7gX] 一、Maven简介 02_依赖管理工具 解决 jar 包的规模问题解决 jar 包的来源问题解决 jar 包的导入问题解决 jar 包之间的依赖 03_构建工具 我们没有注意过…

Spark(1):不依赖Hadoop搭建Spark环境

不依赖Hadoop搭建Spark环境0 概述1 单机安装Spark1.1 下载Spark预编译包1.2 解压和设置1.3 配置环境变量1.4 验证安装2 Spark运行模式2.1 Local模式&#xff08;本地模式&#xff09;2.1.1 Spark Shell2.1.1.1 Python版的Shell2.1.1.2 Scala版的Shell2.1.2 提交独立的Spark应用…

【ThreeJs】【自带依赖】Three.js 自带依赖指南

&#x1f6e0;️ Three.js 辅助库生态手册 定位&#xff1a;覆盖 90% 开发场景的工具选型实操指南&#xff0c;区分「入门必备」和「进阶扩展」。 适用人群&#xff1a;Three.js 新手&#xff08;≥ r132 版本&#xff09;、需要规范开发流程的团队。 1. 控制器&#xff08;Co…

Mac电脑上如何打印出字体图标

背景 我今天打开了一个之前开发的APP&#xff0c;看到项目中用到了字体图标&#xff0c;发现有个“面条”图标用错了&#xff0c;想着修改一下吧。然后用输入法打出”面条“&#xff0c;在输入法的弹窗中就一直往下找&#xff0c;发现并没有出现图标。 想着打出”面条图标“也没…

当AI遇上数据库:Text2Sql.Net如何让“说人话查数据“成为现实

一句话概括&#xff1a;还在为写复杂SQL而头疼&#xff1f;Text2Sql.Net让你用自然语言就能查数据库&#xff0c;堪称程序员的"数据库翻译官"&#xff01; &#x1f3af; 引言&#xff1a;从"SQL地狱"到"自然语言天堂" 想象一下这样的场景&…

整体设计 之 绪 思维导图引擎 之 引 认知系统 之8 之 序 认知元架构 之4 统筹:范畴/分类/目录/条目 之2 (豆包助手 之6)

问题Q68、我们现在仅仅分析了 认知演进 的 “进”的问题&#xff0c;通过层次结构 和 统筹 的同构约束 给出了 不同对象及其对应的操作和约束。 --这句话 你能完全理解吗&#xff08;这意味着 完整的程序细节设计&#xff09;。 还没有分析的还有 “演” 以及组合词 “演进” -…

开始 ComfyUI 的 AI 绘图之旅-Qwen-Image-Edit(十二)

文章标题一、Qwen-Image-Edit1.ComfyOrg Qwen-Image-Edit 直播回放2.Qwen-Image-Edit ComfyUI 原生工作流示例2.1 工作流文件2.2 模型下载3.3 按步骤完成工作流一、Qwen-Image-Edit Qwen-Image-Edit 是 Qwen-Image 的图像编辑版本&#xff0c;基于20B模型进一步训练&#xff0c…

机械制造专属ERP:降本增效与数字转型的关键

转型升级压力下&#xff0c;ERP系统是机械企业破局的得力助手。本文深入解析ERP的核心功能、选型要点与实施价值&#xff0c;助您精准选型&#xff0c;赋能智能制造&#xff0c;全面提升竞争力。在数字化浪潮席卷之下&#xff0c;机械制造企业正面临提质、增效、降本的关键转型…

npm / yarn / pnpm 包管理器对比与最佳实践(含国内镜像源配置与缓存优化)

这篇不是“谁更快”的玄学讨论,而是把团队能落地的做法一次说清:如何选型、如何统一版本、如何把镜像与缓存配好、如何在 CI 和 Monorepo 下稳住“可重复构建”。 一、结论先说在前 单仓库 / 以稳定为先:直接用 npm(配合 npm ci) 足够,维护成本低,生态一等一,Node 16.1…