news 2026/9/10 11:50:44

JVM面试考点全解析:从内存模型到实战排查

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JVM面试考点全解析:从内存模型到实战排查

从牛客面经到真正懂JVM:那些被问烂了却总答不透的考点,我帮你一次理顺

刷过牛客JVM面经的朋友应该都有这种感觉:整天背“运行时数据区分为堆、栈、方法区”,背“GC Roots可达性分析”,结果面试官换个角度问“JDK和JRE到底啥区别”“Docker容器里Java进程被杀了日志在哪看”,一下子卡壳。原因很简单——八股只给了你答案,没给你背后的逻辑链。

这篇文章不搞长篇大论的理论堆砌,我把牛客上高频出现的JVM面试题重新梳理了一遍,按“基础概念→内存模型→垃圾收集器→参数与排查→实战追问”这条线串起来。每一块不仅告诉你怎么答,还会解释为什么这么答、面试官追问时怎么接住,最后附上真实项目里的排查经验。适合准备校招、社招的Java开发,也适合那些“天天写业务但没系统看过JVM”的同学。

1. 先理清最容易被问懵的基础题:JDK、JRE、JVM到底是什么关系

1.1 三者的定义与层次关系

牛客上关于“JDK和JVM、JRE的区别”这类题,出现频率极高,而且经常放在面试的第一题当作“暖场题”。别小看它,我见过不少人在这一题上翻车,因为平时写代码根本不会去区分这几个概念。

一句话版本:JVM是虚拟机本身,JRE是运行Java程序的最小环境,JDK是开发Java程序所需的完整工具包。它们的关系是层层包含的。

展开说:

  • JVM(Java Virtual Machine,Java虚拟机):负责把字节码解释/编译成机器码并执行。它是跨平台的核心,Java能“一次编写,到处运行”靠的就是它屏蔽了操作系统差异。JVM不区分操作系统,它只认.class文件里的字节码。
  • JRE(Java Runtime Environment,Java运行时环境):包含JVM,还包含Java核心类库(rt.jar、java.lang、java.util这些)以及运行所需的支撑文件。如果你只需要运行别人写好的Java程序(比如跑一个Spring Boot的jar包),装JRE就够了。
  • JDK(Java Development Kit,Java开发工具包):包含JRE的全部内容,另外增加了开发工具,最典型的是javac(编译器)、jar(打包工具)、javadoc(文档生成工具)、jvisualvm、jconsole等诊断工具。写代码必须靠JDK。

打个生活化的比方:JVM相当于发动机,JRE是装好发动机和汽油的一台车,JDK则是这套车加上维修工具、说明书和一套完整的生产线设备。你要开车(运行),JRE够用;你要造车(开发),必须JDK。

1.2 面试官喜欢怎么追问

这一题的追问方向,通常有三个。

追问一:“那JDK装完之后,JRE在哪?是不是单独装一个JRE才行?”——其实JDK安装目录下就自带一个jre文件夹,但真正跑Java程序时,JVM不一定从这个jre目录加载。用java -versionjavac -version可以验证两者版本是否一致,如果机器上装了多个JDK,就很容易出现“javac是17但java -version显示1.8”的错乱。

追问二:“没有JRE能跑Java吗?”——理论上,如果你手动把JDK里的jmods、bin目录下必要的组件拼齐,某些场景下能跑,但极不推荐。实际项目部署中,JDK或者基于JDK的镜像才是主流选择,因为线上排查问题需要jstack、jmap这些工具,光有JRE啥都干不了。这也是我强烈建议服务器上直接装JDK的原因,别省那点磁盘空间。

追问三:“JVM、JRE、JDK各自做了什么升级?”——典型例子是JDK 9之前JRE可以独立安装,JDK 9引入模块化系统(JPMS)之后,JRE和JDK的结构发生了大变化,独立JRE安装包被取消了。如果你面试的岗位要求比较新,能答出这个演变过程会加分不少。

2. JVM内存模型:面试必背也最容易翻车的区域

2.1 运行时数据区全景

“JVM内存模型”是牛客面经里出现频率最高的词条之一,基本属于必考内容。注意别把它和Java并发里的“内存模型(JMM)”搞混,JMM讲的是线程间共享变量的可见性规则,而这里说的运行时数据区是JVM在运行Java程序时在内存里划出来的几个区域。

按《Java虚拟机规范》的划分,运行时数据区包括以下几块:

  • 程序计数器(Program Counter Register):当前线程正在执行的字节码行号指示器。每条线程都有一个独立的程序计数器,各线程之间互不影响。这个区域是唯一一个不会抛出OutOfMemoryError的区域,听起来很绕,但记住关键点就行——线程切换后要靠它恢复执行位置。
  • 虚拟机栈(Java Virtual Machine Stack):生命周期和线程相同。每当一个方法被执行时,JVM会创建一个栈帧,栈帧里存放局部变量表(基本类型值和对象引用)、操作数栈、动态链接、方法出口等信息。方法调用和返回的过程,本质上就是栈帧入栈和出栈的过程。这个区域最常见的异常是StackOverflowError,递归没写终止条件就会遇到。
  • 本地方法栈(Native Method Stack):为JVM调用本地方法(native方法)服务。HotSpot虚拟机把本地方法栈和虚拟机栈合二为一了,所以面试时如果问到HotSpot的线程栈,不用刻意区分这两者。
  • Java堆(Java Heap):所有线程共享的内存区域,对象实例和数组在这里分配。堆是垃圾收集器管理的主要区域,所以也叫“GC堆”。堆的细分会在后面专门讲。
  • 方法区(Method Area):存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等。JDK 8以前方法区的实现叫永久代(PermGen),JDK 8开始改为元空间(Metaspace),直接使用本地内存。

牛客上经常有人问“JDK和JVM、JRE的区别”时会绕到“JVM内存模型”,这两个话题确实经常被串在一起考。我的建议是,把运行时数据区画成一张图背下来,然后把每个区域“存什么、会抛什么异常、线程私有还是共享”三个维度列成表,这样不管面试官从哪个角度问都能答上来。

2.2 堆内存的分代设计与高频追问

面试官问完“堆是什么”之后,大概率会追一句:“那堆默认怎么划分?”这就进入了分代包的话题。

经典分代把堆分成老年代和新生代,新生代里面再分为Eden区、From Survivor区、To Survivor区,默认比例是8:1:1(可以通过-XX:SurvivorRatio调整)。对象创建时优先在Eden区分配,经过一次Minor GC如果还存活,就进入Survivor区,每熬过一次GC年龄加一,达到阈值(默认15)后进入老年代。

面试官在这里一般会问三个高频问题:

  1. 为什么要分代?答:绝大多数对象都是朝生夕死的,分代后可以根据不同区域对象的存活特点采用不同的回收策略,新生代用复制算法效率高,老年代用标记-整理或标记-清除算法减少内存碎片,整体上让GC的停顿时间更可控。
  2. 为什么Survivor区要用两个?答:复制算法要求有足够的空闲空间作为存活对象的“避难所”。如果只有一个Survivor区,GC时Eden存活对象无处安放;用两个Survivor区可以让GC时把存活对象从Eden+From复制到To,过程中完成整理,避免内存碎片化。
  3. 对象一定先分配在Eden吗?答:不一定。大对象会直接进入老年代(通过-XX:PretenureSizeThreshold设置阈值),目的是避免大对象在Eden和两个Survivor之间来回复制产生巨大的复制开销。另外,如果设置了-XX:MaxTenuringThreshold,动态年龄判断也可能让对象提前晋升。

2.3 面试陷阱:栈上分配、逃逸分析与TLAB

这里要友情提示一下,牛客上很多面经答案会把“栈上分配”和“TLAB”混为一谈,面试时常被追问出问题。这两个东西要分开理解。

栈上分配是JIT编译器在编译时做逃逸分析后,发现某些对象的作用域只在方法内部、不会逃逸出方法体,于是直接把对象成员变量拆散到栈帧或寄存器里,避免在堆上分配内存。注意,这依赖JIT编译器和逃逸分析,不是所有情况都能做到。

TLAB(Thread Local Allocation Buffer,线程本地分配缓冲区)则是HotSpot为了提升“在堆上分配内存”的效率而做的一个优化。每个线程在Eden区划一小块私有空间,线程创建对象时先在TLAB里分配,避免多个线程争抢同一块堆内存的锁竞争。TLAB的默认大小约等于Eden空间的1%,可以通过-XX:TLABSize调整。

面试官如果问“JVM是怎么优化的”,从这两块入手答会显得你了解深入。答的时候注意逻辑:逃逸分析发生在编译期,决定对象能不能栈上分配;TLAB发生在运行时,决定对象在堆上的哪个位置分配。

3. 垃圾收集器与G1:从八股到原理

3.1 经典收集器对比

JVM面试题里,“G1收集器”是热词榜上的常客,但想答好G1,得先把它的前辈们搞明白。牛客上的高频问法是:“CMS和G1有什么区别?”“你了解哪几种垃圾收集器?”

建议按时间线和适用场景来回答,这样既不乱也不容易漏:

  • Serial收集器:单线程收集器,GC时必须暂停所有工作线程(Stop The World)。虽然是“最古老”的收集器,它在客户端模式下的简单场景仍然可用。
  • ParNew收集器:Serial的多线程版本,专注新生代,和CMS搭配使用是JDK 8早期非常经典的组合。
  • Parallel Scavenge:新生代的并行收集器,目标是“可控的吞吐量”,注重的是CPU利用效率,适合后台计算任务。对应老年代的Parallel Old收集器,两者组合是JDK 8默认的GC组合(至少在JDK 8里,Parallel Scavenge + Parallel Old是默认)。
  • CMS收集器:老年代收集器,首个真正意义上的并发收集器。它采用标记-清除算法,目标是缩短STW时间。缺点也很明显:容易产生内存碎片、对CPU资源敏感、无法处理浮动垃圾。JDK 9以后被标记为废弃,JDK 14正式移除。
  • G1收集器:JDK 9以后的默认收集器,面向服务端,把堆划分成多个Region,兼顾吞吐和停顿时间可控。

面试官如果让你选型,标准回答逻辑是:低延迟场景优先考虑G1或CMS(在支持范围内);高吞吐后台任务可以考虑Parallel组合;要求可控停顿时间则G1是首选。只要把选型理由和业务特征结合起来,这题基本稳过。

3.2 G1的Region设计

G1(Garbage First)的全名是Garbage First Garbage Collector,核心设计目标是在延迟可控的前提下,实现尽可能高的吞吐量。它不再像传统收集器那样严格区分新生代和老年代的物理连续空间,而是把整个堆分成若干个大小相等的独立Region(默认约2048个,每个Region大小从1MB到32MB不等,可以通过-XX:G1HeapRegionSize指定)。

G1的回收流程大致是:

  1. 初始标记(Initial Mark):STW较短,标记GC Roots直接可达的对象。
  2. 并发标记(Concurrent Mark):和用户线程并发执行,从GC Roots做可达性分析。
  3. 最终标记(Final Mark):STW,处理并发阶段遗留下来的SATB(Snapshot At The Beginning)缓冲区记录。
  4. 筛选回收(Live Data Counting and Evacuation):对各个Region的回收价值和成本进行排序,根据用户期望的GC停顿时间(通过-XX:MaxGCPauseMillis设置,默认200毫秒)来制定回收计划,动态选择回收哪些Region。

你可能听说过“G1是分代收集器吗”这个问题。标准答案是:G1逻辑上仍然保留了新生代和老年代的概念,但这两个代不再是物理上连续的内存块,而是由若干Region“逻辑”组合而成。这样做的好处是回收时可以精确控制哪些Region参与回收,让停顿时间可预测。

另外一个高频追问:“G1和CMS谁更好?”——G1能更好地控制停顿时间,而且没有内存碎片问题,但吞吐量在特定场景下可能不如Parallel组合。不要直接说“G1全面优于CMS”,面试官想听的是你对两者特性差异的理解。

3.3 面试追问:怎么判断对象已死?

要讲GC,前提是搞清楚哪些对象可以回收。这个问题在牛客上几乎必考,标准答案是“可达性分析”。

从一组叫做GC Roots的对象出发,沿着引用链向下搜索,搜索过程走过的路径称为引用链。如果某个对象到GC Roots之间没有任何引用链相连,就说明这个对象“不可达”,可以被判定为可回收对象。

GC Roots包含哪些对象?需要记牢这几类:

  • 虚拟机栈中引用的对象(栈帧里的局部变量表)
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI引用的对象
  • JVM内部的引用(基本类型对应的Class对象、一些常驻的异常对象如NullPointerException等)
  • 所有被同步锁(synchronized关键字)持有的对象

面试官比较爱追问“那引用类型有几种?”——正确答案是四种:强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)。软引用在内存不足时会被回收,弱引用在下一次GC时就会被回收,虚引用主要用于对象回收跟踪。这题答完,往往紧接着就问“那ThreadLocal的内存泄漏问题你怎么看”,属于经典连环问,提前准备好这类串联问题会很有优势。

4. JVM关键参数与排查实战

4.1 高频面试参数:-XX:CompileThreshold 这类参数到底在调什么

牛客热词里出现了jvm参数 -xx:compilethreshold,这其实是个很有意思的考点。它跟JIT编译相关,和你平时调堆大小(-Xmx-Xms)完全不是一回事。

-XX:CompileThreshold控制的是方法调用多少次之后触发JIT编译。HotSpot默认解释执行字节码,当某个方法被调用足够多次(即“热点代码”),JIT编译器会把它编译成机器码缓存起来,后续执行直接跑机器码,速度显著提升。默认值在服务端模式下是10000次,客户端模式是1500次。调低这个值,可以让热点代码更早被编译,但也会增加编译线程的负担;调高则反之。

面试官问这题,通常不是真让你报个数字,而是考察你“知不知道JIT编译机制”以及“有没有意识去区分解释执行和编译执行”。可以顺着展开:

  • 解释执行:逐条解释字节码,启动快但运行慢。
  • 编译执行:把热点代码编译成本地机器码,启动慢但运行快。
  • 热点检测:HotSpot默认采用基于计数器的热点探测,包括方法调用计数器(Method Counter)和回边计数器(Back Edge Counter)。
  • C1/C2编译器:C1是客户端编译器,编译快但优化程度低;C2是服务端编译器,编译慢但优化更激进。JDK 10之后引入了Graal JIT编译器作为实验性替代。

另外,-XX:CompileThreshold的实际设置还涉及-XX:CompileCommand-XX:ReservedCodeCacheSize等关联参数。CodeCache是JIT编译后机器码存放的空间,如果太小导致JIT编译失败,控制台会发CodeCache is full警告,该场景在微服务频繁热部署时经常出现。

4.2 线上问题排查:Docker容器中Java程序异常重启,日志去哪找

牛客热词里有“docker 容器部署的java程序,异常重启 jvm日志在哪儿”,说明真实的工程场景已经深入面试提问里了。这个问题很实用,不像纯八股,答好了能直接证明你有生产经验。

先说结论:Docker容器里Java应用异常重启,你得先区分是JVM自己崩了,还是容器被杀了。

场景一:JVM进程自己崩溃。这种通常会在标准输出里留下异常栈,但容器一重启,控制台输出就没了,你查不到历史日志。所以正确做法是:在启动命令里显式配置JVM日志输出文件。例如:

java -Xlog:gc*:file=/logs/gc.log:time,uptime,level \ -Xlog:all=warning:file=/logs/jvm.log:time,uptime \ -jar app.jar

这是 JDK 9+ 的写法,用-Xlog统一管理日志输出,能把你需要的GC日志、JVM内部警告集中落盘。JDK 8的话要分开写,GC日志用-Xloggc:/logs/gc.log,OOM时的堆转储用-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/logs/oom.hprof

场景二:容器被杀(最常见)。如果你看到容器退出码是137,或者Docker事件里出现OOMKilled,那多半是容器内存超限被内核OOM Killer清理了。此时JVM日志里往往什么都没来得及写,因为不是Java层抛出的错误。排查思路按顺序来:

  1. docker inspect看容器的OOMKilled字段是否为true
  2. dmesgjournalctl -k查看宿主机内核日志,找Out of memory: Kill process的记录。
  3. 检查JVM堆内存设置是否超出了容器内存限制。经典的坑:容器Memory限制为1GB,但JVM启动时用默认堆大小,在物理内存大的宿主机上JVM会按物理内存1/4配置堆,直接超过容器配额被杀。
  4. 加上-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0这类参数,让JVM正确感知容器内存限制。JDK 8u191+默认开启容器感知,旧版本不行。

我踩过最深的坑是:Spring Boot应用在K8s里频繁重启,kubectl logs全是正常启动日志,没有任何异常,最后发现是容器cgroup的memory限制引起的。从那之后,我在所有Java应用镜像里都会强制加上-XX:MaxRAMPercentage=75.0-XX:+HeapDumpOnOutOfMemoryError,并单独挂载一个日志目录。

4.3 面试陷阱:SQL执行10秒自动关闭,是JVM或Spring Boot管的吗?

牛客上有这样一个问题:“jvm或者spring boot会设置一个sql执行10秒自动关闭吗?”——这题考察的是你对“JVM职责边界”的理解。

这里我可以很明确地回答:JVM不负责SQL超时关闭,Spring Boot默认也不会帮你做这种全局自动关闭。SQL执行超时控制通常由数据库连接池、ORM框架或数据库自身配置管理。

拆开来看:

  • JDBCStatement可以设置setQueryTimeout(10),单位是秒。这个超时由驱动实现,MySQL驱动通过 socketTimeout 和 JDBC 层配合实现,超过时间抛SQLTimeoutException
  • MyBatis可以在SQL映射文件里配置timeout属性,它最终也是交给JDBC层的setQueryTimeout来做。
  • 连接池(如HikariCP、Druid)里有connectionTimeoutvalidationTimeoutmaxLifetime等参数,控制的是连接获取和连接存活时间,不是单次SQL执行时间。
  • 数据库端,MySQL的max_execution_time(针对SELECT)或innodb_lock_wait_timeout(控制锁等待)属于数据库层面的限制。

所以面试时遇到这题,你要先纠正一下概念:这是“机制归属”问题,不是“默认参数数值”问题。优雅的回答是:“JVM本身不管SQL超时,但应用程序可以通过JDBC的setQueryTimeout、MyBatis的timeout配置或连接池参数来实现。如果在Spring Boot里需要全局统一超时控制,可以用拦截器或切面对所有Mapper方法做统一处理。”

5. 牛客面经里常见的问题整理与回答思路

5.1 高频题速查表

我在牛客上刷了几百条JVM相关的面经,把提问频率最高的题目整理成一个速查表。这套表不是为了让你死记硬背,而是帮你检测自己哪些地方理解得还不够深。

高频题目核心回答要点常见补充追问
JDK/JRE/JVM的区别层层包含,JVM运行字节码,JRE含JVM和核心类库,JDK含开发工具为什么装JDK就能跑程序
JVM内存模型五块区域,分成私有/共享两类,各区域存什么、抛什么异常程序计数器为什么不OOM
堆的分代划分Eden、Survivor(From/To)、老年代及比例对象什么时候进入老年代
判断对象是否可回收可达性分析+GC Roots,谈引用类型什么是浮动垃圾
常见GC组合Serial、Parallel、CMS、G1的特点和适用场景JDK 8默认GC是什么
G1收集器Region化堆内存、可预测停顿、SATBG1和CMS的区别
JVM调优参数-Xms/-Xmx、-XX:NewRatio、-XX:MaxGCPauseMillis、-XX:CompileThresholdOOM怎么排查
线上故障排查jstack看线程、jmap看堆、jstat看GC、Arthas等工具链容器OOMKilled怎么定位
强软弱虚引用引用级别和回收时机ThreadLocal内存泄漏分析
类加载机制加载、验证、准备、解析、初始化双亲委派模型及为什么要这么做

这张表可以作为你的自查清单。每一条里如果有一个“追问”你答不上来,就说明对应的知识链路还没打通。

5.2 回答技巧:八股怎么答才不呆板

背八股本身没错,但面试官一听你背答案,耐心马上减半。我的经验是用“项目经验”或“踩坑案例”来包装知识点,让答案有血有肉。光说一个知识点很干,但提到自己遇到过什么场景、怎么排查、用了什么命令、结果如何,这就是另一个层次了。

举一个例子。面试官问:“你了解G1收集器吗?”

不好回答:“G1是一种垃圾收集器,把堆分成Region,可以控制停顿时间。”

好一点的回答:“我之前在项目里遇到过老年代GC停顿过长的问题。当时使用的是PDK 8默认的Parallel组合,高峰期老年代占用偏高,Full GC一次要几百毫秒。后来我把应用切到G1,设置了-XX:MaxGCPauseMillis=100,并且通过-XX:G1HeapRegionSize=4m调整Region大小,再加上堆外内存和对象生命周期的优化,GC停顿时间明显下降。在处理过程中我发现G1的并发标记阶段CPU占用的峰值挺高,所以还要结合应用本身的CPU负载来评估。”

这样的回答既展现了知识点,又体现出你有真实的定位问题、调优和验证的能力。面试官要的不是一个复读机,是一个会解决问题的工程师。

另一个小建议:不要把JVM和Spring Boot、数据库的知识完全割裂开。现在的面试题越来越喜欢跨层综合,比如问“WAR包部署和JAR包部署对JVM有什么影响”,或者“大型电商系统的JVM参数怎么设”——这种题考验的是你把JVM知识放到真实架构里去应用的能力。

5.3 从面经到看源码:理解JVM的不二法门

面经刷到一定程度后,你会发现所有知识点都能在OpenJDK源码里找到对应实现。不必通读全部源码,但以下几个源码片段非常值得看:

  • share/vm/memory/Heap.cppCollectedHeap相关类:看堆的初始化和GC入口。
  • share/vm/gc/g1/目录:看G1的整个GC流程,包括G1CollectedHeap::do_collectionG1ConcurrentMark等。
  • share/vm/runtime/Thread.cppJavaThread:看线程栈、程序计数器的实现。
  • share/vm/oops/klass.hppinstanceKlass.hpp:看方法区存储的类元信息。

在牛客上,有面试官会问“你有没有看过JVM源码中的某一处”,这个问题其实是在筛选那种“只背八股但没深入学习”的候选人。哪怕你不能完整讲出源码调用链,只要提“我了解G1的GC流程在源码里主要入口是G1CollectedHeap的do_collection方法,它内部会经过并发标记和整理回收两个阶段”这种回答,就能拉开差距。

6. 实操总结:如何搭建一套自己的JVM排查环境

说了这么多理论,最后分享一套我在本地搭建的JVM排查练习环境。这套东西很简单,但值得每个人动手试一遍,比单纯刷牛客面经有用一百倍。

首先准备一个小Java程序:

public class MemoryDemo { public static void main(String[] args) throws Exception { List<byte[]> list = new ArrayList<>(); while (true) { list.add(new byte[1024 * 1024]); Thread.sleep(50); } } }

然后分三步走:

第一步,用JDK自带的jcmd查看参数:jcmd <pid> VM.flags,能看到JVM启动时的最终生效参数,包括-XX:CompileThreshold-XX:MaxHeapSize等。这一步能帮你建立“参数生效值”的概念。

第二步,用jstat观察GC情况:jstat -gcutil <pid> 1000,每秒输出一次各内存区域的使用百分比和GC次数。运行上面的OOM程序,你能亲眼看到Eden区从快速增长到GC触发、对象晋升、老年代占满、最后OOM的完整过程。

第三步,用jmap导出堆快照:jmap -dump:format=b,file=heap.hprof <pid>,再用jhat或Eclipse MAT分析对象构成。看看到底是什么对象撑爆了堆。

如果你在Docker环境里做实验,建议带上-XX:+UseContainerSupport跑一遍,再故意去掉这个参数跑一遍,对比容器OOMKilled时的表现差异。这个实验能让你彻底理解容器环境下JVM参数为什么要显式设置。

这套方法比刷一百道题都更能加深理解。面试官问你“JVM日志在哪看”“怎么排查OOM”,你能直接拿出真实的操作过程来回答,这就是你和其他候选人的分水岭。

最后说点实在的。刷牛客面经是个很好的起点,但真正的成长在于把每个面试题还原成实际场景,去思考“如果线上出了这个问题,我该怎么应对”。现在JVM面试越来越偏向实战化,单纯背八股越来越难蒙混过关。建议你每整理一个知识点,就亲手在本地环境验证一遍,把那些看起来理所当然的结论用自己的眼睛确认一遍。踩过坑,才记得住。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/4 14:11:40

SAM 图像分割快速上手指南:点一个点就能得到对象掩码

SAM 图像分割快速上手指南&#xff1a;点一个点就能得到对象掩码 【免费下载链接】segment-anything The repository provides code for running inference with the SegmentAnything Model (SAM), links for downloading the trained model checkpoints, and example notebook…

作者头像 李华
网站建设 2026/9/3 17:21:43

Signal付费无手机号注册:账号体系与隐私通信的技术解析

最近一条和 Signal 有关的消息值得关注&#xff1a;Signal 正在测试一种“付费创建一个不绑定手机号的账号”的方案。这个消息对普通用户可能只是“注册更方便”&#xff0c;但对从事加密通信、隐私保护、自动化集成、企业合规工作的开发者来说&#xff0c;背后涉及账号体系、身…

作者头像 李华
网站建设 2026/9/4 20:05:59

公共艺术品资产与维护成本管理系统:Spring Boot + Vue 3 实战

最近看到一条挺有意思的新闻话题&#xff1a;“Banksy works cost public almost £150k”。抛开艺术品争议不谈&#xff0c;这件事给技术人员留了一个很现实的思考&#xff1a;公共艺术品一旦进入城市&#xff0c;后续的清洁、修复、安保、保险甚至拆除&#xff0c;都会变…

作者头像 李华
网站建设 2026/9/4 21:00:05

【DeepSeek Harness 基石-Cordis元框架】入门指南与六大核心概念解析

文章目录 1. 项目概述 1.1 什么是 Cordis 1.2 项目状态 1.3 适用场景 1.4 设计哲学 1.5 Deepseek Harness与Cordis的关系 2. 快速开始 2.1 环境要求 2.2 安装 2.3 最简示例 2.4 使用脚手架创建项目 2.5 项目结构 2.6 使用 CLI 启动 3. 核心概念:Context(上下文) 3.1 什么是 …

作者头像 李华