安卓JNI基础知识
JNI基础知识
- JNI简介
- NDK
- 配置开发环境
- JNI实践
- 配置CMake
- JNI编码
- JNI注册
- 1.静态注册
- 2.动态注册
- 编译方式
- CMakeLists编译
- Makefile编译
- 命令编译
- JNI和C/C++代码分离
- Java调用C/C++
- 查看so中包含的方法
- C/C++调用Java
- 打印C/C++的log
- 生成多个共享库so
- JNI调试
本文整理了JNI技术基础知识
JNI简介
JNI 是java原生接口(Java Native Interface),它定义了 Android 从受管理代码(使用 Java 或 Kotlin 编程语言编写)编译的字节码与原生代码(使用 C/C++ 编写)进行交互的方法,也就是安卓通过JNI技术提供Java调用C/C++或者C/C++调用Java的能力。JNI 不依赖于供应商,支持从动态共享库加载代码,虽然有时较为繁琐,但效率较高。

NDK
Android NDK(Native Development Kit),原生开发工具包,它是一组能将C或C++(“原生代码”)嵌入到Android 应用中的工具。可以帮助开发者快速开发C/C+的动态库,自动将so和java应用一起打包成apk。
NDK集成了一些交叉编译器,并提供了相应的mk文件,用于隔离CPU、平台、ABI等差异,开发人员通过配置mk文件(指出“哪些文件需要编译”、“编译特性要求”等),就可以生成自己的so库。
原生共享库:NDK 从 C/C++ 源代码构建这些库或 .so 文件。so是shared object的缩写。
原生静态库:NDK 也可构建静态库或 .a 文件,而您可将静态库关联到其他库。
配置开发环境
- 下载NDK
File>Settings>Android SDK>SDK Tools>勾选需要的版本号>apply>OK - 配置项目NDK

如果NDK location无法编辑输入,可以在local.properties中新增ndk.dir进行设置:
较新的项目,直接在app\build.gradle中直接配置ndk版本号即可。sdk.dir=D\:\\win10_program\\develop\\Android\\AndroidSDK ndk.dir=D\:\\win10_program\\develop\\Android\\AndroidSDK\\ndk\\26.1.10909125 // 已经过时的用法,可以直接删除此行配置,具体参考下面的操作。
命令查看ndk版本号:android {namespace 'com.xxx.xxx'compileSdk 33ndkVersion "25.2.9519653"... }ndk-build --version
JNI实践
这里使用官方例子介绍。
配置CMake
配置CMake的目的是:告诉CMake改如何从源码编译生成目标库。
# 需要生成的目标库native-lib
# 也可以使用add_executable()生成可执行文件
add_library( # 指定要生成的目标库名称为native-libnative-lib# 将native-lib库设置默认为SHARED(原生共享库.so)或STATIC(原生静态库.a)SHARED# 生成native-lib库所需源码的相对路径列表。包含.cpp和.hsrc/main/cpp/native-lib.cppNativeImpl.cpp) # NativeImpl.cpp在后面代码分离部分实现# 指定源文件关联的头文件(适用于头文件和源文件分离的情况,但是也可以不写,因为.cpp中已经include了)
include_directories(src/main/cpp/include/)# 在已有库中查找需要的库,并将它的路径存储在变量xxx-lib中。类似用法的函数
# find_file()、find_path()、find_program()、find_package()
find_library( # 自定义变量的名称xxx-libxxx-lib#在ndk开发包中查找需要的libyyy.so,存储到xxx-lib变量中yyy ) # 将依赖的库文件链接到此目标库上
target_link_libraries(# 指定目标库native-lib# 将下面的库列表全部连接到目标库上${xxx-lib} # 获取find_library找到的yyy库android # 获取android库log) # 获取log库
注意:
1、如果对库文件有修改变动,请务必在Gradle之前清理一下项目 Build > Clean Project。
2、如果需要生成多个共享库,可以在CMakeLists.txt文件中增加多个成对的add_library和target_link_libraries函数。
JNI编码
- 在Java侧声明调用方法。如
stringFromJNI
// 应用启动时,调用此函数会加载原生共享文件sodemo.sostatic {System.loadLibrary("sodemo"); //官方推荐使用:ReLinker.loadLibrary}/*** 声明此方法在原生端(共享文件sodemo.so)中实现,它与该应用程序打包在一起。*/public native String stringFromJNI();
- 在C侧实现具体方法
Java_com_wingtech_sodemo_JNIUtils_stringFromJNI
#include <jni.h>
#include <string>extern "C" JNIEXPORT jstring JNICALL
Java_com_wingtech_sodemo_JNIUtils_stringFromJNI(JNIEnv *env, jobject thiz) {std::string hello = "Hello from C++";return env->NewStringUTF(hello.c_str());
}
方法名称:Java_包名_类名_方法名
方法参数:JNIEnv* 是指向虚拟机环境的指针。jobject 是指向从 Java 端传递的隐式 this 对象的指针。
重要:C/C++和Java通过此方法名称建立了一对一映射关系。
JNI注册
1.静态注册
如果只有一个类具有原生方法,建议使用静态注册。使用标准 System.loadLibrary 从共享库加载原生代码。
从静态类初始化程序中调用 System.loadLibrary(或 ReLinker.loadLibrary)。具体静态注册同前面JNI编码部分所述。
2.动态注册
如果有多个类有原生方法,可以使用RegisterNatives注册,也可以让运行时使用dlsym动态查找它们。可以从 Application进行调用,这样始终加载该库,而且总是会提前加载。当执行到System.loadLibrary()函数时,会回调JNI组件中的JNI_OnLoad()函数;当释放该组件时会回调JNI_OnUnload()函数。
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {JNIEnv* env;// 通过调用了GetEnv函数获取JNIEnv结构体指针env(JNI环境变量),JNIEnv结构体是指向一个函数表的,// 该函数表又指向了一些列对应的JNI函数。所以可以通过env和java交互,如GetObjectClass,CallVoidMethod等if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {return JNI_ERR;}// Find your class. JNI_OnLoad is called from the correct class loader context for this to work.jclass c = env->FindClass("com/example/app/package/MyClass");if (c == nullptr) return JNI_ERR;// 将所有方法装进数组中。这里数组中每个元素是结构体JNINativeMethod。// typedef struct {// const char* name;//Java层native方法的名字// const char* signature;//Java层native方法的描述符// void* fnPtr;//对应JNI函数的指针// } JNINativeMethod;static const JNINativeMethod methods[] = {{"nativeFoo", "()V", reinterpret_cast<void*>(nativeFoo)},{"nativeBar", "(Ljava/lang/String;I)Z", reinterpret_cast<void*>(nativeBar)},};// 使用RegisterNatives注册所有原生方法int rc = env->RegisterNatives(c, methods, sizeof(methods)/sizeof(JNINativeMethod));if (rc != JNI_OK) return rc;return JNI_VERSION_1_6;
}
jni函数的指针
void regist(JNIEnv *env, jobject thiz, jobject jCallback) {
LOGD(“–动态注册调用成功–>”);
jstring pJstring = env->NewStringUTF(“动态注册调用成功”);
jclass pJclass = env->GetObjectClass(thiz);
jmethodID id = env->GetMethodID(pJclass, “beInjectedDebug”, “(Ljava/lang/String;)V”);
//执行函数
env->CallVoidMethod(thiz,id,pJstring);
}
编译方式
一般有两种编译方式:
- 1、CMakeLists编译
- 2、Makefile编译
- 3、命令编译
CMakeLists编译
1、CMakeLists配置
具体配置如前面配置CMake的介绍,这里使用cpp目录下的CMakeLists.txt、native-lib.cpp文件生成.so库。

2、gradle配置
在app\build.gradle中设置库文件适配的CPU架构类型和CMakeLists.txt 文件路径。
android {namespace 'com.xxx.sodemo'compileSdk 33defaultConfig {applicationId "com.xxx.sodemo"minSdk 31targetSdk 33versionCode 1versionName "1.0"testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"ndk {// 生成so库类型abiFilters 'armeabi-v7a', 'arm64-v8a','x86','x86_64'}}externalNativeBuild {cmake {// 设置CMakeLists.txt文件路径path file('src/main/cpp/CMakeLists.txt')version '3.22.1'}}...}
3、编译库文件
点击Make按钮或Build->Make Project,运行结束后,会在 根目录/app/build/intermediates/cmake/debug/obj 路径下生成对应平台的.so库文件。
Makefile编译
使用MK文件编译,不需要编辑CMakeLists.txt,也不需要在build.gradle中配置,只要在Android.mk和Application.mk文件中配置好即可。一般在C/C++同目录下创建mk文件。
1、编写Android.mk文件
#设置当前编译路径为当前文件夹路径
LOCAL_PATH :=$(call my-dir)#清空编译环境的变量(由其他模块设置过的变量)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -lm -llog#指定生成模块的名称(库引用名称),编译时会自动添加lib前缀
LOCAL_MODULE :=JNITest123#需要编译的源文件。如果存在多个.cpp文件时使用"\"隔开
LOCAL_SRC_FILES :=native-lib.cpp \NativeImpl.cpp # NativeImpl.cpp在后面代码分离部分实现#生成动态库
include $(BUILD_SHARED_LIBRARY)
2、编写Application.mk文件
#模块名字,与Android.mk中保持一致
APP_MODULES := JNITest123#支持平台,这里支持所有平台
APP_ABI := all
APP_ALLOW_MISSING_DEPS=true
3、编译库文件
方式一:
1)检查编译环境
打开cmd窗口,运行ndk-build --version,如下输出,说明ndk配置正确。

2)在cmd中进入C/C++文件所在目录下,执行ndk-build命令编译。
NDK_PROJECT_PATH=. # 当前项目
APP_PLATFORM=android-16 # 有默认值,可以不设置
APP_BUILD_SCRIPT=./Android.mk # 当前目录下的Android.mk文件。注意:这里根据实际情况修改路径
NDK_APPLICATION_MK=./Application.mk # 当前目录下的Application.mk文件。注意:这里根据实际情况修改路径
NDK_LOG=1 # 打印编译日志
整理成一行命令执行:
ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk NDK_APPLICATION_MK=./Application.mk NDK_LOG=1
3)执行结果:

说明:在哪个目录下执行ndk-build命令编译,就在此目录下生成库文件。
E:\work\Test\Andriod\SoDemo\app\src\main>ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./cpp/Android.mk NDK_APPLICATION_MK=./cpp/Application.mk APP_PLATFORM=android-16
Android NDK: WARNING: APP_PLATFORM android-16 is higher than android:minSdkVersion 1 in ./AndroidManifest.xml. NDK binaries will *not* be compatible with devices older than android-16. See https://android.googlesource.com/platform/ndk/+/master/docs/user/common_problems.md for more information.
[arm64-v8a] Compile++ : JNITest123 <= native-lib.cpp
[arm64-v8a] SharedLibrary : libJNITest123.so
[arm64-v8a] Install : libJNITest123.so => libs/arm64-v8a/libJNITest123.so
[x86_64] Compile++ : JNITest123 <= native-lib.cpp
[x86_64] SharedLibrary : libJNITest123.so
[x86_64] Install : libJNITest123.so => libs/x86_64/libJNITest123.so
[armeabi-v7a] Compile++ thumb: JNITest123 <= native-lib.cpp
[armeabi-v7a] SharedLibrary : libJNITest123.so
[armeabi-v7a] Install : libJNITest123.so => libs/armeabi-v7a/libJNITest123.so
[x86] Compile++ : JNITest123 <= native-lib.cpp
[x86] SharedLibrary : libJNITest123.so
[x86] Install : libJNITest123.so => libs/x86/libJNITest123.so
方式二:在Android Studio中,打开终端Terminal,cd进入C/C++文件所在目录的父目录下,执行ndk-build.cmd即可。只要代码没有问题,一般可以在同级目录下生成文件。
PS E:\work\Test\Andriod\SoDemo\app\src\main> D:\win10_program\develop\Android\AndroidSDK\ndk\26.1.10909125\ndk-build.cmd
Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-21.
[arm64-v8a] SharedLibrary : libJNITest123.so
[arm64-v8a] Install : libJNITest123.so => libs/arm64-v8a/libJNITest123.so
[x86_64] Compile++ : JNITest123 <= native-lib.cpp
[x86_64] SharedLibrary : libJNITest123.so
[x86_64] Install : libJNITest123.so => libs/x86_64/libJNITest123.so
[armeabi-v7a] Compile++ thumb: JNITest123 <= native-lib.cpp
[armeabi-v7a] SharedLibrary : libJNITest123.so
[armeabi-v7a] Install : libJNITest123.so => libs/armeabi-v7a/libJNITest123.so
[x86] Compile++ : JNITest123 <= native-lib.cpp
[x86] SharedLibrary : libJNITest123.so
[x86] Install : libJNITest123.so => libs/x86/libJNITest123.so
常见问题:
E:\work\Test\Andriod\SoDemo\app\src\main> D:\win10_program\develop\Android\AndroidSDK\ndk\21.0.6113669\ndk-build.cmd
Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-16.
Android NDK: Your APP_BUILD_SCRIPT points to an unknown file:
D:\win10_program\develop\Android\AndroidSDK\ndk\21.0.6113669/jni/Android.mk // 这里是路径问题jni
D:/win10_program/develop/Android/AndroidSDK/ndk/21.0.6113669/build//../build/core/add-application.mk:88: *** Android NDK: Aborting... . Stop.
因为这里的mk文件实际在src\main\cpp中,而NDK编译环境默认在jni目录下找mk文件,所以报错无法找到。这里可以将文件名称cpp修改为默认路径jni,也可以在ndk-build命令里指定mk的路径,具体修改如下。
ndk-build.cmd APP_BUILD_SCRIPT=./cpp/Android.mk NDK_APPLICATION_MK=./cpp/Application.mk
PS E:\work\Test\Andriod\SoDemo\app\src\main> D:\win10_program\develop\Android\AndroidSDK\ndk\26.1.10909125\ndk-build.cmd APP_BUILD_SCRIPT=./cpp/Android.mk NDK_APPLICATION_MK=./cpp/Application.mk
Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-21.
[arm64-v8a] Compile++ : JNITest123 <= native-lib.cpp
[arm64-v8a] SharedLibrary : libJNITest123.so
...
命令编译
JNI和C/C++代码分离
分离设计目的是希望在JNI文件中出现少量的C++代码。
1、编写.cpp文件
这里以NativeImpl.cpp为例
#include <jni.h>
#include "NativeImpl.h"NativeImpl::NativeImpl() {}NativeImpl::~NativeImpl() {}int NativeImpl::Clear_Zero() {LOGD("打印C++ LOGD");LOGE("打印C++ LOGE");LOGI("打印C++ LOGI");LOGW("打印C++ LOGW");return 0;
}
2、编写.h文件
这里以NativeImpl.h为例
#ifndef SODEMO_NATIVEIMPL_H
#define SODEMO_NATIVEIMPL_H
#include "LOG.h"#include <vector>
class NativeImpl {public:NativeImpl();virtual ~NativeImpl();virtual int Clear_Zero();
};#endif //SODEMO_NATIVEIMPL_H
3、在JNI文件中调用C++方法。
#include <jni.h>
#include "NativeImpl.h"NativeImpl nativeImpl;
NativeImpl* getNativeImpl(){return &nativeImpl;
}extern "C"
JNIEXPORT jint JNICALL
Java_com_mytest_sodemo_JNIUtils_clrNumber(JNIEnv *env, jclass clazz) {// TODO: implement clrNumber()int zero = getNativeImpl()->Clear_Zero();return zero;
}
注意:代码分离后,需要将纯C++的源码添加到编译环境中,也就是在CMakeLists.txt的add_library方法中添加NativeImpl.cpp,或者在Android.mk的LOCAL_SRC_FILES中添加NativeImpl.cpp。具体参考上面的编译方式。
Java调用C/C++
Java调用C或C++程序,前提是给定了C或C++的动态库dll(Windows)或so(Linux)文件和函数头文件说明,这里介绍如何正确调用第三方so。
Java层调用C++函数主要通过建立的映射关系,这里jni函数调用java层的函数就要通过JNIEnv。
1、将第三方提供的so文件全部放进app\libs目录下,然后在app\build.gradle的sourceSets中配置libs,这样就会在打包时,自动把libs下的文件副本迁移到apk的lib目录下。
当然,这里的路径可以自定义,只要Gradle在打包时能通过你配置的路径,找到so的存放位置即可。
android {defaultConfig {...}sourceSets {main {jniLibs.srcDirs = ['libs'] // 打包时会把app\libs下的共享库.so的副本迁移到apk的lib目录下。// jniLibs.srcDirs = ['libs/test'] // 也可以在app\libs下新建各个公司或模块提供的库目录。// jniLibs.srcDirs = ['src/mylibs'] // 也可以自定义路径so的存储路径,只要能找到就行。}}...
}

2、根据已知的Java_xx包名_yy类名_方法名格式(也可以通过nm命令获取so库的方法),在自己的项目中app\src\main\java目录下新建xx包名,然后再创建一个和so中的yy类名相同的类,这里要确保包名、类名、方法名、库名(不带lib前缀)四者一致,最后在自己的项目中直接调用yy类中的方法即可。
extern "C" JNIEXPORT jstring JNICALL
Java_com_mytest_sodemo_JNIUtils_stringFromJNI(JNIEnv *env, jobject) {std::string hello = "Hello from C++";return env->NewStringUTF(hello.c_str());
}
注意:这一步非常重要,通过如此设计的方法名,建立了java和C之间的映射关系,所以在其他应用中使用时,也需要建立这种映射关系,否则报错UnsatisfiedLinkError。
//todo 缺图
3、清理和检查
清理后重新打包:Build>Clean Project>等一会儿>Make Project或者Build APK(s)>等一会儿。
检查so是否打入包内:Build>Analyze APK>OK>打开目标APK的lib目录。
4、常见异常
如果检查没有发现错误,编译运行后还是出现UnsatisfiedLinkError异常,多半是因为apk中的so没有打入包内,请按照第3步处理.
查看so中包含的方法
需要使用nm工具,一般在sdk\ndk\xx版本\toolchains\x86-4.9\prebuilt\windows-x86_64\i686-linux-android\bin
nm -D "so文件路径"
C/C++调用Java
打印C/C++的log
在CPP目录下新建head文件LOG.h
#ifndef SODEMO_LOG_H
#define SODEMO_LOG_H#include <android/log.h>#define TAG "haitao"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__);
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__);
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__);
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__);#endif //SODEMO_LOG_H
在需要使用的文件中#include "LOG.h"即可。
生成多个共享库so
如果需要生成多个共享库,可以在CMakeLists.txt再增加add_library和target_link_libraries
参考配置CMake
# 生成libtest-1.so
add_library(test-1SHAREDnative-lib.cpp)
target_link_libraries(test-2 android)
...# 生成libtest-2.so
add_library(test-2 SHAREDnative-lib.cpp)
target_link_libraries(test-2android)
JNI调试

在Debug模式下,有时候会出现这个Permission denied的提示。
解决方法:退出App重新debug运行。如果退出无法解决此问题,重新USB连接即可。
与君共勉:人生自当扶摇上,揽星衔月逐日光。你只管去劈浪,与众生争锋芒,你举步是八万里宽广,你眼望是千江拍白浪,你平生这一趟,要让旁人想都不敢想!
相关文章:
安卓JNI基础知识
JNI基础知识 JNI简介NDK配置开发环境JNI实践配置CMakeJNI编码JNI注册1.静态注册2.动态注册 编译方式CMakeLists编译Makefile编译命令编译 JNI和C/C代码分离Java调用C/C查看so中包含的方法 C/C调用Java打印C/C的log生成多个共享库soJNI调试 本文整理了JNI技术基础知识 JNI简介 …...
Nginx高级技巧:实现负载均衡和反向代理
文章目录 Nginx概述Nginx作用正向代理反向代理负载均衡动静分离 Nginx的安装 -->Docker3.1 安装Nginx3.2 Nginx的配置文件3.3 修改docker-compose文件 Nginx源码安装nginx常用命令nginx配置文件配置文件位置配置文件结构详情 Nginx的反向代理【重点】基于Nginx实现反向代理4…...
2024年2月最新微信域名检测拦截接口源码
这段PHP代码用于检测指定域名列表中的域名是否被封。代码首先定义了一个包含待检测域名的数组 $domainList,然后遍历该数组,对每个域名发送HTTP请求并检查响应内容以判断域名是否被封。 具体步骤如下: 1. 定义待检测的域名列表。 2. 遍历域名…...
1、Linux-安装
一、Linux和Windows的一些区别 1、Linux严格区分大小写——【Windows创建文件夹时不区分大小写】 2、Linux中所有内容都以文件形式存储,包括硬件 3、Linux不靠拓展名区分文件类型,而是可以通过读取文件开头的一些字节来区分。 但是在实际使用中一般要…...
flutter 父组件调用子组件方法
当子组件是有状态组件 声明GlobalKey 如 声明 GlobalKey formKey GlobalKey<FormState>(); Form( key: formKey, autovalidateMode: AutovalidateMode.always, child: Column( children: <Widget>[ TextFormField( autofocus: true, initialValue: "a&quo…...
京东云硬钢阿里云:承诺再低10%
关注卢松松,会经常给你分享一些我的经验和观点。 阿里云刚刚宣布史上最大规模的全线产品降价20%,这热度还没过,京东云当晚就喊话:“随便降、比到底!,全网比价,击穿低价,再低10%”,并…...
Phoncent博客:探索AI写作与编程的无限可能
Phoncent博客,一个名为Phoncent的创新AIGC博客网站,于2023年诞生。它的创始人是庄泽峰,一个自媒体人和个人站长,他在网络营销推广领域有着丰富的经验。庄泽峰深知人工智能技术在内容创作和编程领域的潜力和创造力,因此…...
【Go-Zero】测试API查询信息无法返回数据库信息与api、rpc文件编写规范
【Go-Zero】测试API查询信息无法返回数据库信息与api、rpc文件编写规范 大家好 我是寸铁👊 总结了一篇测试API查询信息无法返回数据库信息与api、rpc文件编写规范的文章✨ 喜欢的小伙伴可以点点关注 💝 问题背景 大家好,我是寸铁!…...
SpringBootWeb快速入门
1.创建springboot工程,新建module 2.勾选web开发相关依赖 3.删除多余文件 4.新建类 5.启动类中运行main方法 6.启动 默认端口号8080 7.打开浏览器,地址栏输入 8.报错 9.原因,控制层位置放错,剪切controller层放进com.example …...
【书生·浦语大模型实战营】第 2 节 -课后作业
第二节 -轻松玩转书生浦语大模型趣味 Demo-课后作业 0.课程体验0.1 鸡兔同笼0.2 逻辑推理0.3 AI会毁灭人类吗? 1.课后作业1.1 基础作业1.1.1 作业11.1.2 作业2 0.课程体验 课程链接:https://github.com/internLM/tutorial 首先,这个课程是免费…...
Java如何使用OpenCV
背景:利用OpenCV功能批量处理视频 OpenCV(Open Source Computer Vision Library)是一个广泛应用于计算机视觉和图像处理领域的开源库。它提供了丰富的功能和工具,可用于处理图像和视频数据,并在各种应用中发挥着重要作…...
C++指针(三)
个人主页:PingdiGuo_guo 收录专栏:C干货专栏 文章目录 前言 1.字符指针 1.1字符指针的概念 1.2字符指针的用处 1.3字符指针的操作 1.3.1定义 1.3.2初始化 1.4字符指针使用注意事项 2.数组参数,指针参数 2.1数组参数 2.1.1数组参数的概念 2.1…...
消息中间件之RocketMQ源码分析(二十七)
Broker提交或回滚事务消息 当生产者本地事务处理完成并且Broker回查事务消息后,不管执行Commit还是Rollback,都会根据用户本地事务的执行结果发送一个End_transaction的RPC请求给Broker,Broker端处理该请求的类是EndTransactionProcessor 第一步&…...
C习题002:澡堂洗澡
问题 输入样例 在这里给出一组输入。例如: 2 5 1 3 3 2 3 3 输出样例 在这里给出相应的输出。例如: No代码长度限制 16 KB 时间限制 400 ms 内存限制 64 MB 栈限制 8192 KB 代码 #include<stdio.h> int main() {int N,W,s,t,p;int arr_s[…...
智能双星:遥测终端机与柳林“巡检机器人“,助力智能运维新升级!
随着科技的不断发展,智能化、自动化的运维管理已经成为企业追求高效、稳定运营的重要方向。柳林遥测终端机、柳林e拍云平台以及巡检机器人的组合,为企业带来了一种全新的、前置的、无感的智能运维体验。 柳林遥测终端机,以其强大的数据采集和…...
算法复习之前缀和【备战蓝桥杯】
一维前缀和 S[i] a[1] a[2] ... a[i] a[l] ... a[r] S[r] - S[l - 1]二维前缀和 S[i, j] 第i行j列格子左上部分所有元素的和 以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵的和为: S[x2, y2] - S[x1 - 1, y2] - S[x2, y1 - 1] S[x1 - 1, y1 - …...
IDEA基础——Maven配置tomcat
配置方案 一、配置maven-tomcat plugin插件(只最高支持到tomcat 8)~~1.添加镜像源,获取tomcat 8插件配置~~~~1.1 在pom.xml里先添加镜像源~~~~1.2 添加tomcat插件配置~~ 2. 添加tomact官方发布的插件配置(无需添加镜像源ÿ…...
数据结构测试题
目录 1.闰年判断 2.志愿者选拔 3.单词接龙 4.对称二叉树 5.英雄南昌欢迎您 6.时间转换 7.矩阵乘法 8. Huffuman树 1.闰年判断 题目描述: 给定一个年份,判断这一年是不是闰年。 当以下情况之一满足时,这一年是闰年: 1. 年…...
【MATLAB】兔子机器人总系统_动力学模型解读(及simulink中的simscape的各模块介绍)
1、动力学模型 Rectangular Joint 控制平面上(x,y轴)的移动,去掉以后,机器人在原地翻滚不移动 Rigid Transform 坐标转换,B站视频已收藏 去掉,机体与地面贴合 此处的作用是设定机体的初…...
Launch学习
参考博客: (1) 史上最全的launch的解析来啦,木有之一欧 1 ROS工作空间简介 2 元功能包 src目录下可以包含多个功能包,假设需要使用机器人导航模块,但是这个模块中包含着地图、定位、路径规划等不同的功能包,它们的逻…...
【仅限SITS2026参会者解封】:AI微服务弹性扩缩容决策引擎设计手册(含动态负载预测模型Python实现+K8s HPA自定义指标CRD YAML)
第一章:SITS2026分享:AI原生微服务架构设计 2026奇点智能技术大会(https://ml-summit.org) 在SITS2026现场,来自全球头部AI基础设施团队的实践者共同提出“AI原生微服务”范式——它并非传统微服务的简单迁移,而是围绕模型生命周…...
算法与心智的双重反噬:为何亚马逊品牌延伸会“污染”搜索标签与用户预期
大众汽车的兴衰史,是品牌定位与延伸战略的经典悲剧,其在亚马逊的商业战场上有着精确的映射。一个品牌凭借极致聚焦的定位(如“微型车”)获得巨大成功,在消费者心智和平台算法中注册了清晰的“价值标签”;然…...
Fan Control:Windows风扇控制终极指南,告别噪音与高温烦恼![特殊字符]
Fan Control:Windows风扇控制终极指南,告别噪音与高温烦恼!🔥 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址…...
大模型面试通关秘籍:小白程序员必备的收藏级实战指南
本文分享了近期大模型应用开发的面经,覆盖阿里、腾讯等知名公司的面试内容和难度。文章指出,大模型面试题难度适中,重点考察微调原理及实践、RAG应用、Agent项目设计等。建议面试者准备充分,多看技术文章,注重项目效果…...
和AI一起搞事情#:边剥龙虾边做个中医技能来起号那
1. 核心概念 在 Antigravity 中,技能系统分为两层: Skills (全局库):实际的代码、脚本和指南,存储在系统级目录(如 ~/.gemini/antigravity/skills)。它们是“能力”的本体。 Workflows (项目级):…...
芯片互连的“速度革命”:铜互连为何能替代铝,成为高端芯片标配?
在芯片的内部结构中,除了负责运算、存储的晶体管,还有一套贯穿芯片全局的“信号传输网络”——芯片互连技术。它就像芯片内部的“高速公路网”,将亿万级晶体管精准连接,实现电信号的快速传输,支撑芯片的运算和存储功能…...
GHelper终极指南:华硕笔记本轻量级性能控制工具完全解析
GHelper终极指南:华硕笔记本轻量级性能控制工具完全解析 【免费下载链接】g-helper Lightweight, open-source control tool for ASUS laptops and ROG Ally. Manage performance modes, fans, GPU, battery, and RGB lighting across Zephyrus, Flow, TUF, Strix, …...
2026届必备的五大AI论文工具横评
Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 技术人工智能的发展速度飞快,论文AI类网站成了可辅助学术写作领域的重要工具&…...
3步解决Zotero PDF Translate翻译失效的终极指南:快速恢复学术研究工具
3步解决Zotero PDF Translate翻译失效的终极指南:快速恢复学术研究工具 【免费下载链接】zotero-pdf-translate Translate PDF, EPub, webpage, metadata, annotations, notes to the target language. Support 20 translate services. 项目地址: https://gitcode…...
Springboot 实现多数据源(PostgreSQL 和 SQL Server)连接堆
一、环境准备 Free Spire.Doc for Python 是免费 Python 文档处理库,无需依赖 Microsoft Word,支持 Word 文档的创建、编辑、转换等操作,其中内置的 Markdown 解析能力,能高效实现 Markdown 到 Doc/Docx 格式的转换,且…...
