当前位置: 首页 > news >正文

【JVM】JVM异常不打印堆栈信息 [ -XX:-OmitStackTraceInFastThrow ]

文章目录

  • 一、背景
  • 二、原因
  • 三、 代码验证

一、背景

生产环境日志突然膨胀到100G+, 为了定位问题,所以截取了部分报错日志,
问题是 堆栈信息呢? 哪里报的NPE在哪???

信息如下:

[ERROR] 2020-12-09 09:41:50.053  - [taskAppId=TASK-1919-33805-97659]:[156] - wait task quit failed, instance id:33805, task id:97659
[ERROR] 2020-12-09 09:41:50.053  - [taskAppId=TASK-1919-34759-100696]:[154] - exception
java.lang.NullPointerException: null
[ERROR] 2020-12-09 09:41:50.053  - [taskAppId=TASK-1919-34759-100696]:[156] - wait task quit failed, instance id:34759, task id:100696
[ERROR] 2020-12-09 09:41:50.059  - [taskAppId=TASK-1917-7841-18206]:[154] - exception
java.lang.NullPointerException: null
[ERROR] 2020-12-09 09:41:50.059  - [taskAppId=TASK-1917-7841-18206]:[156] - wait task quit failed, instance id:7841, task id:18206
[ERROR] 2020-12-09 09:41:50.059  - [taskAppId=TASK-1919-33805-97659]:[154] - exception
java.lang.NullPointerException: null

二、原因

JVM中有个参数:OmitStackTraceInFastThrow,省略异常栈信息从而快速抛出异常.

JVM对一些特定的异常类型做了Fast Throw优化,如果检测到在代码里某个位置连续多次抛出同一类型异常的话,C2会决定用FastThrow方式来抛出异常,而异常Trace即详细的异常栈信息会被清空。这种异常抛出速度非常快,因为不需要在堆里分配内存,也不需要构造完整的异常栈信息。

如果禁用则使用下面的命令:

 -XX:-OmitStackTraceInFastThrow

JVM源码:

//------------------------------builtin_throw----------------------------------
void GraphKit::builtin_throw(Deoptimization::DeoptReason reason, Node* arg) {bool must_throw = true;if (env()->jvmti_can_post_on_exceptions()) {// check if we must post exception events, take uncommon trap if souncommon_trap_if_should_post_on_exceptions(reason, must_throw);// here if should_post_on_exceptions is false// continue on with the normal codegen}// // If this particular condition has not yet happened at this// bytecode, then use the uncommon trap mechanism, and allow for// a future recompilation if several traps occur here.// If the throw is hot, try to use a more complicated inline mechanism// which keeps execution inside the compiled code.bool treat_throw_as_hot = false;ciMethodData* md = method()->method_data();if (ProfileTraps) {if (too_many_traps(reason)) {treat_throw_as_hot = true;}// (If there is no MDO at all, assume it is early in// execution, and that any deopts are part of the// startup transient, and don't need to be remembered.)// Also, if there is a local exception handler, treat all throws// as hot if there has been at least one in this method.if (C->trap_count(reason) != 0&& method()->method_data()->trap_count(reason) != 0&& has_ex_handler()) {treat_throw_as_hot = true;}}// If this throw happens frequently, an uncommon trap might cause// a performance pothole.  If there is a local exception handler,// and if this particular bytecode appears to be deoptimizing often,// let us handle the throw inline, with a preconstructed instance.// Note:   If the deopt count has blown up, the uncommon trap// runtime is going to flush this nmethod, not matter what.if (treat_throw_as_hot&& (!StackTraceInThrowable || OmitStackTraceInFastThrow)) {// If the throw is local, we use a pre-existing instance and// punt on the backtrace.  This would lead to a missing backtrace// (a repeat of 4292742) if the backtrace object is ever asked// for its backtrace.// Fixing this remaining case of 4292742 requires some flavor of// escape analysis.  Leave that for the future.ciInstance* ex_obj = NULL;switch (reason) {case Deoptimization::Reason_null_check:ex_obj = env()->NullPointerException_instance();break;case Deoptimization::Reason_div0_check:ex_obj = env()->ArithmeticException_instance();break;case Deoptimization::Reason_range_check:ex_obj = env()->ArrayIndexOutOfBoundsException_instance();break;case Deoptimization::Reason_class_check:if (java_bc() == Bytecodes::_aastore) {ex_obj = env()->ArrayStoreException_instance();} else {ex_obj = env()->ClassCastException_instance();}break;}if (failing()) { stop(); return; }  // exception allocation might failif (ex_obj != NULL) {// Cheat with a preallocated exception object.if (C->log() != NULL)C->log()->elem("hot_throw preallocated='1' reason='%s'",Deoptimization::trap_reason_name(reason));const TypeInstPtr* ex_con  = TypeInstPtr::make(ex_obj);Node*              ex_node = _gvn.transform( ConNode::make(C, ex_con) );// Clear the detail message of the preallocated exception object.// Weblogic sometimes mutates the detail message of exceptions// using reflection.int offset = java_lang_Throwable::get_detailMessage_offset();const TypePtr* adr_typ = ex_con->add_offset(offset);Node *adr = basic_plus_adr(ex_node, ex_node, offset);const TypeOopPtr* val_type = TypeOopPtr::make_from_klass(env()->String_klass());// Conservatively release stores of object references.Node *store = store_oop_to_object(control(), ex_node, adr, adr_typ, null(), val_type, T_OBJECT, MemNode::release);add_exception_state(make_exception_state(ex_node));return;}}// %%% Maybe add entry to OptoRuntime which directly throws the exc.?// It won't be much cheaper than bailing to the interp., since we'll// have to pass up all the debug-info, and the runtime will have to// create the stack trace.// Usual case:  Bail to interpreter.// Reserve the right to recompile if we haven't seen anything yet.assert(!Deoptimization::reason_is_speculate(reason), "unsupported");Deoptimization::DeoptAction action = Deoptimization::Action_maybe_recompile;if (treat_throw_as_hot&& (method()->method_data()->trap_recompiled_at(bci(), NULL)|| C->too_many_traps(reason))) {// We cannot afford to take more traps here.  Suffer in the interpreter.if (C->log() != NULL)C->log()->elem("hot_throw preallocated='0' reason='%s' mcount='%d'",Deoptimization::trap_reason_name(reason),C->trap_count(reason));action = Deoptimization::Action_none;}// "must_throw" prunes the JVM state to include only the stack, if there// are no local exception handlers.  This should cut down on register// allocation time and code size, by drastically reducing the number// of in-edges on the call to the uncommon trap.uncommon_trap(reason, action, (ciKlass*)NULL, (char*)NULL, must_throw);
}

三、 代码验证

测试代码:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class OmitStackTraceInFastThrowTest {public static void main(String[] args) throws InterruptedException {NPEThread npeThread = new NPEThread();ExecutorService executorService = Executors.newFixedThreadPool(20);for (int i=0; i<Integer.MAX_VALUE; i++) {executorService.execute(npeThread);// 稍微sleep一下, 是为了不要让异常抛出太快, 导致控制台输出太快, 把有异常栈信息冲掉, 只留下fast throw方式抛出的异常Thread.sleep(2);}}
}
class NPEThread extends Thread {private static int count = 0;@Overridepublic void run() {try{System.out.println(this.getClass().getSimpleName()+"--"+(++count));String str = null;// 制造空指针NPESystem.out.println(str.length());}catch (Throwable e){e.printStackTrace();}}
}

运行时间长之后,不再打印堆栈信息,日志如下:

NPEThread--467
NPEThread--468
NPEThread--469
NPEThread--470
NPEThread--471
NPEThread--472
NPEThread--473
NPEThread--474
NPEThread--475
NPEThread--476
NPEThread--477
java.lang.NullPointerExceptionat org.apache.dolphinscheduler.api.utils.NPEThread.run(OmitStackTraceInFastThrowTest.java:28)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)
java.lang.NullPointerExceptionat org.apache.dolphinscheduler.api.utils.NPEThread.run(OmitStackTraceInFastThrowTest.java:28)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)
java.lang.NullPointerExceptionat org.apache.dolphinscheduler.api.utils.NPEThread.run(OmitStackTraceInFastThrowTest.java:28)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)
java.lang.NullPointerExceptionat org.apache.dolphinscheduler.api.utils.NPEThread.run(OmitStackTraceInFastThrowTest.java:28)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)
java.lang.NullPointerExceptionat org.apache.dolphinscheduler.api.utils.NPEThread.run(OmitStackTraceInFastThrowTest.java:28)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)
java.lang.NullPointerExceptionat org.apache.dolphinscheduler.api.utils.NPEThread.run(OmitStackTraceInFastThrowTest.java:28)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)
java.lang.NullPointerExceptionat org.apache.dolphinscheduler.api.utils.NPEThread.run(OmitStackTraceInFastThrowTest.java:28)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)
java.lang.NullPointerExceptionat org.apache.dolphinscheduler.api.utils.NPEThread.run(OmitStackTraceInFastThrowTest.java:28)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)
java.lang.NullPointerExceptionat org.apache.dolphinscheduler.api.utils.NPEThread.run(OmitStackTraceInFastThrowTest.java:28)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)
java.lang.NullPointerExceptionat org.apache.dolphinscheduler.api.utils.NPEThread.run(OmitStackTraceInFastThrowTest.java:28)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)
java.lang.NullPointerExceptionat org.apache.dolphinscheduler.api.utils.NPEThread.run(OmitStackTraceInFastThrowTest.java:28)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)
java.lang.NullPointerExceptionat org.apache.dolphinscheduler.api.utils.NPEThread.run(OmitStackTraceInFastThrowTest.java:28)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)
java.lang.NullPointerExceptionat org.apache.dolphinscheduler.api.utils.NPEThread.run(OmitStackTraceInFastThrowTest.java:28)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at java.lang.Thread.run(Thread.java:748)

运行时间长之后,不再打印堆栈信息,日志如下:

NPEThread--9030
NPEThread--9031
NPEThread--9032
NPEThread--9033
NPEThread--9034
NPEThread--9035
NPEThread--9036
NPEThread--9037
NPEThread--9038
NPEThread--9039
NPEThread--9040
NPEThread--9041
java.lang.NullPointerException
java.lang.NullPointerException
java.lang.NullPointerException
java.lang.NullPointerException
java.lang.NullPointerException
java.lang.NullPointerException
java.lang.NullPointerException
java.lang.NullPointerException
java.lang.NullPointerException
java.lang.NullPointerException
java.lang.NullPointerException
java.lang.NullPointerException
java.lang.NullPointerException

相关文章:

【JVM】JVM异常不打印堆栈信息 [ -XX:-OmitStackTraceInFastThrow ]

文章目录 一、背景二、原因三、 代码验证 一、背景 生产环境日志突然膨胀到100G, 为了定位问题,所以截取了部分报错日志, 问题是 堆栈信息呢? 哪里报的NPE在哪??? 信息如下: [ERROR] 2020-12-09 09:41:50.053 - [taskAppIdTASK-1919-33805-97659]:[156] - wait task qu…...

第十一章 目标检测中的NMS

精度提升 众所周知&#xff0c;非极大值抑制NMS是目标检测常用的后处理算法&#xff0c;用于剔除冗余检测框&#xff0c;本文将对可以提升精度的各种NMS方法及其变体进行阶段性总结。 总体概要&#xff1a; 对NMS进行分类&#xff0c;大致可分为以下六种&#xff0c;这里是依…...

vue项目中使用vant轮播图组件(桌面端)

一. 内容简介 vue使用vant轮播图组件(桌面端) 二. 软件环境 2.1 Visual Studio Code 1.75.0 2.2 chrome浏览器 2.3 node v18.14.0 三.主要流程 3.1 安装环境 3.2 添加代码 3.3 结果展示 四.具体步骤 4.1 安装环境 先安装包 # Vue 3 项目&#xff0c;安装最新版 Va…...

如何做好性能压测 —— 压测环境设计和搭建!

简介&#xff1a;一般来说&#xff0c;保证执行性能压测的环境和生产环境高度一致是执行一次有效性能压测的首要原则。有时候&#xff0c;即便是压测环境和生产环境有很细微的差别&#xff0c;都有可能导致整个压测活动评测出来的结果不准确。 1. 性能环境要考虑的要素 1.1 系…...

手机弱网测试工具:Charles

我们在测试app的时候&#xff0c;需要测试弱网情况下的一些场景&#xff0c;那么使用Charles如何设置弱网呢&#xff0c;请看以下步骤&#xff1a; 前提条件&#xff1a; 手机和电脑要在同一局域网内 Charles连接手机抓包 一、打开Charles&#xff0c;点击代理&#xff0c;…...

Axios七大特性

Axios是一个基于Promise的HTTP客户端&#xff0c;用于浏览器和Node.js环境中发起HTTP请求。它有许多强大的特性&#xff0c;下面将介绍Axios的七大特性。 1. 支持浏览器和Node.js Axios既可以在浏览器中使用&#xff0c;也可以在Node.js环境中使用&#xff0c;提供了统一的AP…...

【机器学习基础】K-Means聚类算法

&#x1f680;个人主页&#xff1a;为梦而生~ 关注我一起学习吧&#xff01; &#x1f4a1;专栏&#xff1a;机器学习 欢迎订阅&#xff01;相对完整的机器学习基础教学&#xff01; ⭐特别提醒&#xff1a;针对机器学习&#xff0c;特别开始专栏&#xff1a;机器学习python实战…...

Vite - 配置 - 自动修改 index.html 中的title

需求描述 在Vue3项目的开发过程中&#xff0c;我们为了能区分正式环境和测试环境&#xff0c; 通常会进行环境配置文件的区分&#xff0c; 例如&#xff0c;开发环境一个配置文件、生产环境一个配置文件。因此&#xff0c;我们就希望 在项目的index.html 的 title 标签中&…...

基于安卓android微信小程序美容理发店预约系统app

项目介绍 为美容院设计一个系统以减少员工的工作量就成为了想法的初始状态。紧接着对美容院进行进一步的调查发现我的想法已然落后。基本上每个美容院都以有了自己的信息系统&#xff0c;并且做的已经较完善了。 在这时我突然想到&#xff0c;现在关注美容养生的人越来越多&am…...

*** stack smashing detected ***: terminated

有一个函数返回值是bool类型&#xff0c;但忘了return了&#xff0c;编译可以通过&#xff0c;但是运行的时候报这个错误。...

鸿蒙系统扫盲(二):再谈鸿蒙是不是安卓套壳?

最近小米发布了澎湃OS&#xff0c;vivo发布了蓝OS&#xff0c;好像自从华为回归后&#xff0c;大伙都开始写自己的OS了&#xff0c;小米官方承认是套壳安卓&#xff0c;然后被大家喷了&#xff0c;于是鸿蒙是不是安卓套壳的话题又回到了大众的视野&#xff0c;今天在讨论下这个…...

PG数据中DBeaver上传csv文件作为数据表

DBeaver 是一个开源的数据库工具&#xff0c;还是蛮好用的&#xff0c;有时候需要我们上传数据做表&#xff0c;数据为CSV格式的&#xff0c;DBeaver本身自带有功能实现的。 可打开连着的数据库&#xff0c;找到模式&#xff0c;点到下面的表里&#xff0c;选择一个表直接导入…...

第十七篇-Awesome ChatGPT Prompts-备份-百度翻译

Awesome ChatGPT Prompts——一个致力于提供挖掘ChatGPT能力的Prompt收集网站 https://prompts.chat/ 第十六篇-Awesome ChatGPT Prompts-备份【英文】 第十七篇-Awesome ChatGPT Prompts-备份-百度翻译 【中文】 高效提示词请参考,各种场景&#xff0c;2023-11-16内容如下(百…...

[Android] Amazon 的 android 音视频开发文档

https://developer.amazon.com/zh/docs/fire-tv/audio-video-synchronization.html#22-getplaybackheadposition-api-level-3https://developer.amazon.com/zh/docs/fire-tv/audio-video-synchronization.html#22-getplaybackheadposition-api-level-3...

UE4基础篇十六:自定义 EQS 生成器

UE4 中的 EQS 带有一组很好的查询项生成器,但在某些情况下,您可能更喜欢根据需要创建生成器。我决定编写自己的生成器,因为我必须编写一个查询来找到查询器周围的最佳位置,但又不能太靠近它。我知道我可以添加一个距离测试来随着距离增加分数,但我什至不想考虑距查询器一定…...

轿车5+1汽车变速器变速箱同步器操纵机构机械结构设计CAD汽车工程

wx供重浩&#xff1a;创享日记 对话框发送&#xff1a;汽车变速器 获取完整论文报告说明书工程源文件 变速器工程图 操纵机构3D图 一、机械式变速器的概述及其方案的确定 1.1 变速器的功用和要求 变速器的功用是根据汽车在不同的行驶条件下提出的要求&#xff0c;改变发动机…...

STM32F4移植SPI注意事项

一、注意事项 可以看我之前移植的文章&#xff0c;那些就不提了&#xff0c;记得要复用&#xff0c;把IO复用成对应的功能io&#xff0c;然后还要注意时钟&#xff0c;看你需要的功能&#xff0c;去调对应的时钟&#xff0c;把时钟调匹配了&#xff0c;基本上不会有问题。 比如…...

CV计算机视觉每日开源代码Paper with code速览-2023.11.16

点击CV计算机视觉&#xff0c;关注更多CV干货 论文已打包&#xff0c;点击进入—>下载界面 点击加入—>CV计算机视觉交流群 1.【基础网络架构】ConvNet vs Transformer, Supervised vs CLIP: Beyond ImageNet Accuracy 论文地址&#xff1a;https://arxiv.org//pdf/23…...

Git 简介及使用(1)

目录 一、在 Linux 环境中安装 Git 1. 先检查当前服务器中是否有 Git&#xff08;如果有显示如下图&#xff09; 2. 安装Git 3. 然后重复第一步&#xff1a;查看 Git 的版本信息即可 二、Git 的初始化及配置 1. 创建目录 2. 对仓库进行初始化 3. 新增两个配置项&#xff08…...

HTTPS流量抓包分析中出现无法加载key

HTTPS流量抓包分析(TLSv1.2)&#xff0c;这篇文章分析的比较透彻&#xff0c;就不班门弄斧了 https://zhuanlan.zhihu.com/p/635420027 写个小问题&#xff1a;RSA密钥对话框加载rsa key文件的时候注意不要在中文目录下&#xff0c;否则会提示&#xff1a;“Enter the passwor…...

在Android 9上用vsomeip 3.3.8实现跨进程通信:一份保姆级编译与配置指南

在Android 9上实现跨进程通信&#xff1a;vsomeip 3.3.8编译与配置实战 在车载以太网和智能座舱系统开发中&#xff0c;跨进程通信&#xff08;IPC&#xff09;是基础且关键的技术环节。对于Android平台开发者而言&#xff0c;如何在NDK环境下高效实现Linux进程间通信&#xff…...

设计系统文本化:用YAML/JSON统一管理设计令牌,实现多端一致与自动化

1. 项目概述&#xff1a;当设计系统遇上纯文本 最近在跟一个跨职能团队协作时&#xff0c;我们遇到了一个典型的老大难问题&#xff1a;设计师在Figma里更新了一个按钮的主色调&#xff0c;前端工程师在代码库里改了对应的CSS变量&#xff0c;但负责撰写产品文档和营销材料的同…...

实在Agent实测:解决采购合同审核流程冗长与原材料交付周期拉长的架构之道

大家好&#xff0c;我是企业架构师老王。站在2026年5月这个时间节点回看&#xff0c;全球供应链的复杂程度已远超三年前的预判。近期我在为几家制造型企业做数字化诊断时发现&#xff0c;一个幽灵般的困境正在吞噬企业的利润&#xff1a;采购合同审核流程冗长&#xff0c;直接导…...

深度学习提取结构光条中心线项目的对比实验与消融实验统计分析方法研究

深度学习提取结构光条中心线项目的对比实验与消融实验统计分析方法研究 1 引言 线结构光三维测量技术凭借其非接触、高精度、快速测量等优势,在工业测量、三维重建、智能制造等领域得到了广泛应用。在结构光视觉测量系统中,光条中心线的提取精度直接决定了三维重建和尺寸测…...

斯坦福CS229机器学习中文教程:从零到一的实战学习指南

斯坦福CS229机器学习中文教程&#xff1a;从零到一的实战学习指南 【免费下载链接】Stanford-CS-229 A Chinese Translation of Stanford CS229 notes 斯坦福机器学习CS229课程讲义的中文翻译 项目地址: https://gitcode.com/gh_mirrors/st/Stanford-CS-229 你是否曾因英…...

Box64终极指南:5分钟学会在ARM设备上运行x86_64程序

Box64终极指南&#xff1a;5分钟学会在ARM设备上运行x86_64程序 【免费下载链接】box64 Box64 - Linux Userspace x86_64 Emulator with a twist, targeted at ARM64, RV64 and LoongArch Linux devices 项目地址: https://gitcode.com/gh_mirrors/bo/box64 你是否曾经梦…...

基于MCP协议构建智能Telegram助手:连接AI与外部服务的实践指南

1. 项目概述&#xff1a;一个连接AI与Telegram的智能桥梁如果你正在寻找一种方法&#xff0c;让你在Telegram上使用的AI助手&#xff08;比如ChatGPT、Claude等&#xff09;能够“活”起来&#xff0c;不仅能聊天&#xff0c;还能帮你查天气、看新闻、管理待办事项&#xff0c;…...

企业级应用awesome-stock-resources:商业项目合规使用终极指南

企业级应用awesome-stock-resources&#xff1a;商业项目合规使用终极指南 【免费下载链接】awesome-stock-resources :city_sunrise: A collection of links for free stock photography, video and Illustration websites 项目地址: https://gitcode.com/gh_mirrors/aw/awe…...

VNote批量操作终极指南:如何一次处理百篇笔记提升效率 [特殊字符]

VNote批量操作终极指南&#xff1a;如何一次处理百篇笔记提升效率 &#x1f680; 【免费下载链接】vnote A pleasant note-taking platform in native C. 项目地址: https://gitcode.com/gh_mirrors/vn/vnote VNote批量操作是每个高效笔记用户必须掌握的技能&#xff01…...

云原生测试工具链选型指南:面向测试从业者的专业架构与实践路径

随着云原生技术栈的深度渗透&#xff0c;软件测试领域正经历一场从理念到工具链的深刻变革。面对Kubernetes、微服务、Service Mesh等新型架构带来的动态性、分布性与高频变更挑战&#xff0c;传统的测试工具与方法论已显乏力。对于测试从业者而言&#xff0c;构建或选型一套适…...