一次 Netty 不健壮导致的无限重连分析

本文详细分析了一次由于Java应用中的OOM导致的Netty客户端无限重连问题。现象表现为Dubbo客户端不断尝试建立连接并在3秒后断开。通过strace和线程分析,发现原因是New I/O boss线程因OOM退出,未执行epoll_ctl注册事件,导致连接建立后无法正常处理。解决方案包括避免OOM、优化Netty的异常处理及升级版本。

由于 OOM 导致不健壮的 Netty 一系列诡异的行为,这次的问题分析会比上次那个更有意思一点。(备注:本文 Netty 版本是上古时代的 3.7.0.Final)

现象描述

开发的同学反馈 dubbo 客户端无法调用远程的服务,抓包来看,客户端一直在建连,每次建连成功 3 秒以后就主动断开连接。
在这里插入图片描述
这个现象就很奇怪了,默认情况下 dubbo 消费端对属于同一个 provider 的不同 service 只会共享一条 tcp 连接进行通信,此处就是为了跟 provider 端建立这个连接。

为什么这里三次握手成功以后会断开连接呢?这个现象其实挺诡异的,于是想到用 strace 看一下背后到底发生了什么。

strace -f -T -p 238289 -o strace-new.238289.out

在 strace 中找 connect 相关的调用,根据线程号过滤对应的日志,可以看到发生了哪些系统调用:
在这里插入图片描述一开始就创建一个 socket,将该套接字设置为非阻塞,随后调用 connect 发起建立,因为是非阻塞套接字,connect 这里不阻塞直接返回 -1,随后开始等待 3s,如果 3s 内没有能建立成功,futex 超时退出。

但是这个跟抓包的行为就不一致了,从包上看,duboo 服务端有回复 SYN+ACK,但是 java 应用认为我没有收到,3s 超时。

同时,这里整个 strace 日志中没有看到对应 fd 相关 epoll_ctl 调用,也就是没有人把这个 fd 加入到 epoll 的事件监听中。

正常来说,我们的一个非阻塞的

日志如下 C:\own\app\python_code\.venv\Scripts\python.exe C:\own\app\python_code\work\IBL_click_all\click_all.py 🚀 启动 Android 应用探索器... 🔄 开始探索当前页面... ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/navigation_my_label/My Labels/My Labels ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 📌 导航栏元素数量: 3, 非导航栏元素数量: 3 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/navigation_setting/Settings/Settings ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/navigation_buy/Shop/Shop ⚠️ 当前在目标应用 (com.android.chrome/org.chromium.chrome.browser.firstrun.FirstRunActivity),正在尝试恢复... ✅ 通过 back 成功返回目标 App ⏳ 等待页面加载最多 10s... ✅ 页面加载完成 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 🟢 点击成功: null/null ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/setting_printer/null ⚠️ 当前在目标应用 (com.google.android.permissioncontroller/com.android.permissioncontroller.permission.ui.GrantPermissionsActivity),正在尝试恢复... ✅ 通过 back 成功返回目标 App ⏳ 等待页面加载最多 10s... ✅ 页面加载完成 📌 导航栏元素数量: 0, 非导航栏元素数量: 6 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/wifi_printer_recycler_view/null ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 📌 导航栏元素数量: 0, 非导航栏元素数量: 6 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/gps_selected_item_button/Settings/null ⚠️ 当前在目标应用 (com.android.settings/.spa.SpaActivity),正在尝试恢复... 🔁 正在通过 activate_app 恢复... ⏳ 等待页面加载最多 10s... ✅ 页面加载完成 ✅ 自动处理了弹窗 📌 导航栏元素数量: 0, 非导航栏元素数量: 8 🟢 点击成功: com.android.permissioncontroller:id/grant_singleton/null ⚠️ 当前在目标应用 (com.google.android.permissioncontroller/com.android.permissioncontroller.permission.ui.GrantPermissionsActivity),正在尝试恢复... ✅ 通过 back 成功返回目标 App ⏳ 等待页面加载最多 10s... ✅ 页面加载完成 📌 导航栏元素数量: 0, 非导航栏元素数量: 6 ✅ 当前页面所有可点击元素已处理完毕。 🔙 返回上一页继续探索... ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/setting_unit/null ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 ✅ 自动处理了弹窗 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/setting_support/Support/null ⚠️ 当前在目标应用 (com.android.chrome/org.chromium.chrome.browser.firstrun.FirstRunActivity),正在尝试恢复... ✅ 通过 back 成功返回目标 App ⏳ 等待页面加载最多 10s... ✅ 页面加载完成 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/setting_information/Information/null ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 📌 导航栏元素数量: 3, 非导航栏元素数量: 13 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/info_list/null ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 📌 导航栏元素数量: 3, 非导航栏元素数量: 17 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/send_info_check/Send Information/null ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 📌 导航栏元素数量: 3, 非导航栏元素数量: 17 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/privacy_policy_text_view/Privacy Policy/null ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 📌 导航栏元素数量: 3, 非导航栏元素数量: 21 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/privacy_policy_text2/When you use the SOFTWARE, information from the Brother Machine and the devices connected to the Brother Machine (“Device”), including but not limited to, product model, serial number, locale ID (regional information), OS type of your installation, firmware, use of each function of the SOFTWARE, may be recorded in our server. Additionally, printing information such as printing date, quantity, the types and sizes of paper, and the types of files, etc. (collectively, “Device Data”) may be recorded in our server. Device Data (except for the serial number) cannot be used in itself or in combination with any other information we may have to identify you as a person. We reserve the right to use such Device Data solely for the improvement of the SOFTWARE or any other products/services of Brother, our marketing/research activities without identifying you as a person, product planning or any other related activities for our customer’s benefits (collectively “Purposes”). We will not use your Device Data other than for the Purposes without your prior consent. We may disclose your Device Data to third parties in an anonymous format solely for achieving the Purposes, and always by obliging such third parties to control such data as confidential. Device Data includes the serial number of your Brother Machine. The serial number can be associated with the data which you might register to our sales company’s product registration website. However, we will not use the serial number to identify you or other than for the Purposes. Serial number may be stored in Server located in countries without an adequate level of protection for personal data compared to that in your country, but we will control the serial number in strict accordance with “Brother’s Statement on Device Data Worldwide” which is available at Brother’s Website <https://web.global.brother/aa/privacy.html> . /null ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 📌 导航栏元素数量: 3, 非导航栏元素数量: 21 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/navigation_layout/Create/Create ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/tabLayout/null ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 🟢 点击成功: null/Templates/Templates ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/download_template_button/DOWNLOAD TEMPLATES/null ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 📌 导航栏元素数量: 3, 非导航栏元素数量: 5 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/actionButtonNewLabel/NEW LABEL/null ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 📌 导航栏元素数量: 0, 非导航栏元素数量: 7 🟢 点击成功: null/Navigate up/Navigate up ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 📌 导航栏元素数量: 0, 非导航栏元素数量: 3 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/buttonPanel/null ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 📌 导航栏元素数量: 0, 非导航栏元素数量: 8 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/edit_undo/Undo/null ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 📌 导航栏元素数量: 0, 非导航栏元素数量: 7 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/edit_save/Save/null ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 📌 导航栏元素数量: 0, 非导航栏元素数量: 4 🟢 点击成功: com.brother.ptouch.iprintandlabel:id/edit_save_label_edit/42/null ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 ⚠️ 分类元素时异常: Message: Cached elements 'By.xpath: //*[ (@clickable='true' or @focusable='true') and @displayed='true' and @enabled='true' ] ' do not exist in DOM anymore; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#staleelementreferenceexception Stacktrace: io.appium.uiautomator2.common.exceptions.StaleElementReferenceException: Cached elements 'By.xpath: //*[ (@clickable='true' or @focusable='true') and @displayed='true' and @enabled='true' ] ' do not exist in DOM anymore at io.appium.uiautomator2.model.ElementsCache.restore(ElementsCache.java:78) at io.appium.uiautomator2.model.ElementsCache.get(ElementsCache.java:153) at io.appium.uiautomator2.handler.GetElementAttribute.safeHandle(GetElementAttribute.java:23) at io.appium.uiautomator2.handler.request.SafeRequestHandler.handle(SafeRequestHandler.java:59) at io.appium.uiautomator2.server.AppiumServlet.handleRequest(AppiumServlet.java:259) at io.appium.uiautomator2.server.AppiumServlet.handleHttpRequest(AppiumServlet.java:253) at io.appium.uiautomator2.http.ServerHandler.channelRead(ServerHandler.java:77) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:438) at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:328) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:302) at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:253) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:287) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1422) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:931) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:700) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:635) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:552) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:514) at io.netty.util.concurrent.SingleThreadEventExecutor$6.run(SingleThreadEventExecutor.java:1044) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.lang.Thread.run(Thread.java:1119) ⚠️ 分类元素时异常: Message: Cached elements 'By.xpath: //*[ (@clickable='true' or @focusable='true') and @displayed='true' and @enabled='true' ] ' do not exist in DOM anymore; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#staleelementreferenceexception Stacktrace: io.appium.uiautomator2.common.exceptions.StaleElementReferenceException: Cached elements 'By.xpath: //*[ (@clickable='true' or @focusable='true') and @displayed='true' and @enabled='true' ] ' do not exist in DOM anymore at io.appium.uiautomator2.model.ElementsCache.restore(ElementsCache.java:78) at io.appium.uiautomator2.model.ElementsCache.get(ElementsCache.java:153) at io.appium.uiautomator2.handler.GetElementAttribute.safeHandle(GetElementAttribute.java:23) at io.appium.uiautomator2.handler.request.SafeRequestHandler.handle(SafeRequestHandler.java:59) at io.appium.uiautomator2.server.AppiumServlet.handleRequest(AppiumServlet.java:259) at io.appium.uiautomator2.server.AppiumServlet.handleHttpRequest(AppiumServlet.java:253) at io.appium.uiautomator2.http.ServerHandler.channelRead(ServerHandler.java:77) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:438) at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:328) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:302) at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:253) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:287) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1422) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:931) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:700) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:635) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:552) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:514) at io.netty.util.concurrent.SingleThreadEventExecutor$6.run(SingleThreadEventExecutor.java:1044) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.lang.Thread.run(Thread.java:1119) 📌 导航栏元素数量: 0, 非导航栏元素数量: 2 🔴 点击失败 unknown_element: Message: Cached elements 'By.xpath: //*[ (@clickable='true' or @focusable='true') and @displayed='true' and @enabled='true' ] ' do not exist in DOM anymore; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#staleelementreferenceexception Stacktrace: io.appium.uiautomator2.common.exceptions.StaleElementReferenceException: Cached elements 'By.xpath: //*[ (@clickable='true' or @focusable='true') and @displayed='true' and @enabled='true' ] ' do not exist in DOM anymore at io.appium.uiautomator2.model.ElementsCache.restore(ElementsCache.java:78) at io.appium.uiautomator2.model.ElementsCache.get(ElementsCache.java:153) at io.appium.uiautomator2.handler.Click.safeHandle(Click.java:36) at io.appium.uiautomator2.handler.request.SafeRequestHandler.handle(SafeRequestHandler.java:59) at io.appium.uiautomator2.server.AppiumServlet.handleRequest(AppiumServlet.java:259) at io.appium.uiautomator2.server.AppiumServlet.handleHttpRequest(AppiumServlet.java:253) at io.appium.uiautomator2.http.ServerHandler.channelRead(ServerHandler.java:77) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:438) at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:328) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:302) at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:253) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:287) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1422) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:931) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:700) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:635) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:552) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:514) at io.netty.util.concurrent.SingleThreadEventExecutor$6.run(SingleThreadEventExecutor.java:1044) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.lang.Thread.run(Thread.java:1119) 🔴 点击失败 unknown_element: Message: Cached elements 'By.xpath: //*[ (@clickable='true' or @focusable='true') and @displayed='true' and @enabled='true' ] ' do not exist in DOM anymore; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#staleelementreferenceexception Stacktrace: io.appium.uiautomator2.common.exceptions.StaleElementReferenceException: Cached elements 'By.xpath: //*[ (@clickable='true' or @focusable='true') and @displayed='true' and @enabled='true' ] ' do not exist in DOM anymore at io.appium.uiautomator2.model.ElementsCache.restore(ElementsCache.java:78) at io.appium.uiautomator2.model.ElementsCache.get(ElementsCache.java:153) at io.appium.uiautomator2.handler.Click.safeHandle(Click.java:36) at io.appium.uiautomator2.handler.request.SafeRequestHandler.handle(SafeRequestHandler.java:59) at io.appium.uiautomator2.server.AppiumServlet.handleRequest(AppiumServlet.java:259) at io.appium.uiautomator2.server.AppiumServlet.handleHttpRequest(AppiumServlet.java:253) at io.appium.uiautomator2.http.ServerHandler.channelRead(ServerHandler.java:77) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:438) at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:328) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:302) at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:253) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:287) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1422) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:931) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:700) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:635) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:552) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:514) at io.netty.util.concurrent.SingleThreadEventExecutor$6.run(SingleThreadEventExecutor.java:1044) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.lang.Thread.run(Thread.java:1119) ✅ 当前页面所有可点击元素已处理完毕。 🔙 返回上一页继续探索... ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 ✅ 当前页面所有可点击元素已处理完毕。 🔙 返回上一页继续探索... ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 ✅ 当前页面所有可点击元素已处理完毕。 🔙 返回上一页继续探索... ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 ✅ 当前页面所有可点击元素已处理完毕。 🔙 返回上一页继续探索... ⏳ 等待页面加载最多 1s... ✅ 页面加载完成 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 ✅ 当前页面所有可点击元素已处理完毕。 🔙 返回上一页继续探索... ⚠️ 当前在目标应用 (com.google.android.apps.nexuslauncher/.NexusLauncherActivity),正在尝试恢复... 🔁 正在通过 activate_app 恢复... ⏳ 等待页面加载最多 10s... ✅ 页面加载完成 ✅ 成功激活目标 App 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 ✅ 当前页面所有可点击元素已处理完毕。 🔙 返回上一页继续探索... ⚠️ 当前在目标应用 (com.google.android.apps.nexuslauncher/.NexusLauncherActivity),正在尝试恢复... 🔁 正在通过 activate_app 恢复... ⏳ 等待页面加载最多 10s... ✅ 页面加载完成 ✅ 成功激活目标 App 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 ✅ 当前页面所有可点击元素已处理完毕。 🔙 返回上一页继续探索... ⚠️ 当前在目标应用 (com.google.android.apps.nexuslauncher/.NexusLauncherActivity),正在尝试恢复... 🔁 正在通过 activate_app 恢复... ⏳ 等待页面加载最多 10s... ✅ 页面加载完成 ✅ 成功激活目标 App 📌 导航栏元素数量: 3, 非导航栏元素数量: 6 ✅ 当前页面所有可点击元素已处理完毕。 🔙 返回上一页继续探索... ⚠️ 当前在目标应用 (com.google.android.apps.nexuslauncher/.NexusLauncherActivity),正在尝试恢复... 🛑 已多次回到 ('com.google.android.apps.nexuslauncher', '.NexusLauncherActivity'),疑似陷入循环,停止恢复。 ❌ 无法恢复至目标应用,退出。 🔚 自动化结束。 Process finished with exit code 0 日志繁琐
最新发布
10-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值