Linux系统下java.io.PrintStream阻塞致Selenium Java应用挂起问题
问题分析与解决方案
线程转储信息
"Exec Stream Pumper" daemon prio=5 id=126 state=BLOCKED LockOwnerName= pool-1-thread-9 LockOwnerId=129 LockName=java.io.PrintStream@27c7422a BlockedTime= -1 BlockedCount= 1 at java.io.PrintStream.write(PrintStream.java:447) at org.openqa.selenium.io.MultiOutputStream.write(MultiOutputStream.java:40) at java.io.OutputStream.write(OutputStream.java:116) at org.apache.commons.exec.StreamPumper.run(StreamPumper.java:108) at java.lang.Thread.run(Thread.java:750)
"Forwarding quit on session ea6c16f7-a829-4711-a058-e0cae7f49447 to remote" prio=5 id=122 state=BLOCKED LockOwnerName= pool-1-thread-9 LockOwnerId=129 LockName=java.io.PrintStream@27c7422a BlockedTime= -1 BlockedCount= 10 at java.io.PrintStream.flush(PrintStream.java:337) at org.openqa.selenium.io.MultiOutputStream.flush(MultiOutputStream.java:48) at org.apache.commons.exec.PumpStreamHandler.stop(PumpStreamHandler.java:195) at org.openqa.selenium.os.OsProcess.destroy(OsProcess.java:135) at org.openqa.selenium.os.CommandLine.destroy(CommandLine.java:139) at org.openqa.selenium.remote.service.DriverService.stop(DriverService.java:281) at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:129) at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:541) at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:596) at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:600) at org.openqa.selenium.remote.RemoteWebDriver.quit(RemoteWebDriver.java:443) at org.openqa.selenium.firefox.FirefoxDriver.quit(FirefoxDriver.java:307) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.openqa.selenium.support.events.EventFiringWebDriver.lambda$new$1(EventFiringWebDriver.java:106) at org.openqa.selenium.support.events.EventFiringWebDriver$$Lambda$315/1342232709.invoke(Unknown Source) at com.sun.proxy.$Proxy6.quit(Unknown Source) at org.openqa.selenium.support.events.EventFiringWebDriver.quit(EventFiringWebDriver.java:212)
问题描述
在Linux机器上运行Selenium Java应用,多次执行后进程出现挂起。线程转储显示java.io.PrintStream引发阻塞,该应用在Windows系统下运行正常,目前仅能通过重启进程解决问题。
核心原因
Linux与Windows的标准输出/错误流处理机制存在差异:Driver进程的输出流未被及时消费时,会触发PrintStream的锁竞争,导致执行quit操作的主线程和流泵线程相互阻塞,最终引发进程挂起。
可行解决方案
自定义DriverService流处理
替换默认的控制台输出,将Driver的日志重定向到文件或直接丢弃,避免锁竞争。示例代码:DriverService service = new FirefoxDriverService.Builder() .usingDriverExecutable(new File("path/to/geckodriver")) .usingAnyFreePort() .withStreamHandler(new PumpStreamHandler(new FileOutputStream("driver-output.log"), new FileOutputStream("driver-error.log"))) .build();禁用Driver冗余日志
通过系统属性关闭不必要的日志输出,减少流写入频率。以FirefoxDriver为例:System.setProperty(FirefoxDriver.SystemProperty.BROWSER_LOGFILE, "/dev/null");升级Selenium与Driver版本
旧版本的Selenium或GeckoDriver存在Linux下的流处理bug,升级至最新稳定版(如Selenium 4.x系列)可修复此类问题。添加进程销毁钩子
在应用中添加关机钩子,确保进程退出时强制清理Driver进程与关联流资源:Runtime.getRuntime().addShutdownHook(new Thread(() -> { if (driver != null) { driver.quit(); } }));
内容的提问来源于stack exchange,提问作者Rajeshkumar
相关产品推荐
相关产品推荐

