关于 smali:2. 从 Java 到 Smali 的映射
一、对照 Java 代码与 Smali 代码差异
1.1 方法调用差异:Java vs Smali
Java 方法分类:
方法类型 | Java 示例 | Smali 指令 | 特点说明 |
---|---|---|---|
静态方法 | Utils.print("hi") | invoke-static | 没有 this 指针 |
实例方法 | obj.show() | invoke-virtual | 有 this,虚函数调用 |
构造函数 | new Person() | invoke-direct | 用于构造对象 |
私有方法 | this.hidden() | invoke-direct | 调用私有方法 |
接口方法 | list.size() | invoke-interface | 调用接口方法 |
父类方法 | super.toString() | invoke-super | 调用父类方法 |
动态调用(API) | Java 8 lambda 等 | invoke-polymorphic | 用于一些特殊函数,如反射调用 |
示例对照
1)静态方法调用
Java
Logger.log("test");
Smali
const-string v0, "test"
invoke-static {v0}, Lcom/example/Logger;->log(Ljava/lang/String;)V
2)实例方法调用
Java
User u = new User();
u.say("hello");
Smali
new-instance v0, Lcom/example/User;
invoke-direct {v0}, Lcom/example/User;-><init>()Vconst-string v1, "hello"
invoke-virtual {v0, v1}, Lcom/example/User;->say(Ljava/lang/String;)V
3)构造器调用
构造器就是特殊方法 <init>
Java
Person p = new Person();
Smali
new-instance v0, Lcom/example/Person;
invoke-direct {v0}, Lcom/example/Person;-><init>()V
1.2 控制流语句差异:Java vs Smali
if-else 语句
Java
if (a > b) {doA();
} else {doB();
}
Smali
# a = v0, b = v1
if-le v0, v1, :else_block
invoke-static {}, Lcom/example/Utils;->doA()V
goto :end:else_block
invoke-static {}, Lcom/example/Utils;->doB()V:end
常用比较指令:
指令 | 条件 |
---|---|
if-eq | 等于(==) |
if-ne | 不等(!=) |
if-lt | 小于(<) |
if-gt | 大于(>) |
if-le | 小于等于(≤) |
if-ge | 大于等于(≥) |
switch 语句
Java
switch (x) {case 1: f1(); break;case 5: f5(); break;default: fDefault();
}
Smali
sparse-switch v0, :switch_data # v0 是 switch 的变量
goto :default # 如果没匹配任何 case,跳转 default:switch_data.sparse-switch0x1 -> :case10x5 -> :case5.end sparse-switch:case1invoke-static {}, Lcom/example/Util;->f1()Vgoto :end:case5invoke-static {}, Lcom/example/Util;->f5()Vgoto :end:defaultinvoke-static {}, Lcom/example/Util;->fDefault()V:end# 后续逻辑继续执行
while 循环
Java
int i = 0;
while (i < 10) {i++;
}
Smali
const/4 v0, 0x0 # i = 0
:loop_start
const/4 v1, 0xA
if-ge v0, v1, :loop_endadd-int/lit8 v0, v0, 1
goto :loop_start:loop_end
说明:
-
if-ge v0, v1, :loop_end
:当 i ≥ 10 跳出循环 -
goto
:用于跳转控制流
1.3 类字段与方法修饰符差异
字段定义差异
Java
public int count;
private String name;
Smali
.field public count:I
.field private name:Ljava/lang/String;
字段类型缩写表:
Java 类型 | Smali 类型 |
---|---|
int | I |
boolean | Z |
byte | B |
char | C |
short | S |
long | J |
float | F |
double | D |
对象 | L类路径; |
字段访问指令
Java
this.count = 1;
int x = this.count;
Smali
const/4 v1, 0x1
iput v1, v0, Lcom/example/MyClass;->count:Iiget v2, v0, Lcom/example/MyClass;->count:I
说明:
-
iput
= instance put,写入字段 -
iget
= instance get,读取字段
方法定义与修饰符
Java
public void print(int n) { ... }
private int getNum() { return num; }
Smali
.method public print(I)V.locals 1# ...代码
.end method.method private getNum()I.locals 1# ...代码
.end method
Java 修饰符 | Smali 前缀 |
---|---|
public | public |
private | private |
protected | protected |
static | static |
final | final |
abstract | abstract |
synchronized | synchronized |
native | native |
1.4 总结:Java ↔ Smali 快速对照表
Java 表达式 | Smali 表达 | 说明 |
---|---|---|
静态方法调用 | invoke-static | 无 this |
实例方法调用 | invoke-virtual | 用 this |
构造函数调用 | invoke-direct | <init>() 构造器 |
if 条件控制 | if-eq / if-lt / if-ge 等 | 条件跳转 |
switch 分支 | .sparse-switch / .packed-switch | 分支跳转表 |
字段定义 | .field public/private 名:类型 | 类成员变量 |
字段访问 | iget / iput | 实例字段读写 |
方法定义 | .method public 名(参数)返回值 | 类方法定义 |
二、方法调用
2.1 Smali 方法调用指令分类
指令 | 调用类型 | 用途(Java 等价) |
---|---|---|
invoke-static | 静态方法 | ClassName.method() |
invoke-virtual | 实例方法(常用) | obj.method() |
invoke-direct | 构造方法、私有方法 | new Obj() ,this.privateMethod() |
invoke-super | 调用父类方法 | super.method() |
invoke-interface | 接口方法 | interfaceObj.method() |
invoke-virtual/range 等 | 处理参数多的 | 用于参数超过 5 个时 |
2.2 基础格式说明
通用格式:
invoke-xxx {参数寄存器列表}, L类名;->方法名(参数类型)返回类型
说明:
-
{}
中写的是使用的寄存器(如{v0, v1}
) -
L类名;
是类路径(如Ljava/lang/String;
) -
(参数类型)
:方法的参数签名 -
返回类型
:返回值类型(V
表示 void)
2.3 详细讲解每个指令
1)invoke-static
:调用静态方法
Java 中 Class.method()
,如 Math.abs(-1)
示例:
invoke-static {v0}, Ljava/lang/Math;->abs(I)I
说明:
-
调用
Math.abs(int)
方法 -
v0
是传入的参数 -
(I)I
表示:参数是int
,返回也是int
特点:
-
不需要实例对象
-
类方法、工具方法、
public static
方法都用这个调用
2)invoke-virtual
:调用实例方法(最常用)
Java 中 obj.method()
,例如 str.length()
示例:
invoke-virtual {v0}, Ljava/lang/String;->length()I
说明:
-
v0
是一个String
对象 -
调用它的
length()
方法 -
()
:无参数,返回int
特点:
-
用于非私有的实例方法(包括
public
、protected
) -
支持虚方法分发(多态)
3)invoke-direct
:调用构造方法、私有方法
Java 中 new MyObject()
或 this.privateMethod()
示例 1:调用构造函数
new-instance v0, Lcom/example/MyClass;
invoke-direct {v0}, Lcom/example/MyClass;-><init>()V
说明:
-
v0
是要构造的对象 -
调用其构造器
MyClass()
-
<init>()V
是构造函数签名(返回类型是 void)
示例 2:调用私有方法
invoke-direct {v0}, Lcom/example/MyClass;->myPrivateMethod()V
特点:
-
只能调用当前类的 private 方法 或 构造函数
-
无法用于调用继承的或 public/protected 方法
补充:invoke-super
调用父类的方法,通常在子类中使用 super.method()
示例:
invoke-super {v0}, Lcom/example/ChildClass;->toString()Ljava/lang/String;
补充:invoke-interface
调用接口方法(Java 接口)
示例:
invoke-interface {v0}, Ljava/util/List;->size()I
2.4 几个重要的调用场景示例
调用静态方法(工具类)
Utils.sayHello();
invoke-static {}, Lcom/example/Utils;->sayHello()V
调用实例方法(普通对象方法)
myObj.getName();
invoke-virtual {v0}, Lcom/example/MyClass;->getName()Ljava/lang/String;
调用构造器(创建对象)
new MyClass();
new-instance v0, Lcom/example/MyClass;
invoke-direct {v0}, Lcom/example/MyClass;-><init>()V
调用私有方法(类内部)
this.secret();
invoke-direct {v0}, Lcom/example/MyClass;->secret()V
2.5 寄存器数量限制说明
最多可以用 5 个寄存器调用 invoke-*
,如果超过 5 个参数(例如构造函数参数很多):
-
使用
invoke-* /range
版本:
invoke-static/range {v0 .. v6}, Lcom/example/MyClass;->bigMethod(IJFLD)V
2.6 小结
指令 | 用途 | 说明 |
---|---|---|
invoke-static | 静态方法 | 不需要对象实例 |
invoke-virtual | 实例方法(普通调用) | 可被 override(多态) |
invoke-direct | 构造方法/私有方法 | 无法 override,调用 <init> |
invoke-super | 父类方法 | 用于 super.xxx() |
invoke-interface | 接口方法 | 用于接口对象 |
三、控制流语句
3.1 if-else
结构
Java 示例:
if (v0 == 1) {Log.i("TAG", "Equal");
} else {Log.i("TAG", "Not Equal");
}
Smali 实现:
# v0 已有值
const/4 v1, 0x1
if-eq v0, v1, :equal # 如果 v0 == 1 跳转到 :equal:not_equalconst-string v2, "TAG"const-string v3, "Not Equal"invoke-static {v2, v3}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)Igoto :end:equalconst-string v2, "TAG"const-string v3, "Equal"invoke-static {v2, v3}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I:end
Smali 中常见条件跳转指令:
指令 | 含义 |
---|---|
if-eq | 相等跳转 |
if-ne | 不等跳转 |
if-lt | 小于跳转 |
if-gt | 大于跳转 |
if-le | 小于等于跳转 |
if-ge | 大于等于跳转 |
if-eqz | v == 0 跳转(zero) |
if-nez | v != 0 跳转 |
3.2 switch-case
Java 示例:
switch (v0) {case 1: f1(); break;case 5: f5(); break;default: fDefault();
}
Smali 实现(sparse-switch):
sparse-switch v0, :switch_data
goto :default:switch_data.sparse-switch0x1 -> :case10x5 -> :case5.end sparse-switch:case1invoke-static {}, Lcom/example/Util;->f1()Vgoto :end:case5invoke-static {}, Lcom/example/Util;->f5()Vgoto :end:defaultinvoke-static {}, Lcom/example/Util;->fDefault()V:end
packed-switch vs sparse-switch
类型 | 用法 |
---|---|
packed-switch | case 是连续整数时使用 |
sparse-switch | case 是稀疏整数时使用 |
3.3 while
循环
Java 示例:
int i = 0;
while (i < 5) {Log.d("loop");i++;
}
Smali 实现:
const/4 v0, 0x0 # i = 0:loop_startconst/4 v1, 0x5if-ge v0, v1, :loop_end # if i >= 5 -> endconst-string v2, "loop"invoke-static {v2}, Landroid/util/Log;->d(Ljava/lang/String;)Iadd-int/lit8 v0, v0, 0x1 # i++goto :loop_start:loop_end
3.4 for
循环(其实就是 while)
Java 示例:
for (int i = 0; i < 3; i++) {Log.e("for");
}
Smali 实现:
const/4 v0, 0x0 # int i = 0:for_beginconst/4 v1, 0x3if-ge v0, v1, :for_end # if i >= 3 -> endconst-string v2, "for"invoke-static {v2}, Landroid/util/Log;->e(Ljava/lang/String;)Iadd-int/lit8 v0, v0, 0x1 # i++goto :for_begin:for_end
3.5 常见跳转逻辑总结表
Java 控制结构 | Smali 表达方式 |
---|---|
if (a == b) | if-eq a, b, :label_true |
if (a != 0) | if-nez a, :label_true |
while (...) | 标签 :begin + 条件跳转 + goto :begin |
for (...) | 与 while 相同结构 |
switch | sparse-switch / packed-switch + 标签 |
四、类字段
4.1 什么是类字段
在 Java 中,字段就是类的成员变量:
public class Person {public String name;private static int count;
}
在 Smali 中,这些字段会写成:
.field public name:Ljava/lang/String;.field private static count:I
4.2 字段的 Smali 语法结构
.field [修饰符] 字段名:类型
常见修饰符:
修饰符 | 含义 |
---|---|
public | 公有 |
private | 私有 |
protected | 受保护 |
static | 静态字段(属于类) |
final | 常量 |
volatile | 多线程可见性(较少见) |
transient | 不序列化(与 Java 一致) |
synthetic | 编译器自动生成(反混淆重要) |
4.3 字段类型表示法(Smali 中)
Java 类型 | Smali 符号 |
---|---|
int | I |
boolean | Z |
byte | B |
char | C |
short | S |
long | J |
float | F |
double | D |
void | V (方法返回专用) |
String | Ljava/lang/String; |
MyClass | Lcom/example/MyClass; |
数组 | [I (int[]),[Ljava/lang/String; (String[]) |
4.4 Smali 中访问字段
字段分为 实例字段 和 静态字段,对应不同的访问指令。
1)实例字段(每个对象一份)
操作 | 指令名 | 示例 |
---|---|---|
读取字段 | iget | iget v1, v0, Lcom/demo/User;->name:Ljava/lang/String; |
写入字段 | iput | iput v2, v0, Lcom/demo/User;->name:Ljava/lang/String; |
2)静态字段(类级别共享)
操作 | 指令名 | 示例 |
---|---|---|
读取字段 | sget | sget v0, Lcom/demo/User;->count:I |
写入字段 | sput | sput v1, Lcom/demo/User;->count:I |
4.5 例子分析:完整的字段声明与访问流程
Java 示例:
public class User {public String name;private static int count = 0;public void setName(String n) {this.name = n;count++;}
}
Smali 对应(简化版):
.class public Lcom/demo/User;
.super Ljava/lang/Object;.field public name:Ljava/lang/String;
.field private static count:I.method public setName(Ljava/lang/String;)V.locals 1# 把参数 n(p1)赋值给 this.nameiput-object p1, p0, Lcom/demo/User;->name:Ljava/lang/String;# sget 静态字段sget v0, Lcom/demo/User;->count:Iadd-int/lit8 v0, v0, 0x1sput v0, Lcom/demo/User;->count:Ireturn-void
.end method
4.6 几个实战技巧与细节
判断字段是静态还是实例
特征 | 静态字段 | 实例字段 |
---|---|---|
修饰符 | 带 static | 不带 static |
读取指令 | sget / sput | iget / iput |
所属 | 类级别共享 | 每个对象一份 |
典型用途 | 常量、计数器 | 每个对象的属性,如 name |
Frida Hook 中字段的常用操作
// 获取实例字段
Java.use("com.demo.User").name.value// 获取静态字段
Java.use("com.demo.User").count.value// 设置字段
Java.use("com.demo.User").name.value = "hack"
4.7 .field 高级用法
初始值:
.field public static final CONST:I = 0x5
表示该字段常量为 5(int
型)
4.8 小结
类型 | 声明指令 | 访问读取 | 写入修改 |
---|---|---|---|
实例字段 | .field name:Type | iget / iget-object | iput / iput-object |
静态字段 | .field static name:Type | sget / sget-object | sput / sput-object |
五、方法访问修饰符在 Smali 中如何体现
5.1 方法的 Smali 定义格式
.method [修饰符] 方法名(参数)返回类型
比如:
.method public static final doSomething(I)Ljava/lang/String;
这是一个:
-
public
公有 -
static
静态 -
final
不可重写
的方法,接受一个int
参数,返回一个String
。
5.2 常见修饰符说明(对照 Java)
Smali 修饰符 | Java 对应 | 含义解释 |
---|---|---|
public | public | 任何类都可以调用(最常见) |
private | private | 仅类内部调用 |
protected | protected | 同包或子类中可调用 |
static | static | 属于类本身,不依赖实例对象 |
final | final | 不可被子类重写(继承中常见) |
abstract | abstract | 抽象方法(无实现体,interface、abstract class 中出现) |
synthetic | 编译器自动添加 | 编译生成的方法(如桥接方法、Lambda 方法),用于反混淆 |
constructor | 构造函数 | 表示这是构造方法(即 <init> ) |
native | native | 本地方法,用 JNI 实现(通常没代码体) |
bridge | 编译器桥接 | 泛型擦除后生成的桥接方法(一般逆不了逻辑) |
varargs | T... args | 可变参数(只是标记,不影响 Smali 写法) |
5.3 完整示例分析
Java 源码
public class Demo {public static final void log(String msg) {Log.d("TAG", msg);}private int compute(int a, int b) {return a + b;}protected abstract void work(); // 抽象方法
}
对应 Smali
.method public static final log(Ljava/lang/String;)V.locals 1const-string v0, "TAG"invoke-static {v0, p0}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)Ireturn-void
.end method.method private compute(II)I.locals 1add-int v0, p1, p2return v0
.end method.method protected abstract work()V
5.4 修饰符的实际作用和实战用途
修饰符 | 实战应用举例 |
---|---|
public | 可直接用 Frida/Java 调用(常用于静态分析) |
private | 需要 Frida Bypass 或 Java.use(...).$init.overload(...) |
static | 无需创建实例,Frida 中直接 .value 或 invokeStatic |
final | 子类不能 override,意味着 Hook 只能静态覆盖 |
abstract | 没有方法体,不能直接 Hook,要 Hook 实现类 |
synthetic | 混淆后生成的自动方法,可包含核心逻辑(Frida 分析重点) |
constructor | 对应 <init> ,实例化时会调用,可以 hook $init |
native | 没有 Smali 代码体,常需要 native 层分析或 trace |
5.5 Hook 时与修饰符的注意事项
1)Hook 静态方法(static)
Java.use("com.test.Demo").log.overload('java.lang.String').implementation = function(msg) {console.log("log hooked: " + msg);
};
2)Hook 实例方法(非 static)
Java.use("com.test.Demo").compute.implementation = function(a, b) {return a + b + 999;
};
3)Hook 构造方法 <init>
Java.use("com.test.Demo").$init.overload('int', 'java.lang.String').implementation = function(i, s) {console.log("构造函数拦截:" + i + ", " + s);return this.$init(i, s);
};
5.6 总结速查表
修饰符组合 | 含义 |
---|---|
.method public | 公有方法(类外可访问) |
.method private | 私有方法(类内访问,hook 时需绕过) |
.method static | 静态方法(不依赖实例) |
.method constructor | 构造方法 <init> |
.method abstract | 抽象方法(无实现体) |
.method public static final | 常量型工具函数 |
.method synthetic | 编译器生成,可能是混淆后的关键方法 |
相关文章:
关于 smali:2. 从 Java 到 Smali 的映射
一、对照 Java 代码与 Smali 代码差异 1.1 方法调用差异:Java vs Smali Java 方法分类: 方法类型Java 示例Smali 指令特点说明静态方法Utils.print("hi")invoke-static没有 this 指针实例方法obj.show()invoke-virtual有 this,虚…...

三、zookeeper 常用shell命令
作者:IvanCodes 日期:2025年5月28日 专栏:Zookeeper教程 ZooKeeper Shell (zkCli.sh) 是与ZooKeeper服务器交互的核心工具。本教程将详细介绍常用命令,并重点解析ZooKeeper数据节点 (ZNode) 的特性与分类。 思维导图 一、连接 Zo…...

分布式流处理与消息传递——Paxos Stream 算法详解
Java 实现 Paxos Stream 算法详解 一、Paxos Stream 核心设计 #mermaid-svg-cEJcmpaQwLXpEbx9 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-cEJcmpaQwLXpEbx9 .error-icon{fill:#552222;}#mermaid-svg-cEJcmpaQw…...
智变与重构:AI 赋能基础教育教学的范式转型研究报告
一、研究背景与核心价值 (一)技术驱动下的教育转型浪潮 在全球数字化转型加速的背景下,人工智能作为核心技术力量,正重塑基础教育生态。据《人工智能赋能未来教育研究报告》指出,我国教育数字化战略行动已推动超 70…...
平衡三进制
平衡三进制 - OI Wiki https://oi-wiki.org/math/balanced-ternary/ 上海市计算机学会竞赛平台 | YACS 方法一,先分离后进位 #include <iostream> using namespace std; int n, a[100], cnt; bool flag; int main() {cin >> n;if(n0){cout <<…...
针对Python开发的工具推荐及分析,涵盖集成开发环境(IDE)、轻量级工具、在线开发平台、代码管理工具等)
以下是针对Python开发的工具推荐及全面分析,涵盖集成开发环境(IDE)、轻量级工具、在线开发平台、代码管理工具等,结合不同场景和需求进行分类说明: 目录 一、集成开发环境(IDE) 1. PyCharm 2…...

960g轻薄本,把科技塞进巧克力盒子
朋友们,谁懂啊 最近本打工人被同事疯狂种草了一款 “巧克力盒子” 华硕灵耀 14 Air 骁龙版! 960g的重量比一瓶大可乐还轻 塞进通勤包毫无压力 连健身房的瑜伽垫都能多卷两圈 这台行走的生产力工具,到底有啥魔法? 今天就带…...

xcode 编译运行错误 Sandbox: rsync(29343) deny(1) file-write-create
解决方法 方法一:修改Targets -> Build Settings 中 ENABLE_USER_SCRIPT_SANDBOXING 设置 NO 方法二:项目使用cocoaPods进行三方管理 且 使用了 use_frameworks,把 use_frameworks 注释掉,然后重新自行pod install...

C# 基于 Windows 系统与 Visual Studio 2017 的 Messenger 消息传递机制详解:发布-订阅模式实现
🧑 博主简介:CSDN博客专家、CSDN平台优质创作者,高级开发工程师,数学专业,10年以上C/C, C#, Java等多种编程语言开发经验,拥有高级工程师证书;擅长C/C、C#等开发语言,熟悉Java常用开…...

ComfyUI+阿里Wan2.1+内网穿透技术:本地AI视频生成系统搭建实战
文章目录 前言1.软件准备1.1 ComfyUI1.2 文本编码器1.3 VAE1.4 视频生成模型 2.整合配置3. 本地运行测试4. 公网使用Wan2.1模型生成视频4.1 创建远程连接公网地址 5. 固定远程访问公网地址总结 前言 各位技术爱好者,今天为您带来一组创新性的AI应用方案!…...
腾讯云开发者社区文章内容提取免费API接口教程
接口简介: 提取指定腾讯云开发者社区文章内容。本接口仅做内容提取,未经作者授权请勿转载。 请求地址: https://cn.apihz.cn/api/caiji/tencent.php 请求方式: POST或GET。 请求参数: 【名称】【参数】【必填】【说…...

利用海外代理IP,做Twitter2026年全球趋势数据分析
近年来,社交媒体趋势分析逐渐成为品牌监控、市场洞察和消费者研究的必备工具。而当谈到全球趋势数据分析,很多人都会立即想到 Twitter趋势(逼近连美丽国的总统都喜欢在上面发表自己的看法- -!!!)。Twitter趋势,即Twitt…...
OpenLayers 图形交互编辑
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 图形要素包括属性信息和几何信息,在实际应用中,不仅需要修改样式信息,也需要修改图形几何信息。在OpenLayers中&…...

pikachu靶场通关笔记06 XSS关卡02-反射型POST
目录 一、XSS 二、反射型XSS 三、POST型报文 四、GET型与POST型区别 五、代码审计 五、渗透实战 1、渗透方法1 2、渗透方法2 本系列为通过《pikachu靶场通关笔记》的XSS关卡(共10关)渗透集合,通过对XSS关卡源码的代码审计找到XSS风险的真实原因&…...

SQLiteStudio - 免费开源、轻量高效,跨平台的 SQLite 数据库管理工具,代替 Navicat for SQLite
管理 SQLite 数据库就用这款软件,真的早该摒弃破解和盗版的 Navicat 了。 SQLiteStudio 是一款专注于管理 SQLite 数据库 的桌面软件,用于浏览和编辑 SQLite 数据库文件。软件的作者是来自波兰的开发者 Paweł Salawa,他是一位拥有 20 年 Ja…...

Prometheus + Grafana + Cadvisor:构建高效企业级服务监控体系
在现代软件开发和运维领域,容器化技术的应用越来越广泛,其中 Docker 作为最受欢迎的容器化解决方案之一,其容器的监控管理变得至关重要。本文将详细介绍如何使用 cadvisor、Prometheus 和 Grafana 来监控 Docker 容器的状态。 一、安装镜像 …...

WEBSTORM前端 —— 第3章:移动 Web —— 第2节:空间转换、转化
目录 一、空间转换 1.空间转换 2.空间转换 – 平移 3.视距 perspective 4.空间 – 旋转 ③空间旋转——Z轴代码与效果视频 ④空间旋转——X轴代码与效果视频 ⑤空间旋转——Y轴代码与效果视频 5.立体呈现 – transform-style 案例 – 3D 导航 6.空间转换 – 缩放 …...

Java研学-MongoDB(一)
一 MongoDB 简介 MongoDB是一种高性能、开源的NoSQL数据库,采用面向文档的存储模型,以BSON(Binary JSON)格式存储数据,具有灵活的数据模型、强大的扩展性和丰富的功能特性,广泛应用于各类现代应用程序的数据…...

【AI面试秘籍】| 第25期:RAG的关键痛点及解决方案深度解析
今天我们来聊聊大模型领域一个非常火热的技术——RAG(Retrieval Augmented Generation)。RAG通过引入外部知识库,有效地缓解了大型语言模型(LLM)在处理知识密集型任务时可能出现的幻觉、知识过时等问题。然而ÿ…...
OpenGL、GLUT、freeGLUT 与 GLFW 的区别
在图形编程中,OpenGL 是最核心的渲染 API,但仅靠它本身无法完成窗口创建、事件处理等任务。因此,开发者通常会借助一些辅助库来简化开发流程。常见的库包括 GLUT、freeGLUT 和 GLFW。 本文将详细讲解这些技术之间的区别,并提供每…...

服务器带宽线路的区别(GIA、CN2、BGP、CMI等)
服务器带宽线路的区别(GIA、CN2、BGP、CMI等) 一、BGP线路 1. 定义与技术特点 BGP(Border Gateway Protocol,边界网关协议)是一种用于不同自治系统(AS)之间交换路由信息的协议,属…...

ppt一键制作:ai自动生成PPT,便捷高效超级精美!
深夜的台灯下,你对着杂乱的 PPT 内容反复刷新灵感,鼠标在字体、配色选项间来回穿梭,好不容易拼凑出的页面,却总透着浓浓的 “廉价感”;汇报在即,逻辑混乱的大纲改了又改,每一页感觉合适又不搭&a…...
多方法解决MNIST数字识别
全连接层 import torch from torchvision import datasets, transforms import torch.nn as nn import torch.optim as optim from tqdm import tqdm # 用于进度条显示 import os# 定义数据预处理(标准化+Tensor转换) transform = transforms.Compose([transforms.ToTensor…...

Maven(黑马)
Maven 是一个强大的项目管理和构建自动化工具,主要用于 Java 项目的构建、依赖管理和文档生成。它通过使用 POM(Project Object Model)文件来管理项目的配置和依赖关系,从而实现项目的自动化构建和管理。以下是 Maven 的一些核心概…...
CppCon 2014 学习:ODB, Advanced Weapons and Tactics
#Schema Evolution 是数据库持久化技术中的一个重要概念,特别是在使用像 ODB 这样的 C ORM 框架时。 展示的代码片段正是 ODB 支持的**模式演化(Schema Evolution)**语法示例。 什么是 Schema Evolution? Schema Evolution 指的…...

将手机网络经USB数据线和本地局域网共享给华为AP6050DN无线接入点
引言 由于最近装毕的新家所在的小区未能及时通宽带,于是家中各类无线设备如何上网就成了首要要解决的问题。 鉴于家中要联网的设备多、类型杂、支持频段也不一,总是开手机热点不是回事儿,于是就想着把手机网络引至华为AP6050DN无线接入点中,让家中所有的无线设备都能快速高…...

【论文解读】Deformable DETR | Deformable Transformers for End-to-End Object Detection
论文地址:https://arxiv.org/pdf/2010.04159 代码地址:https://github.com/fundamentalvision/Deformable-DETR 摘要 DETR最近被提出,旨在消除物体检测中许多手工设计的组件的需求,同时展示出良好的性能。然而,由于T…...
android 图片背景毛玻璃效果实现
图片背景毛玻璃效果实现 1 依赖 // Glide implementation("com.github.bumptech.glide:glide:4.16.0") kapt("com.github.bumptech.glide:compiler:4.16.0") implementation("jp.wasabeef:glide-transformations:4.3.0") 2 布局<com.googl…...

机器学习----决策树
一、决策树简介 from sklearn.tree import DecisionTreeClassifier from sklearn.tree import plot_tree 决策树是一种树形结构,树中每个内部节点表示一个特征上的判断,每个分支代表一个判断结果的输出,每个叶子节点代表一种分类结果。 决…...

LabVIEW输血袋字符智能检测系统
针对医疗行业输血袋字符检测需求,基于 LabVIEW 图形化开发平台与基恩士(KEYENCE)机器视觉硬件,构建高精度、高可靠性的字符在线识别系统。通过选用基恩士工业相机、光源及 NI 数据采集设备等硬件,结合 LabVIEW 强大的图…...