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

Android学习之路(27) ProGuard,混淆,R8优化

前言

使用java编写的源代码编译后生成了对于的class文件,但是class文件是一个非常标准的文件,市面上很多软件都可以对class文件进行反编译,为了我们app的安全性,就需要使用到Android代码混淆这一功能。

针对 Java 的混淆,ProGuard 就是常用的混淆工具,且他不仅仅是混淆工具,它同时可以对代码进行 压缩优化混淆

下面我们来简单介绍下ProGuard工作流程。

ProGuard 工作流程

ProGuard工作过程包括四个步骤:shrinkoptimizeobfuscatepreverigy。这四个步骤都是可选,但是顺序都是不变的

46abad1b3fbc2c28db008ecb949676b2.png

  • shrink:检测并删除项目中未使用到的类,字段,方法以及属性
  • optimize:优化字节码,移除无用指令,或者进行指令优化。
  • obfuscate:代码混淆,将代码中的类,字段,方法和属性等名称使用无意义的名称进行表示,减少代码反编译后的可读性。
  • preverify:针对 Java 1.6 及以上版本进行预校验, 校验 StackMap /StackMapTable 属性.在编译时可以关闭,加快编译速度

Android中的代码优化以及混淆

Android构建中,在AGP3.4.0之前也是使用的ProGuard 进行代码优化混淆,但是在3.4.0之后,谷歌将这一工作赋予给了性能更佳的R8编译器

虽然摒弃了ProGuard,但是R8编译器还是兼容ProGuard的配置规则

使用R8编译器可以做以下优化:

  • 1.代码缩减
  • 2.资源缩减
  • 3.代码混淆
  • 4.代码优化
1.代码缩减

代码缩减指的是:R8编译期智能检测代码中未使用到的类、字段、方法和属性等,并移除

比如你项目中依赖了很多库,但是只使用了库里面少部分代码,为了移除这部分代码,R8会根据配置文件确定应用代码的所有入口点:包括应用启动的第一个Activity或者服务等,R8会根据入口,检测应用代码,并构建出一张图表,列出应用运行过程中可能访问的方法,成员变量和类等,并对图中没有关联到的代码,视为可移除代码。

如下图:

图中入口位置:MainActivity,整个调用链路中,使用到了foo,bar函数以及AwesomeApi类中的faz函数,所以这部分代码会被构建到依赖图中,而OkayApi类以及其baz函数都未访问到,则这部分代码就可以被优化。

使用方式:

arduino
复制代码
android {buildTypes {release {...minifyEnabled true}}...
}

minifyEnabled 设置为true,会默认启用R8代码缩减功能。

代码优化需要注意的两种情况:

1.反射调用的情况

2.JNI调用的情况

R8并未对反射以及JNI等情况进行检测,如果配置文件中未处理,则这部分代码就会被丢弃,会出现NoClassFindException的异常,如何解决呢?

  • 1.1:在配置文件中使用-keep对这部分类进行说明:
kotlin
复制代码
-keep public class MyClass
  • 1.2:给需要保留的代码添加@keep注解

前提条件:1.声明了使用AndroidX 2.使用AGP默认的ProGuard文件

R8配置文件

R8使用ProGuard 规则文件来决定哪部分代码需要保留,配置文件来源分为下面几个:

  • 1.AndroidStudio:

位置:/proguard-rules.pro

说明

创建新的模块时,会在当前模块目录下创建一个默认的:proguard-rules.pro 文件

  • 2.AGP插件

位置:由AGP在编译时生成的proguard-android-optimize.txt

说明

Android Gradle 插件会生成 proguard-android-optimize.txt(其中包含了对大多数 Android 项目都有用的规则),并启用 @Keep* 注解。

编译后在\build\intermediates\proguard-files\目录下会生成3个文件:

image-20230424141102942

其中proguard-android-optimize.txt-4.1.1是需要进行optimize代码优化的ProGuard配置文件,而proguard-android.txt-4.1.1表示不需要进行optimize代码优化的ProGuard文件。

4.1.1表示当前模块的AGP插件版本

  • 3.库依赖项

位置

AAR 库:<library-dir>/proguard.txt

JAR 库:<library-dir>/META-INF/proguard/

说明

引入的aar或者jar包的库中,默认包含proguard优化规则,则在编译过程中也会被纳入R8配置项中,所以特别注意aar中引入的proguad和原项目规则冲突的情况。

  • 4.AAPT2(Android资源打包工具)

位置:使用 minifyEnabled true 构建项目后:<module-dir>/build/intermediates/proguard-rules/debug/aapt_rules.txt

说明

AAPT2 会根据对应用清单中的类、布局及其他应用资源的引用,生成保留规则。例如,AAPT2 会为您在应用清单中注册为入口点的每个 activity 添加一个保留规则。

  • 5.自定义配置文件

位置:默认情况下,当您使用 Android Studio 创建新模块时,IDE 会创建 <module-dir>/proguard-rules.pro,以便您添加自己的规则。

说明

您可以添加其他配置,R8 会在编译时应用这些配置。如果您将 minifyEnabled 属性设为 true,R8 会将来自上述所有可用来源的规则组合在一起,但是需要注意依赖库引入导致的规则冲突问题

如果需要输出 R8 在构建项目时应用的所有规则的完整报告:可以添加下面语句到proguard-rules.pro中

javascript
复制代码
// You can specify any path and filename.
-printconfiguration ~/tmp/full-r8-config.txt

如果需要添加额外的proguad文件:可以通过将相应文件添加到模块的 build.gradle 文件的 proguardFiles 属性中:

如分别给每个productflavor添加规则可以使用下面这种方式:

java
复制代码
android {...buildTypes {release {minifyEnabled trueproguardFilesgetDefaultProguardFile('proguard-android-optimize.txt'),// List additional ProGuard rules for the given build type here. By default,// Android Studio creates and includes an empty rules file for you (located// at the root directory of each module).'proguard-rules.pro'}}flavorDimensions "version"productFlavors {flavor1 {...}flavor2 {proguardFile 'flavor2-rules.pro'}}
}
2.资源缩减

资源缩减是在代码缩减之后进行的,只有去除了不需要的代码后, 才可以知道哪些代码里面的资源也是不被引入,可以移除的。

资源缩减只要在模块gradle下面添加shrinkResources属性即可:

arduino
复制代码
android {...buildTypes {release {shrinkResources trueminifyEnabled true...}}
}

注意:资源缩减需要提前开启代码缩减minifyEnabled

当然你也可以对资源文件添加白名单

xml
复制代码
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"tools:discard="@layout/unused2" />

使用tools:keep指定需要保留的资源文件,使用tools:discard指定可以舍弃的资源文件

3.代码混淆

混淆指的是将类名,方法名,属性名使用无意义的字符来表示:看下图:

image-20230424134309753

如何进行混淆?

混淆的一些基本规则

  • 一颗星:表示保留当前包下的类名,如果有子包,子包中的类会被混淆
kotlin
复制代码
-keep class cn.hadcn.test.*
  • 两颗星:表示保留当前包下的类名,如果有子包,子包中的类名也会被保留。
kotlin
复制代码
-keep class cn.hadcn.test.**
  • 上面的方式虽然保留了类名,但是内容还是会被混淆,使用下面方式保留内容
kotlin
复制代码
-keep class cn.hadcn.test.* {*;}
  • 在此基础上,我们也可以使用Java的基本规则来保护特定类不被混淆,比如我们可以用extends,implements等这些Java规则。如下例子就避免所有继承Activity的类被混淆:
scala
复制代码
-keep public class * extends android.app.Activity
  • 如果我们要保留一个类中的内部类不被混淆则需要用$符号,如下例子表示保持ScriptFragment内部类JavaScriptInterface中的所有public内容不被混淆。
kotlin
复制代码
-keepclassmembers class cc.ninty.chat.ui.fragment.ScriptFragment$JavaScriptInterface {public *;
}
  • 再者,如果一个类中你不希望保持全部内容不被混淆,而只是希望保护类下的特定内容,就可以使用:
csharp
复制代码
<init>;     //匹配所有构造器
<fields>;   //匹配所有域
<methods>;  //匹配所有方法方法
  • 你还可以在或前面加上private 、public、native等来进一步指定不被混淆的内容,如
kotlin
复制代码
-keep class cn.hadcn.test.One {public <methods>;
}
  • 当然你还可以加入参数,比如以下表示用JSONObject作为入参的构造函数不会被混淆:
kotlin
复制代码
-keep class cn.hadcn.test.One {public <init>(org.json.JSONObject);
}
  • 有时候你是不是还想着:我不需要保持类名,我只需要把该类下的特定方法保持不被混淆就好,那你就不能用keep方法了,keep方法会保持类名,而需要用keepclassmembers ,如此类名就不会被保持,为了便于对这些规则进行理解,官网给出了以下表格:

android打包混淆及语法规则详解_android

bash
复制代码
# -keep关键字
# keep:包留类和类中的成员,防止他们被混淆
# keepnames:保留类和类中的成员防止被混淆,但成员如果没有被引用将被删除
# keepclassmembers :只保留类中的成员,防止被混淆和移除。
# keepclassmembernames:只保留类中的成员,但如果成员没有被引用将被删除。
# keepclasseswithmembers:如果当前类中包含指定的方法,则保留类和类成员,否则将被混淆。
# keepclasseswithmembernames:如果当前类中包含指定的方法,则保留类和类成员,如果类成员没有被引用,则会被移除。
注意事项
  • 1.使用AS4.1.1版本进行混淆编译后,在 /build/outputs/mapping/release/下面会生成以下四个文件:

    • configuration:所有ProGuard文件整合后的规则文件:
    • mapping:混淆前后的映射文件,这个文件在使用反混淆的时候有用。
    • seeds:未进行混淆的类和成员。
    • usage:未使用的文件,也就是移除后的文件。

      image-20230424143702751

  • 2.有使用jni的情况下,jni方法不可混淆
arduino
复制代码
-keepclasseswithmembernames class * {    native <methods>;
}
  • 3.反射用到的类不混淆。
  • 4.AndroidMainfest中的类不混淆,所有四大组件和Application的子类和Framework层下所有的类默认不会进行混淆,自定义的View默认也不会被混淆。所以像网上贴的很多排除自定义View,或四大组件被混淆的规则在Android Studio中是无需加入的。
  • 5.与服务端交互时,使用GSON、fastjson等框架解析服务端数据时,所写的JSON对象类不混淆,否则无法将JSON解析成对应的对象;
  • 6.使用第三方开源库或者引用其他第三方的SDK包时,如果有特别要求,也需要在混淆文件中加入对应的混淆规则;
  • 7.有用到WebView的JS调用也需要保证写的接口方法不混淆,原因和第一条一样;
  • 8.Parcelable的子类和Creator静态成员变量不混淆,否则会产生Android.os.BadParcelableException异常;
php
复制代码
# 保持Parcelable不被混淆    
-keep class * implements Android.os.Parcelable {         public static final Android.os.Parcelable$Creator *;
}
  • 9.使用enum类型时需要注意避免以下两个方法混淆,因为enum类的特殊性,以下两个方法会被反射调用,见第二条规则。
arduino
复制代码
-keepclassmembers enum * {  public static **[] values();  public static ** valueOf(java.lang.String);  
}
混淆模板

下面是一个混淆模板:可根据自身需要进行添加和删除

scala
复制代码
#--------------------------1.实体类---------------------------------
# 如果使用了Gson之类的工具要使被它解析的JavaBean类即实体类不被混淆。(这里填写自己项目中存放bean对象的具体路径)
-keep class com.php.soldout.bean.**{*;}
​
#--------------------------2.第三方包-------------------------------
​
#Gson
-keepattributes Signature
-keepattributes *Annotation*
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }
-keep class com.google.gson.examples.android.model.** { *; }
-keep class com.google.gson.* { *;}
-dontwarn com.google.gson.**
​
#butterknife
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
​
#-------------------------3.与js互相调用的类------------------------
​
​
#-------------------------4.反射相关的类和方法----------------------
​
​
#-------------------------5.基本不用动区域--------------------------
#指定代码的压缩级别
-optimizationpasses 5
​
#包明不混合大小写
-dontusemixedcaseclassnames
​
#不去忽略非公共的库类
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
​
#混淆时是否记录日志
-verbose
​
#优化  不优化输入的类文件
-dontoptimize
​
#预校验
-dontpreverify
​
# 保留sdk系统自带的一些内容 【例如:-keepattributes *Annotation* 会保留Activity的被@override注释的onCreate、onDestroy方法等】
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
​
# 记录生成的日志数据,gradle build时在本项根目录输出
# apk 包内所有 class 的内部结构
-dump proguard/class_files.txt
# 未混淆的类和成员
-printseeds proguard/seeds.txt
# 列出从 apk 中删除的代码
-printusage proguard/unused.txt
# 混淆前后的映射
-printmapping proguard/mapping.txt
​
​
# 避免混淆泛型
-keepattributes Signature
# 抛出异常时保留代码行号,保持源文件以及行号
-keepattributes SourceFile,LineNumberTable
​
#-----------------------------6.默认保留区-----------------------
# 保持 native 方法不被混淆
-keepclasseswithmembernames class * {native <methods>;
}
​
-keepclassmembers public class * extends android.view.View {public <init>(android.content.Context);public <init>(android.content.Context, android.util.AttributeSet);public <init>(android.content.Context, android.util.AttributeSet, int);public void set*(***);
}
​
#保持 Serializable 不被混淆
-keepclassmembers class * implements java.io.Serializable {static final long serialVersionUID;private static final java.io.ObjectStreamField[] serialPersistentFields;!static !transient <fields>;!private <fields>;!private <methods>;private void writeObject(java.io.ObjectOutputStream);private void readObject(java.io.ObjectInputStream);java.lang.Object writeReplace();java.lang.Object readResolve();
}
​
# 保持自定义控件类不被混淆
-keepclasseswithmembers class * {public <init>(android.content.Context,android.util.AttributeSet);
}
# 保持自定义控件类不被混淆
-keepclasseswithmembers class * {public <init>(android.content.Context,android.util.AttributeSet,int);
}
# 保持自定义控件类不被混淆
-keepclassmembers class * extends android.app.Activity {public void *(android.view.View);
}
​
# 保持枚举 enum 类不被混淆
-keepclassmembers enum * {public static **[] values();public static ** valueOf(java.lang.String);
}
​
# 保持 Parcelable 不被混淆
-keep class * implements android.os.Parcelable {public static final android.os.Parcelable$Creator *;
}
​
# 不混淆R文件中的所有静态字段,我们都知道R文件是通过字段来记录每个资源的id的,字段名要是被混淆了,id也就找不着了。
-keepclassmembers class **.R$* {public static <fields>;
}
​
#如果引用了v4或者v7包
-dontwarn android.support.**
​
# 保持哪些类不被混淆
-keep public class * extends android.app.Appliction
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Fragment
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.preference.Preference
​
-keep class com.zhy.http.okhttp.**{*;}
-keep class com.wiwide.util.** {*;}
​
# ============忽略警告,否则打包可能会不成功=============
-ignorewarnings
4.代码优化

为了进一步缩减应用,R8 会在更深的层次上检查代码,以移除更多不使用的代码,或者在可能的情况下重写代码,以使其更简洁。下面是此类优化的几个示例:

  • 如果您的代码从未采用过给定 if/else 语句的 else {} 分支,R8 可能会移除 else {} 分支的代码
  • 如果您的代码只在一个位置调用某个方法,R8 可能会移除该方法并将其内嵌在这一个调用点
  • 如果 R8 确定某个类只有一个唯一子类且该类本身未实例化(例如,一个仅由一个具体实现类使用的抽象基类),它就可以将这两个类组合在一起并从应用中移除一个类。

更多优化点可以查看:Jake Wharton 写的关于 R8 优化的博文。

总结

本篇文章主要讲解了关于R8编译器在整个编译过程中对apk代码以及资源的一些优化操作,主要集中在代码缩减,资源缩减,代码混淆,代码优化这几部分,其中对代码混淆做了一个比较全面的分析,后期还会讲解一些关于代码反混淆的知识,这篇文章就讲到这里了,我是小余,我们下期见。

作者:小余的自习室
链接:https://juejin.cn/post/7225511164120891453
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

相关文章:

Android学习之路(27) ProGuard,混淆,R8优化

前言 使用java编写的源代码编译后生成了对于的class文件&#xff0c;但是class文件是一个非常标准的文件&#xff0c;市面上很多软件都可以对class文件进行反编译&#xff0c;为了我们app的安全性&#xff0c;就需要使用到Android代码混淆这一功能。 针对 Java 的混淆&#x…...

进程中线程使用率偏高问题排查

1. top命令查看CPU使用率高的进程 2. top -H -p 15931(进程PID) 查看进程下的线程 3. printf "%x\n" 17503(线程PID) 线程PID 10进制转16进制 0x445f 4. jstack -l 15931(JVM进程PID) 导出java进程栈信息&#xff0c;里面包含线程nid0x445f和所在的类&#xff0…...

【JavaEE进阶】 图书管理系统开发日记——肆

文章目录 &#x1f343;前言&#x1f38d;约定前后端交互接⼝&#x1f340;服务器代码实现&#x1f6a9;控制层&#x1f6a9;业务层&#x1f6a9;数据层 &#x1f334;前端代码的修改⭕总结 &#x1f343;前言 今天我们来实现修改图书模块 首先我们先来看一下&#xff0c;需要…...

STM32--USART串口(1)串口协议

一、通信接口 全双工&#xff1a;通信双方能够同时进行双向通信&#xff1b; 半双工&#xff1a;通信双方能够进行双向通信&#xff0c;但不能同时通信&#xff1b; 单工&#xff1a;只能从一个设备到另一个设备&#xff1b; 同步&#xff1a;接收方可以在时钟信号的指引下进…...

单臂路由实验(华为)

思科设备参考&#xff1a; 单臂路由实验&#xff08;思科&#xff09; 一&#xff0c;实验目的 在路由器的一个接口上通过配置子接口的方式&#xff0c;实现相互隔离的不同vlan之间互通。 ​ 二&#xff0c;设备配置 Switch1 <Huawei>sys [Huawei]vlan batch 10 20…...

websocket编写聊天室

【黑马程序员】WebSocket打造在线聊天室【配套资料源码】 总时长 02:45:00 共6P 此文章包含第1p-第p6的内容 简介 温馨提示&#xff1a;现在都是第三方支持聊天&#xff0c;如极光&#xff0c;学这个用于自己项目完全没问题&#xff0c;大项目不建议使用 需求分析 代码...

【论文解读】Collaboration Helps Camera Overtake LiDAR in 3D Detection

CoCa3D 摘要引言Collaborative Camera-Only 3D DetectionCollaborative depth estimationCollaborative detection feature learning 实验结论和局限 摘要 与基于 LiDAR 的检测系统相比&#xff0c;仅相机 3D 检测提供了一种经济的解决方案&#xff0c;具有简单的配置来定位 3…...

【Python实战】Python多线程批量采集图片

前言 本文来介绍如何多线程采集图片&#xff0c;多线程效率更快&#xff0c;但是&#xff0c;我们单一IP请求过于频繁&#xff0c;可能会被反爬&#xff0c;被封IP&#xff0c;所以&#xff0c;我们就要用到IP代理池&#xff0c;这里&#xff0c;我给大家推荐一个&#xff0c;可…...

【JavaEE spring】SpringBoot 统一功能处理

SpringBoot 统一功能处理 1. 拦截器1.1 拦截器快速⼊⻔1.2 拦截器详解1.2.1 拦截路径1.2.2 拦截器执⾏流程 1.3 登录校验1.3.1 定义拦截器1.3.2 注册配置拦截器 2. 统⼀数据返回格式2.1 快速⼊⻔2.2 存在问题2.3 案例代码修改2.4 优点 3. 统⼀异常处理 1. 拦截器 后端程序根据…...

小猪o2o生活通系统更新到了v24.1版本了php文件开源了提供VUE了但是车牌识别功能你真得会用吗

一.车牌识别设置项 车牌识别设置项总开关&#xff1a;系统后台-社区管理-社区配置-车牌识别配置。 平台需要开启车牌识别功能&#xff0c;其次平台可以选择车牌识别功能是由平台配置还是小区自己配置有需要提供代码的可以Q我昵称注明&#xff1a;CSDN网友。如果是平台自己配置&…...

Servlet+Ajax实现对数据的列表展示(极简入门)

目录 1.准备工作 1.数据库源&#xff08;这里以Mysql为例&#xff09; 2.映射实体类 3.模拟三层架构&#xff08;Dao、Service、Controller&#xff09; Dao接口 Dao实现 Service实现&#xff08;这里省略Service接口&#xff09; Controller层&#xff08;或叫Servlet层…...

汽车租赁系统

目录 一.研究背景 二.系统架构 1、SSM 2、JAVA 3、MySQL 4、系统架构 三.系统功能 1、车辆管理 2、客户管理 3、销售管理 4、统计分析 四.系统实现 五.结论总结 一.研究背景 传统的销售与信息统计管理都主要依靠人工&#xff0c;处理出的销售数据量与使用管理系统…...

随笔:回家过年

每一年的年底&#xff0c;伴随着气温的降低&#xff0c;大家开始逐渐增加了返乡的热情。风雪、堵车阻挡不住从各大一线城市归家的思绪。 这种年底大迁徙是中国人对家的执着。有钱没钱回家过年。随着年龄的增加&#xff0c;回家其实是只是做回孩子。脱下了城市里的正装&#xff…...

代理模式(静态代理、JDK 动态代理、CGLIB 动态代理)

代理模式(静态代理、JDK 动态代理、CGLIB 动态代理) 一、代理模式概述1. 生活中的代理案例2. 为什么要使用代理3. 代理模式在 Java 中的应用4. 概述5. 生活中代理图示二、代理的实现方式1. Java 中代理图示2. 静态代理2.1 案例2.2 实现案例2.3 静态代理存在的问题三、动态代理…...

【nginx实战】通过nginx实现http 长连接(即keep alive)

文章目录 一. http的长连接历史1. HTTP短连接模型2. HTTP长连接模型 二. nginx作为代理时实现HTTP长连接1. nginx与client的长连接1.1. keepalive_timeout指令1.2. keepalive_requests指令* 场景分析 2. 保持和server的长连接2.1. location设置* 场景分析 2.2. upstream设置* 场…...

通用函数

目录 处理null 多数值判断 Oracle从入门到总裁:https://blog.csdn.net/weixin_67859959/article/details/135209645 Oracle 提供了两个简单的数据处理函数&#xff1a; nvl()、decode()。在版本升级的过程中&#xff0c;这两个函数又衍生出了许多子函数 处理null 下面首先…...

Linux 查看系统信息 + 服务信息命令(简记)

概述 作用&#xff1a;Linux 运维工作中常用的命令速查 小步教程 (xiaobuteach.com) Linux 命令大全 | 菜鸟教程 (runoob.com) 文本编辑器vim 本章大纲 | 小步教程 vim 多文件编辑 | 小步教程 常用 ps 查看服务启动命令 Linux ps 命令 | 菜鸟教程 (runoob.com) # 查找…...

有了Future为什么还要CompletableFuture?

文章目录 Future 接口理论知识复习Future 接口概述场景描述小结 Future 接口常用实现类 FutureTask 异步任务Future 的作用Futrue 编码测试优缺点分析优点缺点小结 面对一些复杂的任务对于简单的业务场景使用 Future 接口完全 OK回调通知创建异步任务多个任务前后依赖可以组合对…...

Android super.img解包和打包指南(含工具下载lpunpack、lpmake、lpdump)

本文所有命令均需要在linux 上执行 一、解包 1、将Android sparse image格式的super.img转成二进制文件 $ sudo apt install android-sdk-libsparse-utils $ simg2img super.img super.img.bin 2、下载工具lpunpack 和lpmake、lpdump 以及其依赖库 下载地址:https://downl…...

端到端实现高精地图重建(TopoNet解读和横评)

论文出处 [2304.05277] Graph-based Topology Reasoning for Driving Scenes (arxiv.org)https://arxiv.org/abs/2304.05277 TopoNet TopoNet的目标是从车辆上安装的多视角摄像头获取图像&#xff0c;感知实体并推理出驾驶场景的拓扑关系&#xff0c;实现端到端预测&#xf…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

深度学习习题2

1.如果增加神经网络的宽度&#xff0c;精确度会增加到一个特定阈值后&#xff0c;便开始降低。造成这一现象的可能原因是什么&#xff1f; A、即使增加卷积核的数量&#xff0c;只有少部分的核会被用作预测 B、当卷积核数量增加时&#xff0c;神经网络的预测能力会降低 C、当卷…...

高防服务器价格高原因分析

高防服务器的价格较高&#xff0c;主要是由于其特殊的防御机制、硬件配置、运营维护等多方面的综合成本。以下从技术、资源和服务三个维度详细解析高防服务器昂贵的原因&#xff1a; 一、硬件与技术投入 大带宽需求 DDoS攻击通过占用大量带宽资源瘫痪目标服务器&#xff0c;因此…...

多元隐函数 偏导公式

我们来推导隐函数 z z ( x , y ) z z(x, y) zz(x,y) 的偏导公式&#xff0c;给定一个隐函数关系&#xff1a; F ( x , y , z ( x , y ) ) 0 F(x, y, z(x, y)) 0 F(x,y,z(x,y))0 &#x1f9e0; 目标&#xff1a; 求 ∂ z ∂ x \frac{\partial z}{\partial x} ∂x∂z​、 …...

数据库——redis

一、Redis 介绍 1. 概述 Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的、高性能的内存键值数据库系统&#xff0c;具有以下核心特点&#xff1a; 内存存储架构&#xff1a;数据主要存储在内存中&#xff0c;提供微秒级的读写响应 多数据结构支持&…...

OPENCV图形计算面积、弧长API讲解(1)

一.OPENCV图形面积、弧长计算的API介绍 之前我们已经把图形轮廓的检测、画框等功能讲解了一遍。那今天我们主要结合轮廓检测的API去计算图形的面积&#xff0c;这些面积可以是矩形、圆形等等。图形面积计算和弧长计算常用于车辆识别、桥梁识别等重要功能&#xff0c;常用的API…...

el-amap-bezier-curve运用及线弧度设置

文章目录 简介示例线弧度属性主要弧度相关属性其他相关样式属性完整示例链接简介 ‌el-amap-bezier-curve 是 Vue-Amap 组件库中的一个组件,用于在 高德地图 上绘制贝塞尔曲线。‌ 基本用法属性path定义曲线的路径,可以是多个弧线段的组合。stroke-weight线条的宽度。stroke…...