ReactNative 启动应用(2)

ReactNative 启动应用

简述

本节我们来看一下ReactNative在Android上启动Activity的流程,ReactNative在Android上也是一个Apk,它的实现全部都在应用层,所以它肯定也是符合我们Android应用的启动流程的,UI页面的载体也是一个Activity,然后启动JS引擎来加载index.js,执行javascript的代码,然后javascript通过Fabric渲染器和TurboModule执行到java代码,调用到最终的Native实现,本节我们就来看一下启动的这个过程。

Application启动

1.1 MainApplication.init
ReactNative的能力被包装为Package,Package里面包含一些Module,每个Module是一个子能力,后续介绍TurboModule的时候会介绍包加载的流程。

class MainApplication : Application(), ReactApplication {// 主要就是构建了DefaultReactNativeHost和ReactHostoverride val reactNativeHost: ReactNativeHost =object : DefaultReactNativeHost(this) {override fun getPackages(): List<ReactPackage> =// 这里加载了所有包PackageList(this).packages.apply {// Packages that cannot be autolinked yet can be added manually here, for example:// add(MyReactNativePackage())}override fun getJSMainModuleName(): String = "index"override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUGoverride val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLEDoverride val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED}// 详见1.2override val reactHost: ReactHostget() = getDefaultReactHost(applicationContext, reactNativeHost)override fun onCreate() {super.onCreate()SoLoader.init(this, false)if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {load()}}
}

1.2 getDefaultReactHost
调用ReactNativeHost.toReactHost构造ReactHost。

@OptIn(UnstableReactNativeAPI::class)
@JvmStatic
public fun getDefaultReactHost(context: Context,reactNativeHost: ReactNativeHost,
): ReactHost {require(reactNativeHost is DefaultReactNativeHost) {"You can call getDefaultReactHost only with instances of DefaultReactNativeHost"}//详见1.3return reactNativeHost.toReactHost(context)
}

1.3 toReactHost
调用了getDefaultReactHost

@UnstableReactNativeAPI
internal fun toReactHost(context: Context): ReactHost =// 详见1.4DefaultReactHost.getDefaultReactHost(context,packages,jsMainModuleName,bundleAssetName ?: "index",isHermesEnabled ?: true,useDeveloperSupport,)

1.4 getDefaultReactHost
初始化了JS引擎,加载了js代码,还构建了DefaultReactHostDelegate,最终会把这些信息封装到一个ReactHostImpl中,ReactHost建立了React和Activity一些交互的接口。

@OptIn(UnstableReactNativeAPI::class)
@JvmStatic
public fun getDefaultReactHost(context: Context,packageList: List<ReactPackage>,jsMainModulePath: String = "index",jsBundleAssetPath: String = "index",isHermesEnabled: Boolean = true,useDevSupport: Boolean = ReactBuildConfig.DEBUG,cxxReactPackageProviders: List<(ReactContext) -> CxxReactPackage> = emptyList(),
): ReactHost {// 构建ReactHostImplif (reactHost == null) {// 创建jsBundleLoader,这个是用来执行JS代码的val jsBundleLoader =JSBundleLoader.createAssetLoader(context, "assets://$jsBundleAssetPath", true)// 创建JS引擎val jsRuntimeFactory = if (isHermesEnabled) HermesInstance() else JSCInstance()val defaultTmmDelegateBuilder = DefaultTurboModuleManagerDelegate.Builder()cxxReactPackageProviders.forEach { defaultTmmDelegateBuilder.addCxxReactPackage(it) }// 构建DefaultReactHostDelegateval defaultReactHostDelegate =DefaultReactHostDelegate(jsMainModulePath = jsMainModulePath,jsBundleLoader = jsBundleLoader,reactPackages = packageList,jsRuntimeFactory = jsRuntimeFactory,turboModuleManagerDelegateBuilder = defaultTmmDelegateBuilder)val componentFactory = ComponentFactory()DefaultComponentsRegistry.register(componentFactory)// 创建ReactHostImpl,详见1.5reactHost =ReactHostImpl(context,defaultReactHostDelegate,componentFactory,true /* allowPackagerServerAccess */,useDevSupport,).apply {jsEngineResolutionAlgorithm =if (isHermesEnabled) {JSEngineResolutionAlgorithm.HERMES} else {JSEngineResolutionAlgorithm.JSC}}}return reactHost as ReactHost
}

1.5 ReactHostImpl
构建了一个DevSupportManager。

public ReactHostImpl(Context context,ReactHostDelegate delegate,ComponentFactory componentFactory,Executor bgExecutor,Executor uiExecutor,boolean allowPackagerServerAccess,boolean useDevSupport) {mContext = context;mReactHostDelegate = delegate;mComponentFactory = componentFactory;mBGExecutor = bgExecutor;mUIExecutor = uiExecutor;mQueueThreadExceptionHandler = ReactHostImpl.this::handleHostException;mMemoryPressureRouter = new MemoryPressureRouter(context);mAllowPackagerServerAccess = allowPackagerServerAccess;mUseDevSupport = useDevSupport;// debug版本和release版本,分别构建不同的SupportManagerif (mUseDevSupport) {mDevSupportManager =new BridgelessDevSupportManager(ReactHostImpl.this, mContext, mReactHostDelegate.getJsMainModulePath());} else {mDevSupportManager = new ReleaseDevSupportManager();}
}

Application中主要是初始化了一些React的对象,主要就是一个ReactHostImpl,ReactHostImpl里面持有了JS代码和引擎,以及要加载的包信息等等。

Activity启动

2.1 ReactActivity.onCreate
调了ReactActivityDelegate的onCreate

protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 详见2.2mDelegate.onCreate(savedInstanceState);
}

2.2 ReactActivityDelegate.onCreate
构建ReactDelegate,会根据flag构建ReactDelegate传入不同的参数,我们跟新架构的路径。
ReactDelegate会持有ReactHost或者ReactNativeHost,新架构是前者,老架构师后者。

public void onCreate(Bundle savedInstanceState) {String mainComponentName = getMainComponentName();final Bundle launchOptions = composeLaunchOptions();if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && isWideColorGamutEnabled()) {mActivity.getWindow().setColorMode(ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT);}if (ReactFeatureFlags.enableBridgelessArchitecture) {// 详见2.3mReactDelegate =new ReactDelegate(getPlainActivity(), getReactHost(), mainComponentName, launchOptions);} else {mReactDelegate =new ReactDelegate(getPlainActivity(),getReactNativeHost(),mainComponentName,launchOptions,isFabricEnabled()) {@Overrideprotected ReactRootView createRootView() {ReactRootView rootView = ReactActivityDelegate.this.createRootView();if (rootView == null) {rootView = super.createRootView();}return rootView;}};}if (mainComponentName != null) {// 详见2.3loadApp(mainComponentName);}
}

2.3 ReactActivityDelegate.loadApp
构建根View,配置给Activity。

protected void loadApp(String appKey) {// 详见2.4mReactDelegate.loadApp(appKey);getPlainActivity().setContentView(mReactDelegate.getReactRootView());
}

2.4 ReactDelegate.loadApp
这里一样有两套逻辑,新架构一套老架构一套,我们还是看新架构的流程。
这里构建了一个ReactSurfaceImpl,ReactSurfaceImpl里面会持有一个ReactSurfaceView,ReactSurfaceView是一个FrameLayout的子类,作为根View。
然后调用了mReactSurface.start来初始化。

public void loadApp(String appKey) {// With Bridgeless enabled, create and start the surfaceif (ReactFeatureFlags.enableBridgelessArchitecture) {if (mReactSurface == null) {// 构建了一个ReactSurfaceImpl和ReactSurfaceView,ReactSurfaceImpl持有ReactSurfaceView  // ReactSurfaceView本质就是一个FrameLayoutmReactSurface = mReactHost.createSurface(mActivity, appKey, mLaunchOptions);mActivity.setContentView(mReactSurface.getView());}// 启动ReactSurfaceImpl,详见2.5mReactSurface.start();} else {if (mReactRootView != null) {throw new IllegalStateException("Cannot loadApp while app is already running.");}mReactRootView = createRootView();mReactRootView.startReactApplication(getReactNativeHost().getReactInstanceManager(), appKey, mLaunchOptions);}
}

2.5 ReactSurfaceImpl.start
这里的Task是ReactNative自己写的一套逻辑,封装了异步调用的能力,功能类似于RXJava,就不详细看了,只要知道这是干啥用的就可以。
大致就是在mBGExecutor线程池里面调用getOrCreateStartTask返回的Task,然后等任务完成后回调getResult。
逻辑在getOrCreateStartTask里。

public TaskInterface<Void> start() {// 详见2.6return Task.call(this::getOrCreateStartTask, mBGExecutor).continueWithTask(Task::getResult);
}

2.6 ReactSurfaceImpl.getOrCreateStartTask
主要就是通过waitThenCallGetOrCreateReactInstanceTask来构建ReactInstance的Task

private Task<Void> getOrCreateStartTask() {final String method = "getOrCreateStartTask()";if (mStartTask == null) {log(method, "Schedule");mStartTask =// 调用waitThenCallGetOrCreateReactInstanceTask来构建ReactInstance,首次就会构建,后续使用缓存,详见2.7waitThenCallGetOrCreateReactInstanceTask().continueWithTask((task) -> {if (task.isFaulted()) {mReactHostDelegate.handleInstanceException(task.getError());// 如果出现异常则调用DestoryTask。return getOrCreateDestroyTask("getOrCreateStartTask() failure: " + task.getError().getMessage(),task.getError()).continueWithTask(destroyTask -> Task.forError(task.getError())).makeVoid();}return task.makeVoid();},mBGExecutor);}return mStartTask;
}

2.7 ReactSurfaceImpl.waitThenCallGetOrCreateReactInstanceTaskWithRetries
直接调用了waitThenCallGetOrCreateReactInstanceTaskWithRetries重载函数

@ThreadConfined("ReactHost")
private Task<ReactInstance> waitThenCallGetOrCreateReactInstanceTask() {// 调用重载函数,传入参数为重试次数,详见2.8return waitThenCallGetOrCreateReactInstanceTaskWithRetries(0, 4);
}

2.8 ReactSurfaceImpl.waitThenCallGetOrCreateReactInstanceTaskWithRetries
这里最终调用了getOrCreateReactInstanceTask来创建 创建ReactInstance的Task,也就是说其实最终是通过getOrCreateReactInstanceTask返回的Task里面的任务来创建ReactTask,其他的代码都是负责处理辅助逻辑,如失败重试,失败销毁,切换线程执行等。

@ThreadConfined("ReactHost")
private Task<ReactInstance> waitThenCallGetOrCreateReactInstanceTaskWithRetries(int tryNum, int maxTries) {final String method = "waitThenCallGetOrCreateReactInstanceTaskWithRetries";if (mReloadTask != null) {log(method, "React Native is reloading. Return reload task.");return mReloadTask;}if (mDestroyTask != null) {// 如果失败后重试次数没到最大重试次数,还可以重试boolean shouldTryAgain = tryNum < maxTries;if (shouldTryAgain) {log(method,"React Native is tearing down."+ "Wait for teardown to finish, before trying again (try count = "+ tryNum+ ").");return mDestroyTask.onSuccessTask((task) -> waitThenCallGetOrCreateReactInstanceTaskWithRetries(tryNum + 1, maxTries),mBGExecutor);}raiseSoftException(method,"React Native is tearing down. Not wait for teardown to finish: reached max retries.");}// 调用getOrCreateReactInstanceTask来创建ReactInstance,详见2.9return getOrCreateReactInstanceTask();
}

2.9 ReactSurfaceImpl.getOrCreateReactInstanceTask
ReactInstance代表着React的一个实例,里面持有了FabricUIManager,TurboModuleManager等,且提供了loadJSBundle执行JS代码,是React在Java侧最重要的管理类了。
这里最终调用了instance.loadJSBundle来执行JS代码。

@ThreadConfined("ReactHost")
private Task<ReactInstance> getOrCreateReactInstanceTask() {final String method = "getOrCreateReactInstanceTask()";log(method);return mCreateReactInstanceTaskRef.getOrCreate(() -> {log(method, "Start");ReactMarker.logMarker(ReactMarkerConstants.REACT_BRIDGELESS_LOADING_START, BRIDGELESS_MARKER_INSTANCE_KEY);// 获取JsBundleLoder,最终是通过这个来执行JS代码的,这个JsBundleLoader就是我们在Application初始化ReactHost的时候创建的那个。return getJsBundleLoader().onSuccess(task -> {// 前面Task完成后会进onSuccess,task.getResult可以拿到前面方法的返回值,就是JsBundleLoaderfinal JSBundleLoader bundleLoader = task.getResult();final BridgelessReactContext reactContext = getOrCreateReactContext();final DevSupportManager devSupportManager = getDevSupportManager();reactContext.setJSExceptionHandler(devSupportManager);log(method, "Creating ReactInstance");// 构建ReactInstance,这里初始化了很多内容,比较重要的有FabricUIManager,TurboModuleManagerfinal ReactInstance instance =new ReactInstance(reactContext,mReactHostDelegate,mComponentFactory,devSupportManager,mQueueThreadExceptionHandler,mUseDevSupport,getOrCreateReactHostInspectorTarget());mReactInstance = instance;instance.initializeEagerTurboModules();MemoryPressureListener memoryPressureListener =createMemoryPressureListener(instance);mMemoryPressureListener = memoryPressureListener;mMemoryPressureRouter.addMemoryPressureListener(memoryPressureListener);log(method, "Loading JS Bundle");// 执行JS代码,详见2.10instance.loadJSBundle(bundleLoader);// ...return new Result();},mBGExecutor).onSuccess(task -> {// ...流转生命周期return reactInstance;},mUIExecutor);});
}

2.10 ReactInstance.loadJSBundle
这里逻辑挺绕的,这里会调用JSBundleLoader的loadScript,JSBundleLoader是在1.4通过createAssetLoader创建的,是一个匿名内部类,里面就是调用了JSBundleLoaderDelegate.loadScriptFromAssets,JSBundleLoaderDelegate是loadscript的一个入参,是这里的匿名内部类,随意就是执行了这里的loadScriptFromAssets。

public void loadJSBundle(JSBundleLoader bundleLoader) {// Load the JS bundleSystrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "ReactInstance.loadJSBundle");bundleLoader.loadScript(new JSBundleLoaderDelegate() {@Overridepublic void loadScriptFromFile(String fileName, String sourceURL, boolean loadSynchronously) {mBridgelessReactContext.setSourceURL(sourceURL);loadJSBundleFromFile(fileName, sourceURL);}@Overridepublic void loadSplitBundleFromFile(String fileName, String sourceURL) {loadJSBundleFromFile(fileName, sourceURL);}@Overridepublic void loadScriptFromAssets(//执行的是这,我们在编译后会将js打包到assets目录下,这里就是执行入口。AssetManager assetManager, String assetURL, boolean loadSynchronously) {mBridgelessReactContext.setSourceURL(assetURL);// 详见2.11loadJSBundleFromAssets(assetManager, assetURL);}@Overridepublic void setSourceURLs(String deviceURL, String remoteURL) {mBridgelessReactContext.setSourceURL(deviceURL);}});Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
}public static JSBundleLoader createAssetLoader(final Context context, final String assetUrl, final boolean loadSynchronously) {return new JSBundleLoader() {@Overridepublic String loadScript(JSBundleLoaderDelegate delegate) {delegate.loadScriptFromAssets(context.getAssets(), assetUrl, loadSynchronously);return assetUrl;}};
}

2.11 ReactInstance.loadJSBundleFromAssets
这个是native方法,映射到C++层是JReactInstance::loadJSBundleFromAssets。

void JReactInstance::loadJSBundleFromAssets(jni::alias_ref<JAssetManager::javaobject> assetManager,const std::string& assetURL) {const int kAssetsLength = 9; // strlen("assets://");auto sourceURL = assetURL.substr(kAssetsLength);auto manager = extractAssetManager(assetManager);// 加载asset内的文件,将结果存在scriptauto script = loadScriptFromAssets(manager, sourceURL);// 最终调用的C++层的ReactInstance::loadScriptinstance_->loadScript(std::move(script), sourceURL);
}

2.12 ReactInstance::loadScript
这里调用了JSCRuntime.evaluateJavaScript,这里就到了JSI到逻辑了,JSI是使用JS引擎提供的api封装的轻量级框架,用于提供Ojbect-C和JS或者C++和JS通信,我们这里就不继续深入了,后面会有专门一节介绍JSI。
这里调用JSI接口执行JS代码,就到了index.js了,后续index.js代码是怎么最终通知Native构建View以及显示的逻辑我们在Fabric渲染器章节再来介绍。

void ReactInstance::loadScript(std::unique_ptr<const JSBigString> script,const std::string& sourceURL) {
auto buffer = std::make_shared<BigStringBuffer>(std::move(script));
std::string scriptName = simpleBasename(sourceURL);runtimeScheduler_->scheduleWork([this,scriptName,sourceURL,buffer = std::move(buffer),weakBufferedRuntimeExecuter = std::weak_ptr<BufferedRuntimeExecutor>(bufferedRuntimeExecutor_)](jsi::Runtime& runtime) {try {SystraceSection s("ReactInstance::loadScript");bool hasLogger(ReactMarker::logTaggedMarkerBridgelessImpl);if (hasLogger) {ReactMarker::logTaggedMarkerBridgeless(ReactMarker::RUN_JS_BUNDLE_START, scriptName.c_str());}// 调用JSCRuntime.evaluateJavaScript,这就到了JSI层了,我们这里暂时不继续看了,后面会有一节专门讲JSIruntime.evaluateJavaScript(buffer, sourceURL);if (hasLogger) {ReactMarker::logTaggedMarkerBridgeless(ReactMarker::RUN_JS_BUNDLE_STOP, scriptName.c_str());ReactMarker::logMarkerBridgeless(ReactMarker::INIT_REACT_RUNTIME_STOP);ReactMarker::logMarkerBridgeless(ReactMarker::APP_STARTUP_STOP);}if (auto strongBufferedRuntimeExecuter =weakBufferedRuntimeExecuter.lock()) {strongBufferedRuntimeExecuter->flush();}} catch (jsi::JSError& error) {jsErrorHandler_->handleFatalError(error);}});
}

小结

通过上面的介绍,我们知道了ReactNative的Android app是怎么启动并且最终执行到JS到index.js代码,中间我们跳过了一些逻辑,比如加载TruboModule包,且后面index.js执行后又是怎么通知到Native侧,让应用更新对应的View布局,以及JSI是怎么通过JS引擎提供的接口实现JS和C++层通信,这些我们会在后面的章节来介绍。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/58100.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

商家转账到零钱功能:便捷高效的资金流转新方式

在当今数字化时代&#xff0c;线上支付已成为商业活动中不可或缺的一部分。为了满足商家与消费者之间日益增长的多样化需求&#xff0c;各大支付平台纷纷推出了创新的支付解决方案。其中&#xff0c;“商家转账到零钱”功能便是一项备受瞩目的创新服务&#xff0c;它不仅极大地…

Yii2 init 初始化脚本分析

脚本目的&#xff1a; init 脚本主要的作用是&#xff1a;从 environments 目录中复制配置文件&#xff0c;确保应用适配不同环境&#xff08;例如开发、生产环境等&#xff09;。 工作流程&#xff1a; 获取 $_SERVER 的 argv 参数 加载 environments/index.php 文件&#…

CMake中的List关键词:详细指南

CMake中的List关键词&#xff1a;详细指南 一、List的基本概念二、List的常用命令1. 获取List的长度2. 获取List中指定索引的元素3. 将元素追加到List中4. 在List中指定位置插入元素5. 在List的开头插入元素6. 从List中移除元素7. 移除List中的重复元素8. 对List进行排序9. 将L…

OpenTelemetry 实际应用

介绍 OpenTelemetry“动手”指南适用于想要开始使用 OpenTelemetry 的人。 如果您是 OpenTelemetry 的新手&#xff0c;那么我建议您从OpenTelemetry 启动和运行帖子开始&#xff0c;我在其中详细介绍了 OpenTelemetry。 OpenTelemetry开始改变可观察性格局&#xff0c;它提供…

【动态规划】力扣198.打家劫舍

目录 一、题目二、思路1.递归2.递推 三、代码 一、题目 二、思路 1.递归 题目中指出不可以选相邻的房间&#xff0c;说明如果选了第 1 间&#xff0c;那么第 2 间一定不可以选&#xff0c;第 3 间房间可以选&#xff0c;也可以不选……假设是按照从第 1 间房间开始依次往后选…

OCR应用之集装箱箱号自动识别技术,原理与应用

集装箱箱号自动识别技术是现代物流领域中的一项重要技术&#xff0c;它通过先进的图像识别、字符识别等技术手段&#xff0c;实现了对集装箱箱号的快速、准确识别。这一技术不仅大大提高了物流效率&#xff0c;降低了运营成本&#xff0c;还成为了港口、码头、堆场等场所减员增…

Vue学习笔记(六)

模板引用(获取DOM 操作) 虽然Vue的声明性渲染模型为你抽象了大部分对DOM的直接操作&#xff0c;但在某些情况下&#xff0c;我们仍然需要直接访问底层DOM元素。要实现这一点&#xff0c;我们可以使用特殊的refattribute。 挂载结束后引用都会被暴露在this.$refs之上。 <s…

QT linux 打包时库和插件如何生成

在Linux下使用Qt创建应用程序包时&#xff0c;插件需要以下步骤生成&#xff1a; 确保你的Qt应用程序已经正确编译并且能够运行。 使用linuxdeployqt工具来打包你的应用程序。这个工具会自动收集所需的库和插件&#xff0c;并将它们打包到一个AppImage或者一个tarball中。 首…

.NetCore中事务没有正常完成

1. 示例代码 async Task<string> FunCode() {//业务代码using var trans TransactionHelper.GetTransactionScope();//插入表A&#xff0c;A中有Name字段await 数据库操作1;await 数据库操作2; trans.Complete();//调用其他系统接口await ERP.SendContent(); } 2. …

[NeetCode 150] Counting Bits

Counting Bits Given an integer n, count the number of 1’s in the binary representation of every number in the range [0, n]. Return an array output where output[i] is the number of 1’s in the binary representation of i. Example 1: Input: n 4Output: […

QT项目-仿QQ聊天(带宠物系统)

目录 一&#xff0c;项目介绍 二&#xff0c;开发环境 三&#xff0c;涉及技术 四&#xff0c;项目效果示例图 1&#xff0c;登录界面 2&#xff0c;主界面 3&#xff0c;聊天界面 4&#xff0c;功能界面 5&#xff0c;宠物界面 一&#xff0c;项目介绍 这是一个基于u…

Sampling采样与Virtual Columns虚拟列

1.大数据体系下&#xff0c;在真正的企业环境中&#xff0c;很容易出现很大的表&#xff0c;比如体积达到 TB 级别.对这种表一个简单的 SELECT * 都会非常的慢&#xff0c;哪怕 LIMIT 10 想要看 10 条数据&#xff0c;也会走 MapReduce 流程 这个时间等待是不合适的.Hive 提供的…

Kafka之消费者客户端

1、历史上的二个版本 与生产者客户端一样&#xff0c;在Kafka的发展过程当中&#xff0c;消费者客户端主要有两个大的版本&#xff1a; 旧消费者客户端&#xff08;Old Consumer&#xff09;&#xff1a;基于Scala语言开发的版本&#xff0c;又称为Scala消费者客户端。新消费…

蚁剑连接本地木马文件报错

项目场景&#xff1a; 本地搭建php和蚁剑环境&#xff0c;连接本地木马文件ma.php 问题描述 使用蚁剑连接localhost时报错 错误{ "address":"127.0.0.1" "code":"ECONNREFUSED", "errno":"ECONNREFUSED", &qu…

【JVM】——JVM运行机制、类加载机制、内存划分

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01; 希望本文内容能够帮助到你&#xff01;&#xff01; 目录 一&#xff1a;JVM引入 1&#xff1a;编程语言 2&#xff1a;JAVA运行机制 二&#xff1a;JVM中内存…

1U服务器和Hyper-V虚拟机使用记录

记录最近接触服务器和虚拟机的一些使用操作知识 背景&#xff1a;1U服务器上架使用&#xff0c;备份其他服务器vm虚拟机&#xff0c;Hyper-V管理虚拟机使用测试 设备&#xff1a;IBM3550服务器交换机&#xff0c; 移动硬盘&#xff1a;附加存储盘&#xff0c; u盘1&#xff1…

Openshift上使用Elasticsearch (ECK) Operator部署ES

部署 7.16.2 版本 Elasticsearch (ECK) Operator部署ES oc new-project middleware-elasticsearchapiVersion: elasticsearch.k8s.elastic.co/v1 kind: Elasticsearch metadata:name: es-testnamespace: middleware-elasticsearch spec:http:tls:selfSignedCertificate:disab…

go高并发之路——本地缓存

一、使用场景 试想一个场景&#xff0c;有一个配置服务系统&#xff0c;里面存储着各种各样的配置&#xff0c;比如直播间的直播信息、点赞、签到、红包、带货等等。这些配置信息有两个特点&#xff1a; 1、并发量可能会特别特别大&#xff0c;试想一下&#xff0c;一个几十万…

Anchor DETR:Transformer-Based目标检测的Query设计

写在前面 文中指出之前DETR-like算法存在以下问题&#xff1a; 之前DETR-liked检测算法里&#xff0c;object query是一组可学习的嵌入表示&#xff08;就是一组256-d的向量&#xff09;&#xff0c;缺乏明确的物理意义&#xff0c;不能解释它们会关注什么地方。每个object q…

探索现代软件开发中的持续集成与持续交付(CI/CD)实践

探索现代软件开发中的持续集成与持续交付&#xff08;CI/CD&#xff09;实践 随着软件开发的飞速进步&#xff0c;现代开发团队已经从传统的开发模式向更加自动化和灵活的开发流程转变。持续集成&#xff08;CI&#xff09; 与 持续交付&#xff08;CD&#xff09; 成为当下主…