基于Git与Jacoco的增量代码覆盖率精准统计方案
1. 为什么我们需要增量代码覆盖率如果你做过持续集成肯定对代码覆盖率报告不陌生。每次跑完测试Jacoco都会生成一份报告告诉你哪些代码被测试覆盖了哪些还是“裸奔”状态。但不知道你有没有遇到过这种情况一个已经稳定运行了几个月的老项目整体覆盖率可能只有60%新来的同事写了几百行代码测试写得非常认真但一合并到主分支整体覆盖率可能只提升了0.1%甚至因为分母总代码量变大了覆盖率反而下降了。这合理吗显然不合理。老板可能会问“我们最近不是一直在强调质量吗怎么覆盖率没见涨” 你很难解释清楚因为老代码的历史欠账拖累了新代码的优秀表现。这就是全量覆盖率统计的尴尬之处它无法精准反映本次改动的代码质量。我们真正关心的是这次提交、这个需求、这个迭代里新写或者修改的代码测试写得怎么样增量代码覆盖率就是为了解决这个问题而生的。它只关注两个版本之间发生变化的代码比如你从main分支拉出一个feature/login分支开发了两周这期间新增或修改的所有类和方法就是增量代码。我们的目标就是精准地统计这部分代码的测试覆盖情况。我经历过好几次因为全量覆盖率不达标而卡住发布团队不得不花时间去补一些陈年老代码的测试而这些代码可能已经稳定运行了几年修改风险远大于收益。自从引入了增量覆盖率统计我们的关注点就清晰了确保新增代码有高标准的测试覆盖。发布卡点变成了“增量覆盖率必须达到85%”这直接推动了开发同学在写业务代码的同时就养成编写测试的习惯质量门禁变得更有意义团队效率也提高了。2. 实现思路三种方案的权衡想要实现增量覆盖率核心思路其实就两步第一找到哪些代码是“增量”的第二让Jacoco只统计这些增量代码的覆盖情况。围绕这个核心业界主要有三种实现路径我在实际选型时都仔细琢磨过。第一种修改Jacoco的插桩阶段。简单说就是在Jacoco给字节码“打点”的时候就判断当前正在插桩的类或方法是否属于增量代码列表如果不是就直接跳过。这个方案非常“根源”理论上效率最高因为它从一开始就避免了收集无关代码的执行数据。但它的门槛也最高你需要深入理解Jacoco的插桩机制和Java字节码操作ASM框架相当于要对Jacoco的核心逻辑动手术。除非你们团队有深厚的字节码功底否则调试和维护成本会很高。第二种修改Jacoco的报告生成阶段。这是目前最主流、也是我个人最推荐的做法。它的思路是Jacoco正常收集所有代码的执行数据但在最后生成HTML或XML报告时我们介入处理。我们告诉Jacoco一个增量代码的列表Jacoco在遍历所有类和方法准备生成报告项时会先判断当前项是否在增量列表中只有命中了的才进行统计和输出。这样做的好处是我们无需触碰复杂的插桩逻辑只需要在报告生成这个相对“上层”的环节进行过滤。对Jacoco源码的改造范围小更可控也更符合我们“增量统计”的直觉。第三种后处理全量报告。即先让Jacoco生成完整的全量覆盖率报告然后我们自己写一个解析程序像“筛子”一样把报告中属于增量代码的部分过滤出来重新组装成一份报告。这个方法听起来很“取巧”完全不用改Jacoco。但它的问题也很明显精度可能受损而且有“浪费”。Jacoco已经费劲计算了所有代码的覆盖率我们却只取其中一小部分之前的计算成了沉没成本。更重要的是报告结构的解析和重组并不简单容易出错。所以综合来看第二种方案——改造报告生成阶段——在复杂性、可控性和准确性上取得了最好的平衡。我们接下来的实战也将围绕这个方案展开。它就像是在Jacoco的流水线末端加装了一个智能分拣装置只把我们关心的“包裹”挑出来打包。3. 第一步用Git和Javaparser精准抓取增量代码要实现增量统计首先得把“增量”是什么定义清楚。我们的输入通常是两个Git版本比如一个旧的基线版本baseVersion和一个新的特性版本nowVersion。输出则是一个列表清晰地告诉我们哪些类是新增的哪些类是修改的对于修改的类具体是哪些方法发生了变化。3.1 核心工具选型这里我们需要两个利器JGit它是Git的纯Java实现库。我们不需要在服务器上安装Git命令行工具直接用JGit的API就能完成克隆仓库、比较版本差异等所有操作非常适合集成到Java应用中。JavaParser这是一个强大的Java源代码解析库。它能将Java文件解析成一棵抽象语法树AST。为什么不用直接比较.class文件呢因为字节码对比太“底层”了一个简单的空格换行都可能导致字节码不同但我们关心的其实是源代码逻辑层面的变化。JavaParser能帮我们精准地识别出方法签名和方法体的变化。在你的Maven项目中需要引入它们dependency groupIdorg.eclipse.jgit/groupId artifactIdorg.eclipse.jgit/artifactId version6.6.0.202305091015-r/version /dependency dependency groupIdcom.github.javaparser/groupId artifactIdjavaparser-core/artifactId version3.25.2/version /dependency3.2 获取差异文件列表首先我们用JGit把两个版本的代码都拉到本地或内存中然后进行差异比较。我们只关心业务代码所以要做好过滤文件类型只处理.java文件。源码目录通常只关注src/main/java下的生产代码排除src/test下的测试代码。变更类型只关注ADD新增和MODIFY修改。DELETE删除的代码不需要统计覆盖率。下面是我封装的一个核心方法它返回一个DiffEntry的列表每个DiffEntry代表一个发生变化的Java文件。public ListDiffEntry getDiffFiles(String gitUrl, String baseVersion, String nowVersion) throws GitAPIException, IOException { // 1. 克隆或打开两个版本的仓库 try (Git baseGit Git.cloneRepository() .setURI(gitUrl) .setDirectory(new File(/tmp/repo_base)) .setBranch(baseVersion) .call(); Git nowGit Git.cloneRepository() .setURI(gitUrl) .setDirectory(new File(/tmp/repo_now)) .setBranch(nowVersion) .call()) { // 2. 准备两个版本的树解析器 ObjectId baseTree baseGit.getRepository().resolve(baseVersion ^{tree}); ObjectId nowTree nowGit.getRepository().resolve(nowVersion ^{tree}); // 3. 执行差异比较 ListDiffEntry diff nowGit.diff() .setOldTree(new TreeWalkIterator(baseGit.getRepository(), baseTree)) .setNewTree(new TreeWalkIterator(nowGit.getRepository(), nowTree)) .call(); // 4. 过滤出我们关心的Java业务文件 return diff.stream() .filter(entry - entry.getNewPath().endsWith(.java)) .filter(entry - entry.getNewPath().contains(src/main/java/)) .filter(entry - entry.getChangeType() DiffEntry.ChangeType.ADD || entry.getChangeType() DiffEntry.ChangeType.MODIFY) .collect(Collectors.toList()); } }3.3 深入方法级识别真正改动的代码行拿到差异文件列表只是第一步。一个文件被标记为MODIFY可能是修改了某个方法也可能是只加了注释或改了格式。我们需要更细的粒度。这就是JavaParser大显身手的地方。我们的策略是对比同一个文件在两个版本中的AST找出所有方法并计算每个方法的“指纹”。如果新版本中某个方法的指纹在旧版本中不存在那它就是增量方法。如何计算方法的“指纹”呢一个简单可靠的方法是计算方法体源码的MD5哈希值。但直接对整个方法体字符串做MD5对格式变化如换行、空格太敏感。更好的做法是先用JavaParser获取方法体的AST节点然后使用一个“规范化”的访问者模式来遍历节点忽略注释和空格只关注有实际意义的语法元素如语句、表达式再基于此生成哈希。这里为了简化我们先采用方法名参数列表简化后方法体MD5的方式。public class MethodParserUtils { public static ListMethodInfo parseMethods(File javaFile) { ListMethodInfo methodList new ArrayList(); try { CompilationUnit cu StaticJavaParser.parse(javaFile); cu.accept(new VoidVisitorAdapterVoid() { Override public void visit(MethodDeclaration md, Void arg) { super.visit(md, arg); // 获取方法签名名称参数类型 String methodName md.getNameAsString(); String params md.getParameters().stream() .map(p - p.getType().asString()) .collect(Collectors.joining(,)); // 获取方法体并计算MD5这里可以优化为规范化后的AST哈希 String methodBody md.getBody().map(Node::toString).orElse(); String md5 DigestUtils.md5DigestAsHex(methodBody.getBytes()); methodList.add(new MethodInfo(methodName, params, md5)); } }, null); } catch (IOException e) { e.printStackTrace(); } return methodList; } }有了这个方法解析器我们就能对每个MODIFY类型的差异文件分别解析新旧两个版本然后对比两个方法列表。新版本中存在但旧版本中不存在通过方法名参数MD5联合判断的方法就是我们要找的增量方法。3.4 组装最终结果最终我们会生成一个结构化的数据大概是这样的JSON格式它清晰地描述了增量代码的图谱{ changedClasses: [ { className: com/example/service/UserService, changeType: MODIFY, changedMethods: [ {methodName: createUser, signature: (Lcom/example/dto/UserDTO;)Ljava/lang/Long;}, {methodName: updateUserStatus, signature: (Ljava/lang/Long;Ljava/lang/Integer;)Z} ] }, { className: com/example/controller/NewController, changeType: ADD, changedMethods: [] // 新增类所有方法都视为增量 } ] }这个结果就是我们下一步要喂给Jacoco的“食材清单”。4. 第二步改造Jacoco源码让它“认识”增量代码现在我们手上有了一份增量代码清单。下一步就是修改Jacoco让它生成报告时能“看懂”这份清单并只统计清单上代码的覆盖率。我们需要下载Jacoco的源码建议从GitHub拉取与你现在使用的版本一致的分支然后进行针对性的改造。4.1 为Report工具添加增量参数Jacoco生成报告的命令行工具是org.jacoco.cli.internal.commands.Report类。我们要给它增加一个命令行参数用来接收我们上一步生成的增量代码信息文件比如一个JSON文件路径。找到Report类的createOptions方法或相关字段添加一个选项Option(name --diffCode, usage Path to the JSON file containing changed class/method info for incremental coverage., metaVar path) private String diffCodePath;这样我们在执行报告生成命令时就可以通过--diffCode changed.json来传入我们的增量清单了。4.2 关键改造点Analyzer与CoverageBuilderJacoco生成报告的核心流程是读取.exec执行数据文件和.class文件通过Analyzer进行分析将结果填充到CoverageBuilder中最后再由Report类根据CoverageBuilder中的数据生成报告。我们的改造主要在两个地方第一在CoverageBuilder中存储增量信息。我们需要修改CoverageBuilder的构造函数让它能接收并存储我们传入的增量代码数据。可以设计一个全局可访问的静态容器比如一个Map以类名和方法签名为Key存储是否需要覆盖的标志。public class CoverageBuilder { private static MapString, SetString incrementalMethodsMap new HashMap(); public CoverageBuilder(String diffCodePath) { // 解析diffCodePath指向的JSON文件将增量方法信息加载到incrementalMethodsMap中 loadIncrementalData(diffCodePath); } // ... 原有代码 }第二在Analyzer中过滤非增量代码。Analyzer类是遍历所有类文件的入口。我们需要在它的analyzeClass方法中加入判断逻辑。如果用户指定了--diffCode参数即incrementalMethodsMap不为空那么对于每一个被分析的类我们先检查它是否在我们的增量清单里。private void analyzeClass(final byte[] source) { final ClassReader reader new ClassReader(source); String className reader.getClassName(); // 形如 com/example/Service // 增量模式开启且当前类不在增量清单中则直接跳过 if (!incrementalMethodsMap.isEmpty() !incrementalMethodsMap.containsKey(className)) { return; } // 如果是增量类继续原有的分析流程... // 但这里我们还需要把className信息传递下去以便在方法级别进行过滤 final ClassVisitor visitor createAnalyzingVisitor(classId, className); reader.accept(visitor, 0); }第三在方法访问器中进行最终匹配。仅仅过滤到类级别还不够因为一个修改的类里可能只有部分方法是新增或改动的。我们需要深入到方法级别。这需要修改ClassProbesAdapter的visitMethod方法。在这个方法里我们能拿到当前正在访问的方法名和描述符签名。用类名方法签名作为Key去查询incrementalMethodsMap。如果匹配成功说明这是一个需要统计覆盖率的增量方法我们才为其创建相应的探针访问器否则我们可以跳过一个方法或者为其创建一个“不收集覆盖信息”的访问器。public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) { // 判断当前方法是否为增量方法 boolean isIncrementalMethod false; String currentClass this.className; // 从外部传入 String methodKey generateMethodKey(name, desc); // 生成唯一标识 if (incrementalMethodsMap.containsKey(currentClass)) { isIncrementalMethod incrementalMethodsMap.get(currentClass).contains(methodKey); } // 根据是否是增量方法决定如何创建MethodVisitor final MethodVisitor mv cv.visitMethod(access, name, desc, signature, exceptions); if (mv null) { return null; } if (isIncrementalMethod) { // 对于增量方法使用正常的探针适配器用于收集覆盖率 final MethodProbesAdapter probesAdapter new MethodProbesAdapter(mv, this.className, name, desc); // ... 返回适配器 } else { // 对于非增量方法返回一个“空”的访问器不收集覆盖率数据 return mv; } }经过这三处改造Jacoco在生成报告时就会“选择性失明”只关注我们指定的增量代码了。最后用Maven或Gradle编译我们修改后的Jacoco源码生成一个定制版的jacococli.jar文件。5. 第三步参数匹配的“坑”与解决方案在改造过程中我踩过一个实实在在的“坑”就是方法参数的匹配问题。这个问题不解决增量匹配就会失灵。我们使用JavaParser从源代码中解析出的方法参数列表是给人看的格式比如String username, int age。而Jacoco内部使用的ASM框架在访问字节码时看到的方法描述符Descriptor是JVM内部表示法叫做“类型描述符”。对于上面的例子ASM看到的描述符是(Ljava/lang/String;I)VV代表返回类型void。你看这完全是两种不同的“语言”。直接拿String username, int age去和(Ljava/lang/String;I)V比较肯定匹配不上。我们必须进行转换让它们在同一个维度上对话。解决方案是使用ASM提供的Type工具类。这个类能完美地解析和转换方法描述符。import org.objectweb.asm.Type; public class MethodSignatureUtil { /** * 将ASM的方法描述符转换为简化的参数类型字符串 * param methodDescriptor 例如 (Ljava/lang/String;I)Z * return 例如 String,int */ public static String descriptorToParamString(String methodDescriptor) { // 获取参数类型数组 Type[] argTypes Type.getArgumentTypes(methodDescriptor); ListString paramList new ArrayList(); for (Type t : argTypes) { // 获取类型的类名并做简化处理 String className t.getClassName(); // 将java.lang.String - String, int - int if (className.startsWith(java.lang.)) { className className.substring(java.lang..length()); } // 对于数组类型如java.lang.String[]我们可能想保留String[] // 这里根据你的匹配策略调整 paramList.add(className); } return String.join(,, paramList); } /** * 生成用于比对的Method Key * param methodName 方法名 * param descriptor 方法描述符 * return 例如 createUser(String,Long) */ public static String generateMethodKey(String methodName, String descriptor) { String params descriptorToParamString(descriptor); return methodName ( params ); } }在从JavaParser获取方法信息时我们也需要生成一个格式一致的Key。JavaParser可以方便地获取参数类型列表我们将其转换为简单的类型名字符串即可。这样两边生成的Key就能对齐了比如都是createUser(String,Long)。匹配的逻辑就变成了简单的字符串相等判断非常可靠。这个“坑”填平后增量代码的识别精度就得到了保证。无论是基本类型、引用类型、泛型在字节码中会被擦除还是数组Type类都能正确处理。6. 实战从命令到报告的完整流程理论说了这么多我们来串一下整个操作流程让你有个清晰的实操画面。假设你的项目是一个标准的Maven Spring Boot应用。第一步准备阶段。在你的CI服务器如Jenkins的构建任务中确保已经通过Jacoco Maven插件生成了代码覆盖率执行数据文件jacoco.exec并且编译好的.class文件和源代码.java文件都是可访问的。第二步生成增量代码清单。在CI的Shell脚本步骤中调用我们之前写好的“增量代码获取”工具。这个工具应该被打包成一个可执行的JAR。java -jar code-diff-tool.jar \ --gitUrl https://your-git-repo.git \ --baseVersion origin/main \ --nowVersion HEAD \ --output changed.json这条命令会比较当前构建的代码HEAD和主分支origin/main的差异并将结果输出到changed.json文件。第三步生成增量覆盖率报告。使用我们改造后、重新编译的Jacoco CLI工具来生成报告。java -jar jacococli-incremental.jar report jacoco.exec \ --classfiles target/classes \ --sourcefiles src/main/java \ --html report/incremental-html \ --xml report/incremental-report.xml \ --diffCode changed.json注意这里用的是我们自定义的jacococli-incremental.jar并且传入了--diffCode参数指向差异文件。这个命令会生成一个只包含增量代码覆盖率的HTML和XML报告。第四步集成与门禁。在CI流水线中我们可以解析生成的incremental-report.xml文件提取出总的增量代码行数、覆盖行数计算出增量覆盖率百分比。然后将这个百分比与预设的质量门禁比如80%进行比较。如果低于阈值就让构建失败并清晰地提示“本次提交的增量代码覆盖率仅为75%未达到80%的要求请补充测试用例。”为了让整个过程更顺畅我建议将“增量代码获取工具”和“定制版Jacoco CLI”都打包成Docker镜像。这样在CI中只需要几行Docker命令就能搞定避免了在CI服务器上配置Java环境和各种依赖的麻烦。整个流程就变成了一个标准化、可复用的质量关卡。7. 可能遇到的问题与进阶思考在实际落地过程中你可能会遇到一些具体问题。比如如何正确处理内部类Inner Class和匿名类在Java字节码中内部类的类名会包含一个$符号例如OuterClass$InnerClass。而我们从Git差异中获取的通常是源代码文件名OuterClass.java。在匹配时需要将内部类映射回其外部类。一个实用的方法是在匹配类名时如果发现incrementalMethodsMap中没有完全匹配的项可以尝试检查当前类名是否以某个增量类名开头例如com/example/OuterClass$是以com/example/OuterClass开头的如果是则将其视为该外部类的增量部分。另一个问题是Lambda表达式和方法引用。它们也会被编译成类中的特殊方法如lambda$...。我们的JavaParser可能不会将它们识别为普通方法。对于增量覆盖率的统计我们通常更关注开发者显式编写的方法这些由编译器生成的Lambda方法可以暂时忽略或者通过更复杂的字节码分析来纳入统计这取决于你对精度要求的严格程度。从更高的角度看把增量覆盖率统计做成一个独立的工具只是第一步。更优雅的做法是将其深度集成到你的DevOps平台中。平台可以在代码合并请求Merge Request界面自动展示本次提交的增量覆盖率报告让评审者一目了然。平台还可以收集历史数据绘制团队或项目的增量覆盖率趋势图观察质量文化的建设效果。更进一步可以结合测试用例分析对未被覆盖的增量代码行给出智能提示甚至推荐相似的测试用例作为编写参考。我自己的体会是技术方案的落地工具只占三分另外七分在于流程和共识。推动团队接受“增量覆盖率”这个更合理的度量标准需要沟通和引导。我们可以先从新项目或重点核心模块试点用实际数据证明它的价值——它能更公平地评估开发者的当前工作能更早地发现测试缺口从而让大家自愿地去使用和维护它。当团队每个人都开始关注“我这次改动的代码测试够了没有”时整个产品的代码质量防线就前移了一大步这才是我们做技术方案追求的最终效果。

相关新闻

Windows XP 环境下兼容高版本Visual C++运行库的部署策略

Windows XP 环境下兼容高版本Visual C++运行库的部署策略

1. 为什么你的Windows XP装不上新软件?一个签名引发的“血案” 如果你还在维护一台老旧的Windows XP电脑,不管是用来运行某个特定的工业控制软件,还是怀旧玩老游戏,最近几年可能都遇到过同一个让人头疼的问题:从网上下…

2026/5/17 8:33:43 阅读更多 →
HY-MT1.5-1.8B翻译模型实战测评:从短句到长文档的翻译效果

HY-MT1.5-1.8B翻译模型实战测评:从短句到长文档的翻译效果

HY-MT1.5-1.8B翻译模型实战测评:从短句到长文档的翻译效果 1. 引言 最近在尝试各种翻译工具时,我遇到了一个挺有意思的问题:市面上很多翻译模型,处理短句时效果不错,但一遇到长文档,要么翻译得前言不搭后…

2026/7/4 20:08:37 阅读更多 →
从零理解Golang channel:图解有缓存/无缓存的底层差异与应用选择

从零理解Golang channel:图解有缓存/无缓存的底层差异与应用选择

从零理解Golang channel:图解有缓存/无缓存的底层差异与应用选择 在Go语言的并发世界里,channel(通道)无疑是那颗最耀眼的明珠。它不仅是goroutine(协程)间通信的桥梁,更是Go语言“通过通信共享…

2026/5/17 8:33:40 阅读更多 →

最新新闻

Python社交网络分析:从脏数据清洗到图构建的七道硬核工序

Python社交网络分析:从脏数据清洗到图构建的七道硬核工序

1. 这不是“画个关系图”就完事的——为什么用Python做社交网络分析,90%的人连数据清洗这关都过不去“Social Network Analysis in Python”这个标题听起来很学术、很技术,但如果你真把它当成一门“学几个networkx函数就能发论文”的速成课,那…

2026/7/5 7:02:00 阅读更多 →
5分钟快速上手:Parsec VDD虚拟显示器完全指南

5分钟快速上手:Parsec VDD虚拟显示器完全指南

5分钟快速上手:Parsec VDD虚拟显示器完全指南 【免费下载链接】parsec-vdd ✨ Perfect virtual display for game streaming 项目地址: https://gitcode.com/gh_mirrors/pa/parsec-vdd 你是否曾经因为缺少物理显示器而无法充分利用远程服务器?或者…

2026/7/5 6:59:59 阅读更多 →
基于WebGPU与WASM的本地AI图像修复与超分工具Inpaint-Web部署与实战

基于WebGPU与WASM的本地AI图像修复与超分工具Inpaint-Web部署与实战

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度 在实际图像处理工作中,我们经常遇到两类棘手问题:一是从网络获取的图片分辨率过低,放大后细节模糊…

2026/7/5 6:57:59 阅读更多 →
Python图像隐写术:用位操作实现LSB信息隐藏

Python图像隐写术:用位操作实现LSB信息隐藏

1. 项目概述:用Python的“像素画笔”藏匿秘密如果你对编程感兴趣,尤其是用Python处理过图片,那你一定知道PIL或Pillow库,它们能让你轻松地读取像素、修改颜色。但你是否想过,一张看似普通的风景照、一张可爱的表情包&a…

2026/7/5 6:55:58 阅读更多 →
3个痛点,1个方案:Wand-Enhancer如何彻底改变你的游戏修改体验

3个痛点,1个方案:Wand-Enhancer如何彻底改变你的游戏修改体验

3个痛点,1个方案:Wand-Enhancer如何彻底改变你的游戏修改体验 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/gh_mirrors/we/Wand-Enhancer 你是否曾经为游戏修…

2026/7/5 6:53:58 阅读更多 →
WarcraftHelper:魔兽争霸III终极性能优化与兼容性解决方案

WarcraftHelper:魔兽争霸III终极性能优化与兼容性解决方案

WarcraftHelper:魔兽争霸III终极性能优化与兼容性解决方案 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper WarcraftHelper是一款专为《魔兽…

2026/7/5 6:49:57 阅读更多 →

日新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

月新闻