《leetcode-runner》【图解】如何手搓一个debug调试器——调试程序【JDI开发】【万字详解】
前文:
《leetcode-runner》如何手搓一个debug调试器——引言
《leetcode-runner》如何手搓一个debug调试器——架构
《leetcode-runner》如何手搓一个debug调试器——指令系统
本文主要聚焦于如何编写调试程序
背景
在leetcode算法背景下,用户只编写了一个Solution文件。在此基础上,项目该做出哪些额外操作,才能够启动并运行程序呢?
显然,我们需要程序入口。其次,还需要自己实现一套调试程序,控制调试进度
程序入口
方案选择
在Java中,程序入口是main方法。想要启动Solution类,我们存在两种解决方案
-
复制用户编写的Solution的所有内容,并动态添加main函数入口,将新得到的内容写入一个全新的文件。最后启动这个全新文件
-
原封不动的拷贝用户编写的Solution的所有内容,同时创建一个全新的Main类,在Main类中调用Solution的方法
考虑到规整性,leetcode-runner选择了第二种解决方案
如何将测试案例转换为适配Solution方法入参的代码
模板引入
让我们通过一个简单的case引入解决方案
solution模板
class Solution {public int lengthOfLongestSubstring(String s) {}
}
测试案例
“abcabcbb”
现在的需求是,根据solution模板
,测试案例
,创建一个调用Solution的Main函数
假设我们没有经过程序自动计算生成,让我们手写,Main类长啥样呢?
import java.util.*;public class Main {public static void main(String[] args) {Solution solution = new Solution(); // 创建实例String a = "abcabcbb"; // 测试案例转换为Java代码solution.lengthOfLongestSubstring(a); // 调用核心方法}
}
让我们分析一下这段代码哪些是固定的,哪些是需要动态生成的
首先整个Main的结构是死的,创建实例是死的,活的部分是测试案例转换代码
和方法调用
进一步改写,得到如下模板
import java.util.*;public class Main {public static void main(String[] args) {Solution solution = new Solution();{{callCode}}}
}
{{callCode}},标志着调用代码生成的位置,需要程序动态生成创建
测试案例转换
现在有一个字符串——“abcabcbb”,我们需要将他转换为Java代码。但现在存在一个问题,我们需要将"abcabcbb"赋值给变量,那么变量名叫啥?,变量类型是啥?
现在的测试案例非常简单,变量名给个a,类型一眼字符串
那我现在上上强度
请问,[1,2,3]应该转换成什么类型的变量呢?
a. 数组
b. TreeNode
c. ListNode
现在各位读者猜猜,选啥
3、2、1
答案是——都有可能!!!
以leetcode-1367为例
这样的数组类型既可以表示ListNode,也可以表示TreeNode。当然,int[]数组自然也是可以的
从上述案例可以发现,测试案例转变得到的变量类型并不是恒定的,它取决于上下文——Solution的方法入参
如果入参类型是ListNode,那么[1,2,3]就是ListNode。如果入参类型是TreeNode,那么[1,2,3]就是TreeNode。如果入参是int[],那么[1,2,3]就是int[]
因此,我们要明确将测试案例转换成何种类型的变量,就必须要知道入参类型是什么,而这就引出了核心代码分析功能
核心代码分析
所谓核心代码分析,就是对于leetcode提供的片段代码,识别出关键信息
在leetcode-runner项目中,核心信息有方法名
,所有的入参类型
,并通过AnalysisResult
封装分析结果
CodeAnalyzer
是代码分析器,用于分析核心代码片段,返回分析的结果
至于如何分析核心代码,需要利用正则这项技术
这里我将提供leetcode-runner部分源码
/*** Java代码分析器** @author feigebuge* @email 2508020102@qq.com*/
public class JavaCodeAnalyzer extends AbstractCodeAnalyzer{public JavaCodeAnalyzer(Project project) {super(project);}/*(\w+) 捕获组, 匹配字母数字下划线*/private static final String methodPattern = "public\\s+.*\\s+(\\w+)\\s*\\(([^)]*)\\)";private static final Pattern pattern = Pattern.compile(methodPattern);public AnalysisResult analyze(String code) {LogUtils.simpleDebug(code);// 正则表达式匹配方法签名Matcher matcher = pattern.matcher(code);if (matcher.find()) {String methodName = matcher.group(1); // 获取方法名String parameters = matcher.group(2); // 获取参数列表// 解析参数类型List<String> parameterTypes = new ArrayList<>();String[] parametersArray = parameters.split("\\s*,\\s*");for (String param : parametersArray) {// 提取类型部分String[] parts = param.split("\\s+");if (parts.length > 1) {parameterTypes.add(parts[0].trim()); // 只获取类型}}return new AnalysisResult(methodName, parameterTypes.toArray(new String[0]));}throw new DebugError("代码片段分析错误! 无法匹配任何有效信息\n code = " + code);}
}
在代码中,利用到正则的匹配组的功能,通过match.group方法,匹配得到不同的类型
举个例子
public String dfs(int a, int b)
这行代码将会被regex的group匹配到两组内容
group 1:dfs
group 2:int a, int b
group 1匹配得到方法名——dfs
group 2匹配得到括号内部的所有内容,接下来只需要按照逗号进行分割,取第一个符号就可以得到入参类型
通过分析结果,将测试案例转换为Java代码
先上UML,再解释
在leetcode-runner中,负责将测试案例转换为对应代码的类是TestcaseConvertor
,但我目前写的毕竟是Java 调试器,自然而然的,负责这块的类就是JavaTestcaseConvertor,后文将称呼他为JTC
在JTC处理测试案例时,会将测试案例和方法入参类型进行匹配,然后统一交给ConvertorFactory
,根据不同的入参类型生成不同的VariableConvertor
VariableConvertor
负责将测试案例转换成不同类型的代码。比如IntArrayConvertor
,负责将输入转换为int[]
变量;IntConvertor,负责将输入转为为int
变量
流程汇总
现在,我们将上文介绍的类进行汇总,得到整体流程
在项目中,已经存在Main.template,具体内容如下
import java.util.*;public class Main {public static void main(String[] args) {Solution solution = new Solution();{{callCode}}}
}
现在,我们需要做的是将测试案例转换成代码 + 创建实例调用代码,将代码填入{{callCode}}
内部
整套流程如下
对应到leetcode-runner代码,就长这样
tip:
- autoAnalyze()方法是对analyze(String)做出的封装,他会自动获取核心代码,并传递给analyze方法
- autoConvert()方法是对convert(String testcase)方法做出的封装,autoConvert()会自动获取代码片段,并传递给convert(String testcase)方法
JDI层次
Mirror
JDI(Java Debug Interface),是一套为了debug调试获取目标JVM运行状态的接口
通过JDI定义的接口,我们可以驱动目标JVM调试目标代码,同时获取JVM执行的状态信息,以及目标代码的数据信息
在JDI开发中,最最核心的是VirtualMachie
类,他封装了正在执行debug的JVM的所有信息。为了和执行调试程序的JVM做出区分,执行debug的JVM我们称为TargetVM
这里,需要进行一个区分,在JDI开发中,VirtualMachine
是TargetVM的镜像——Mirror
在JDI开发过程中,所有的操作都会如实的作用到TargetVM
,就像镜子那样,你一动,我就动。因此,在JDI的包下,所有类都是Mirror
的子类,换句话说,Mirror是顶级父类
VirtualMachine
连接
总共有两种连接方式
- 连接正在运行的程序,并返回目标VM的镜像
- 启动一个应用程序并连接返回目标VM的镜像
这两者的区别是:方法1可以是远程连接,方法2必须是本地连接
对于方法一,连接需要地址,端口信息,因此方法一在debug调试时,可以远程连接。JDI在电脑A,目标VM在电脑B
对于方法二,JDI提供的接口同时负责启动,连接。因为启动的功能交由JDI,因此只能是本地连接
leetcode-runner提供了两种连接方式,笔者将提供部分连接代码
方法一
private void debugRemotely() {startVMService();connectVM();
}private void startVMService() {this.port = DebugUtils.findAvailablePort();LogUtils.simpleDebug("get available port : " + this.port);String cdCmd = "cd " + env.getFilePath();String startCmd = String.format("%s -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=%d -cp %s %s",env.getJava(), port, env.getFilePath(), "Main");String combinedCmd = "cmd /c " + cdCmd + " & " + startCmd;LogUtils.simpleDebug(combinedCmd);try {Process exec = Runtime.getRuntime().exec(combinedCmd);getRunInfo(exec);} catch(InterruptedException ignored) {} catch (Exception e) {throw new DebugError(e.toString(), e);}
}/*** 连接VM, 开始debug*/
private void connectVM() {// 创建连接VirtualMachineManager vmm = Bootstrap.virtualMachineManager();AttachingConnector connector = getConnector(vmm);// 配置调试连接信息Map<String, Connector.Argument> arguments = connector.defaultArguments();arguments.get("port").setValue(String.valueOf(port));// 连接到目标 JVMVirtualMachine vm = null;// 3次连接尝试int tryCount = 1;do {try {DebugUtils.simpleDebug("第 " + tryCount + " 次连接, 尝试中...", project);vm = connector.attach(arguments);DebugUtils.simpleDebug("连接成功", project);break;} catch (IOException | IllegalConnectorArgumentsException e) {DebugUtils.simpleDebug("连接失败: " + e, project);try {Thread.sleep(1000);} catch (InterruptedException ignored) {}}tryCount++;} while (tryCount <= 3);if (vm == null) {LogUtils.warn("vm 连接失败");throw new DebugError("vm 连接失败");}startProcessEvent(vm);
}
方法二
/*** 本地断点启动*/
private void debugLocally() {// 获取 LaunchingConnectorLaunchingConnector connector = Bootstrap.virtualMachineManager().defaultConnector();// 配置启动参数Map<String, Connector.Argument> arguments = connector.defaultArguments();arguments.get("main").setValue("Main"); // 替换为你的目标类全路径arguments.get("options").setValue("-classpath " + env.getFilePath() + " -Dencoding=utf-8"); // 指定类路径// fix: 编译jdk和运行jdk不一致问题arguments.get("home").setValue(env.getJAVA_HOME());arguments.get("vmexec").setValue("java.exe");// 启动目标 JVMVirtualMachine vm;try {vm = connector.launch(arguments);} catch (IOException | IllegalConnectorArgumentsException | VMStartException e) {throw new DebugError("vm启动失败!", e);}// 捕获目标虚拟机的输出captureStream(vm.process().getInputStream(), OutputHelper.STD_OUT);captureStream(vm.process().getErrorStream(), OutputHelper.STD_ERROR);// 获取当前类的调试信息startProcessEvent(vm);
}
EventQueue / EventSet
在介绍本小节内容前,请允许我提个问题
如果TargetVM处理产生各种结果,该如何通知VirtualMachine
呢?
或者换个问法,VirtualMachine
如何知道TargetVM干了啥,产生了生么结果呢?
这就得引出EventQueue
EventQueue
,管理即将到来的TargetVM在debug过程中产生的事件。事件总是会被封装到EventSet
当中。EventSet
总是由debug程序创建生成,并可以通过EventQueue
读取
VirtualMachine
如果想要知道TargetVM产生了哪些事件,可以通过VirtualMachine.eventQueue()
获得EventQueue
,EventQueue.remove()
得到EventSet
。最后通过遍历EventSet
可以获得TargetVM即将处理的各种事件
笔者将简化leetcode-runner代码,提供一个基本的处理demo
EventQueue eventQueue = virtualMachine.eventQueue();
while (true) {EventSet set = eventQueue.remove();Iterator<Event> it = set.iterator();boolean resumeStoppedApp = false;while (it.hasNext()) {// 只要有一个事件不resume, 就必须resumeresumeStoppedApp |= !handleEvent(it.next());}if (resumeStoppedApp) {set.resume();}
}
Event
发生在TargetVM,并且调试器非常感兴趣的事件。Event是所有事件的顶级父类,当事件发生,事件实例将会写入EventQueue,等待调试程序处理
Event有很多类型
- BreakpointEvent
- ClassPrepareEvent
- StepEvent
- …
Event中封装了非常多的重要信息
如果某个Event继承了LocatableEvent,那他就拥有了TargetVM执行的位置信息和线程引用
这两个对象相当关键,其具体信息将在下一小节介绍
ThreadReference / Location
ThreadReference:目标JVM的线程引用,包含TargetVM当前执行线程的所有信息。我们都知道,代码会在某个线程中执行,在调用方法时,会执行入栈操作。栈中包含局部变量的引用,通过引用可以获取局部变量的实际值
Location:表示目标JVM当暂停线程当前执行到的位置信息。
包括
- sourceName:当前执行位置的源码名称
- sourcePath:源码路径
- lineNumber:执行代码行号
- …
Value,Type
Value是TargetVM中,值的镜像。在JDI开发体系中,Value的整个继承图谱巨tm复杂且麻烦
下图是JDI的文档,大体上分,Java所有value镜像可以分为PrimitiveValue
,ObjectReference
。前者是基本类型的镜像,后者是对象类型的镜像
Type,类型的镜像
Value
,Type
之间的关系,有点像实例,和Class之间的关系
对于对象类型的Value,如果想要获取对象的某个字段的值,需要通过ReferenceType获取Field信息,然后通过ObjectReference.getValue(Field)
的方法获得Value
这里贴出一段处理ArrayDeque内部elements属性的代码
private String handleArrayDeque(ObjectReference objRef, int depth) {ReferenceType referenceType = objRef.referenceType();Value elements = objRef.getValue(referenceType.fieldByName("elements"));...}
EventRequestManager
事件请求管理器,通过管理器,可以向TargetVM发送各种事件请求
eg
- createStepRequest 创建单步运行请求
- createBreakpointRequest 创建断点请求
- createClassPrepareRequest 类准备请求
- …
md,写不动了,今天就这样吧,明天继续补充…
架构
相关文章:
《leetcode-runner》【图解】如何手搓一个debug调试器——调试程序【JDI开发】【万字详解】
前文: 《leetcode-runner》如何手搓一个debug调试器——引言 《leetcode-runner》如何手搓一个debug调试器——架构 《leetcode-runner》如何手搓一个debug调试器——指令系统 本文主要聚焦于如何编写调试程序 背景 在leetcode算法背景下,用户只编写了…...
【高阶数据结构】线段树加乘(维护序列)详细解释乘与加懒标记
文章目录 1.题目[AHOI2009] 维护序列 2.懒标记处理先加后乘的形式1. 先加后乘的操作 先乘后加的形式2. 先乘后加的操作**乘法操作****加法操作** 懒标记的下传 3.代码 1.题目 题目来源:https://www.luogu.com.cn/problem/P2023 [AHOI2009] 维护序列 题目背景 老师交给小可可…...
ElasticSearch常见知识点
1、什么是ElasticSearch? Elasticsearch 是基于 Lucene 的 Restful 的分布式实时全文搜索引擎,每个字段都被索引并可被搜索,可以快速存储、搜索、分析海量的数据。 2、什么是倒排索引? 正常的索引是比如二叉树。倒排索引是用内容…...
ARM与x86:架构对比及其应用
典型的服务器架构的x86采用模块化方法,基于带有可更换组件的主板。CPU和其他组件(如显卡和GPU、内存控制器、存储或处理核心)针对特定功能进行了优化,可以轻松更换或扩展。然而,这种便利是有代价的;这些硬件…...
macos 搭建 ragflow 开发环境
ragflow 是一个很方便的本地 RAG 库。本文主要记录一下在本机的部署过程 1、总体架构说明 开发环境:macbook pro(m1),16G内存 512G固态 因本机的内存和硬盘比较可怜,所以在服务器上部署基础 docker 包,…...
CVPR 2024 人体姿态估计总汇(3D人体、手语翻译和人体网格恢复/重建等)
1、Human Pose Estimation(人体姿态估计) CLOAF: CoLlisiOn-Aware Human FlowMeta-Point Learning and Refining for Category-Agnostic Pose EstimationSurMo: Surface-based 4D Motion Modeling for Dynamic Human Rendering ⭐codeGALA: Generating Animatable Layered Ass…...
docker 安装mongodb
1、先获取mongodb镜像 docker pull mongo:4.2 2、镜像拉取完成后,运行mongodb容器 docker run \ -d \ --name mongo \ --restartalways \ --privilegedtrue \ -p 27017:27017 \ -v /home//mongodb/data:/data/db \ mongo:4.2 --auth 3、mongodb服务配置 如上图&…...
82_Redis缓存雪崩击穿穿透问题
在实际业务应用中,Redis常常与诸如MySQL这类关系型数据库协同工作,旨在缓解后端数据库的负担。它扮演了一个高效缓存的角色,特别是针对那些频繁被访问的热点数据。当用户发起查询时,系统首先尝试从Redis中获取这些数据。由于Redis提供了极快的访问速度,如果数据存在于Redi…...
统计学习算法——逻辑斯谛回归
内容来自B站Up主:动画讲编程https://www.bilibili.com/video/BV1CR4y1L7RC、风中摇曳的小萝卜https://www.bilibili.com/video/BV17r4y137bW,仅为个人学习所用。 极大似然估计 几率、概率与似然 几率是指某个事件发生的可能性与不发生的可能性之比&am…...
设计模式03:行为型设计模式之策略模式的使用情景及其基础Demo
1.策略模式 好处:动态切换算法或行为场景:实现同一功能用到不同的算法时和简单工厂对比:简单工厂是通过参数创建对象,调用同一个方法(实现细节不同);策略模式是上下文切换对象,调用…...
C51交通控制系统的设计与实现
实验要求: 本题目拟设计一个工作在十字路口的交通信号灯控制系统,设东西方向为主干道A,南北方向为辅助干道B。要求:(1)用发光二极管模拟交通灯信号;(2)灵活控制主、辅干…...
css 实现自定义虚线
需求: ui 画的图是虚线,但是虚线很宽正常的border 参数无法做到 进程: 尝试使用 border:1px dashed 发现使用这个虽然是虚线但是很短密密麻麻的 这并不是我们想要的那就只能换方案 第一个最简单,让ui 画一个图然…...
网络协议基础--协议分层
一.协议概述 1.TCP/IP 传输协议概述 TCP/IP 传输协议,即传输控制 / 网络协议,也被称作网络通讯协议。它是网络中使用的最基本通信协议,对互联网中各部分进行通信的标准和方法予以规定。通常所说的 TCP/IP 协议并非仅指 TCP 和 IP 两个协议&a…...
iOS - TLS(线程本地存储)
从源码中,详细总结 TLS (Thread Local Storage) 的实现: 1. TLS 基本结构 // TLS 的基本结构 struct tls_data {pthread_key_t key; // 线程本地存储的键void (*destructor)(void *); // 清理函数 };// 自动释放池的 TLS class Autorelease…...
主链和Layer2之间资产转移
主链和Layer2之间资产转移 主链和Layer2之间资产转移是实现Layer2技术的关键环节,以下是资产转移的流程、流行解决方案及原理: 资产从主链转移到Layer2 用户在主链上发起一笔交易,将资产发送到一个特定的智能合约地址,这个合约是主链与Layer2之间的桥梁。智能合约会锁定用…...
深度学习-算法优化与宇宙能量梯度分布
在当今迅速发展的科技世界中,算法优化和能量分布问题已成为研究的热点,尤其是在人工智能、机器学习和物理科学领域。算法优化通常涉及提高计算效率和降低资源消耗,而宇宙能量梯度分布则涉及宇宙中能量的分布和流动方式。两者看似是完全不同的…...
《Java核心技术II》实现服务器
实现服务器 这节实现简单服务器,可以向客户端发送信息。 服务器套接字 ServerSocket用于建立套接字 var s new ServerSocket(8189); 建立一个监听端口8189的服务器。 Socket incoming s.accept(); 此对象可以得到输入流和输出流。 InputStream inStream incomin…...
登上Nature!交叉注意力机制 发顶会流量密码!
在深度学习领域,交叉注意力融合技术正迅速崛起,并成为处理多模态数据的关键工具。这一技术通过有效地整合来自不同模态的信息,使得模型能够更好地理解和推理复杂的数据关系。 随着多模态数据的日益普及,如图像、文本和声音等&…...
Windows 正确配置android adb调试的方法
下载适用于 Windows 的 SDK Platform-Tools https://developer.android.google.cn/tools/releases/platform-tools?hlzh-cn 设置系统变量,路径为platform-tools文件夹的绝对路径 点击Path添加环境变量 %adb%打开终端输入adb shell 这就成功了!...
leetcode刷题记录(五十六)——53. 最大子数组和
(一)问题描述 给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 子数组是数组中的一个连续部分。 示例 1: 输入:nums [-2,1,…...
SQL BETWEEN 操作符
SQL BETWEEN 操作符 SQL中的BETWEEN操作符用于选取介于两个值之间的数据范围。这些值可以是数字、文本或日期。BETWEEN操作符是SQL中非常实用的一个功能,它可以帮助我们快速地筛选出符合特定条件的数据记录。 BETWEEN操作符的基本用法 BETWEEN操作符的基本语法如…...
分布式 IO 模块:引领立体车库迈向智能化新时代
在城市空间愈发珍贵的当下,立体车库作为高效利用空间的停车解决方案,正日益普及。而明达技术MR30分布式 IO 模块的应用,如同为立体车库注入了智能 “芯” 动力,让停车变得更加便捷、高效、智能。 MR30分布式 IO 模块,作…...
《C++11》深入剖析正则表达式库:解锁文本处理的高效之道
在现代编程领域,文本处理是一项不可或缺的任务,而正则表达式无疑是这一领域的强大利器。C11标准库的引入,为C开发者带来了正则表达式库,极大地丰富了C在文本处理方面的能力。本文将全方位、多角度地深入探讨C11正则表达式库&#…...
Mongodb相关内容
Mongodb相关内容 1、Windows平台安装2、Linux平台安装3、基本常用命令文档更新删除文档分页查询索引 pymongo操作 客户端下载:https://download.csdn.net/download/guoqingru0311/90273435 1、Windows平台安装 方式一: 方式2: 方式3&#…...
United States of America三种表示
"United States of America", "United States", 和 "America" 都表示美国,但它们的使用场景和背景略有不同。以下是关于为什么这些名称可以合在一起表示美国的详细解释: 1. "United States of America" 全称&a…...
【Redis】Redis特性及其应用场景
目录 Redis特性 在内存中存储数据 可编程性 可扩展性 持久化 集群 高可用 补充特性 Redis的应用场景 数据库 缓存 会话存储 消息队列中间件 Redis特性 Redis是一个在内存中存储数据的中间件,用于作为数据库、数据缓存。Redis在分布式系统中有着较…...
Vue 使用blob下载文件,打开文件,文件是损毁的
文章目录 问题分析解决 问题 如图所示,在进行图片下载时下载的文件显示图片已被损 分析 代码如下: import axios from axios; async function downloadImage1(link, name) {try {const response await axios.get(link, {responseType: blob, // 设置响…...
Android 通过systrace如何快速找到app的刷新率
1. 如何抓取systrace: 方法一 andrdoid11以及以上的android版本都支持使用perfetto的方式抓取systrace,简单好用。 adb shell perfetto --buffer 512mb --time 10s --out /data/misc/perfetto-traces/perfetto_trace gfx input view wm am hal res dalv…...
vulnhub靶场【Raven系列】之2 ,对于mysql udf提权的复习
前言 靶机:Raven-2,IP地址为192.168.10.9 攻击:kali,IP地址为192.168.10.2 都采用虚拟机,网卡为桥接模式 文章所用靶机来自vulnhub,可通过官网下载,或者通过链接:https://pan.quark.cn/s/a65…...
【单片机开发 - STM32(H7)】启动流程、方式、烧录方式详解
如侵权,联系删,个人总结学习用 参考资料:(最末尾有我的原生笔记,那个格式规范点) 安富莱 ARM汇编伪指令详解-CSDN博客 【STM32】STM32内存映射以及启动过程(超详细过程)-CSDN博客…...
[手机Linux] ubuntu 错误解决
Ubuntu: 1,ttyname failed: Inappropriate ioctl for device 将 /root/.profile 文件中的 mesg n || true 改为如下内容。 vim /root/.profile tty -s && mesg n || true 2,Errors were encountered while processing: XXX XXXX sudo apt-get --purge remove xxx…...
springCloudGateway+nacos自定义负载均衡-通过IP隔离开发环境
先说一下想法,小公司开发项目,参考若依框架使用的spring-cloud-starter-gateway和spring-cloud-starter-alibaba-nacos, 用到了nacos的配置中心和注册中心,有多个模块(每个模块都是一个服务)。 想本地开发,…...
MyBatis-增删改查操作一些细节
目录 删除 新增 修改 查询 小结: 删除功能 需求:根据ID删除用户信息 SQL:delete from user where id 5; Mapper接口方法(注意这里不是实现类): /*** 根据id删除*/ Delete("delete from user wher…...
windows 极速安装 Linux (Ubuntu)-- 无需虚拟机
1. 安装 WSL 和 Ubuntu 打开命令行,执行 WSL --install -d ubuntu若报错,则先执行 WSL --update2. 重启电脑 因安装了子系统,需重启电脑才生效 3. 配置 Ubuntu 的账号密码 打开 Ubuntu 的命令行 按提示,输入账号,密…...
【学习笔记】各种强化学习环境
0. 写在前面 0.1 强化学习综述/资料(更新中) 鹏程实验室: 中文报道:学术分享丨具身智能综述:鹏城实验室&中大调研近400篇文献,英文原文:Aligning Cyber Space with Physical World…...
统计有序矩阵中的负数
统计有序矩阵中的负数 描述 给你一个 m * n 的矩阵 grid,矩阵中的元素无论是按行还是按列,都以非递增顺序排列。 请你统计并返回 grid 中 负数 的数目 示例 1: 输入:grid [[4,3,2,-1],[3,2,1,-1],[1,1,-1,-2],[-1,-1,-2,-3]]…...
【已解决】git clone报错:Failed to connect to github.com port 443: Timed out
1.问题原因1 报错信息1: fatal: unable to access https://github.com/microsoft/xxx/: Failed to connect to github.com port 443: Timed out 报错信息2: fatal: unable to access https://github.com/xxx/xx/: OpenSSL SSL_read: Connection was …...
Android SystemUI——使用Dagger2加载组件(四)
SystemUI 是 Android 系统中的一个重要模块,负责绘制系统栏(如状态栏、导航栏)、锁屏、快捷设置等用户界面元素。由于其复杂性,良好的架构设计和依赖管理对于保持代码的可维护性和扩展性至关重要。这就是 Dagger2 在此发挥重要作用的地方。 一、Dagger2介绍 Dagger2 是一个…...
Lesson 109 A good idea
Lesson 109 A good idea 词汇 idea n. 主意,想法 复数:ideas 用法:口语:Good idea! 好主意! Big idea! 高见!好主意! Great idea! 好主意 Bad idea! 坏主…...
网络安全-RSA非对称加密算法、数字签名
数字签名非常普遍: 了解数字签名前先了解一下SHA-1摘要,RSA非对称加密算法。然后再了解数字签名。 SHA-1 SHA-1(secure hash Algorithm )是一种 数据加密算法。该算法的思想是接收一段明文,然后以一种不可逆的方式将…...
自动化办公|xlwings简介
xlwings 是一个开源的 Python 库,旨在实现 Python 与 Microsoft Excel 的无缝集成。它允许用户使用 Python 脚本自动化 Excel 操作,读取和写入数据,执行宏,甚至调用 VBA 脚本。这使得数据分析、报告生成和其他与 Excel 相关的任务…...
C#使用OpenTK绘制3D可拖动旋转图形三棱锥
接上篇,绘制着色矩形 C#使用OpenTK绘制一个着色矩形-CSDN博客 上一篇安装OpenTK.GLControl后,这里可以直接拖动控件GLControl 我们会发现GLControl继承于UserControl //// 摘要:// OpenGL-aware WinForms control. The WinForms designer will always call the default//…...
【网络云SRE运维开发】2025第3周-每日【2025/01/14】小测-【第13章ospf路由协议】理论和实操
文章目录 选择题(10道)理论题(5道)实操题(5道) 【网络云SRE运维开发】2025第3周-每日【2025/01/14】小测-【第12章ospf路由协议】理论和实操 选择题(10道) 在OSPF协议中,…...
计算机网络 (34)可靠传输的工作原理
前言 计算机网络可靠传输的工作原理主要依赖于一系列协议和机制,以确保数据在传输过程中能够准确无误地到达目的地。 一、基本概念 可靠传输指的是数据链路层的发送端发送什么,在接收端就收到什么,即保证数据的完整性、正确性和顺序性。由于网…...
提高互联网Web安全性:避免越权漏洞的技术方案
目录 一、越权漏洞概述 二、常见的越权漏洞类型 三、越权漏洞的影响 四、越权漏洞的技术解决方案 一、越权漏洞概述 越权(Authorization Bypass)类漏洞是指在系统中,攻击者通过绕过身份验证或访问控制,获取本不应访问的资源或…...
c语言 --- 字符串
创建字符串 1. 使用字符数组创建字符串 #include <stdio.h>int main() {char str[20] "Hello, world!";str[0] h; // 修改字符串的第一个字符printf("%s\n", str); // 输出:hello, world!return 0; }解释: 数组大小 20 表…...
Linux探秘坊-------1.系统核心的低语:基础指令的奥秘解析(3)
1.zip/unzip指令 语法: zip 压缩⽂件.zip ⽬录或⽂件 功能:将⽬录或⽂件压缩成zip格式 常⽤选项: -r:递归处理,将指定⽬录下的 所有⽂件和⼦⽬录⼀并处理 example: 1.事前准备 建立以下文件与目录: 2.压缩test 目…...
Java中网络编程的学习
目录 网络编程概述 网络模型 网络通信三要素: IP 端口号 通信协议 IP地址(Internet Protocol Address) 端口号 网络通信协议 TCP 三次握手 四次挥手 UDP TCP编程 客户端Socket的工作过程包含以下四个基本的步骤: 服务器程序…...
微服务的CAP定理与数据一致性抉择
分布式系统中的CAP定理,包括一致性(Consistency)、可用性(Availability)和分区容错性(Partition Tolerance)三个核心要素。 微服务是分布式系统的一种表现形式,以及用户对于系统是分…...
正则表达式 - 简介
正则表达式 - 简介 正则表达式(Regular Expression,简称Regex)是一种用于处理字符串的强大工具,它允许我们按照特定的模式(pattern)来搜索、匹配、查找和替换文本。正则表达式广泛应用于各种编程语言和工具…...