java - java.lang.OutOfMemoryError : unable to create new native thread error using ChromeDriver and Chrome through Selenium in Spring boot

标签 java multithreading spring-boot selenium out-of-memory

我们已经使用Spring Boot开发了基于 Selenium 的Web应用程序。该服务器位于Google云端服务器上,作为VM实例。

我们有一个使用执行器的线程基础机制。使用 Selenium ,我们打开一个Chrome浏览器(无头)来执行操作,并为每个操作创建一个新线程。

遇到outOfMemory错误后,如果我们重新启动云实例,则在1小时内它将再次中断,并出现相同的错误。

请在下面的代码段中找到我们用来为每个请求创建执行程序服务的新实例的代码段。

executorService = Executors.newFixedThreadPool(1);
Future<Object> futureDetails = executorService.submit(new Callable<Object>() {

        @Override
        public Object call() throws Exception {

            Object response = client.getDetails(number);

            return response;
        }
    });

    executorService.shutdown();

我们有(16个vCPU,64 GB内存)服务器配置。

请在下面找到该版本的详细信息。

Spring 靴-2.0.0.RELEASE

Selenium -3.9.1

Linux-Debian 4.9.130-2(2018-10-27)x86_64 GNU/Linux

Chrome驱动程序-2.35.528139(47ead77cb35ad2a9a83248b292151462a66cd881)

谷歌浏览器-70.0.3538.110

JDK-1.8.0_232

请使用下面的资源报告找到:ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 257648
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 10240
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 257648
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

另外,我确实使用以下命令检查了内存:free -m
              total        used        free      shared  buff/cache   available
Mem:          64433        9479       54490         279         463       54132
Swap:             0           0           0

请在错误堆栈跟踪下面找到:

org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: unable to create new native thread at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1006) ~[spring-webmvc-5.0.4.RELEASE.jar!/:5.0.4.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925) ~[spring-webmvc-5.0.4.RELEASE.jar!/:5.0.4.RELEASE] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978) ~[spring-webmvc-5.0.4.RELEASE.jar!/:5.0.4.RELEASE] at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:881) ~[spring-webmvc-5.0.4.RELEASE.jar!/:5.0.4.RELEASE] at javax.servlet.http.HttpServlet.service(HttpServlet.java:661) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:855) ~[spring-webmvc-5.0.4.RELEASE.jar!/:5.0.4.RELEASE] at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-embed-websocket-8.5.28.jar!/:8.5.28] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter.doFilter(OAuth2AuthenticationProcessingFilter.java:176) [spring-security-oauth2-2.2.1.RELEASE.jar!/:na] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar!/:5.0.4.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar!/:5.0.4.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) [spring-security-web-5.0.3.RELEASE.jar!/:5.0.3.RELEASE] at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) [spring-web-5.0.4.RELEASE.jar!/:5.0.4.RELEASE] at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) [spring-web-5.0.4.RELEASE.jar!/:5.0.4.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-5.0.4.RELEASE.jar!/:5.0.4.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar!/:5.0.4.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109) [spring-web-5.0.4.RELEASE.jar!/:5.0.4.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar!/:5.0.4.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) [spring-web-5.0.4.RELEASE.jar!/:5.0.4.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar!/:5.0.4.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) [spring-web-5.0.4.RELEASE.jar!/:5.0.4.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.4.RELEASE.jar!/:5.0.4.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:496) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_241] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_241] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.28.jar!/:8.5.28] at java.lang.Thread.run(Thread.java:748) [na:1.8.0_241] Caused by: java.lang.OutOfMemoryError: unable to create new native thread



请帮助我了解问题和此问题的根本原因。如果您也可以提出解决方案,那将更好。

提前致谢。

最佳答案

此错误消息...

java.lang.OutOfMemoryError: unable to create new native thread

...暗示JVM无法在系统运行OutOfMemory时创建任何新的 native 线程

OutOfMemoryError

当您尝试启动新程序或尝试使用已运行的程序时,即使您仍然有足够的物理和页面文件存储空间,也会出现Out of Memory错误消息。当您运行Java程序或Java应用程序时,会为JVM分配一些内存。 JVM将该内存分为两部分。一个是堆栈内存,另一个是堆内存。堆栈内存用于执行方法,而堆内存用于存储对象。当堆变满时,JVM会抛出java.lang.OutOfMemoryError

java.lang.OutOfMemoryError

当堆内存已满并且JVM无法将内存分配给新对象时,将抛出java.lang.OutOfMemoryError。由于您用Java创建的对象存储在堆内存中,因此,当不再需要这些对象时,必须将其从内存中删除。垃圾收集器会自动从堆内存中删除不需要的对象。如果您的对象具有实时引用,则垃圾收集器不会删除它们。它仅删除那些没有实时引用的对象。在此过程中,如果在任何时间点堆内存中没有剩余空间供新对象使用,则JVM将抛出java.lang.OutOfMemoryError

这个用例

根据您的代码试用,您已经使用ThreadPoolExecutor实现了多线程,从而在打开浏览上下文时为每个请求创建和使用线程。

使用Selenium的多线程

正如您所提到的,在1小时内它以相同的错误破坏了agian,我怀疑这是由于WebDriver is not thread-safe造成的。话虽如此,如果您可以序列化对底层驱动程序实例的访问,则可以在多个线程中共享一个引用。这是不可取的。但是,您始终可以为每个线程实例化一个WebDriver实例。

理想情况下,线程安全性的问题不在您的代码中,而是在实际的浏览器绑定(bind)中。他们都假设一次只能有一个命令(例如,像真实用户一样)。但是另一方面,您始终可以为每个线程实例化一个WebDriver实例,这将启动多个浏览选项卡/窗口。到此为止,您的程序似乎是完美的。

现在,可以在同一Webdriver上运行不同的线程,但是测试结果将不是您期望的。背后的原因是,当您使用多线程在不同的选项卡/窗口上运行不同的测试时,需要一些线程安全编码,否则您将执行的操作(如click()send_keys())将转到打开的选项卡/窗口,即当前具有焦点,无论您希望运行的线程如何。从本质上讲,这意味着所有测试将同时在目标选项卡/窗口上具有焦点而不是的同一选项卡/窗口上同时运行。

附加注意事项

但是,另一个问题是正在使用的二进制版本之间的不兼容,如下所示:
  • 您正在使用chromedriver = 2.35
  • chromedriver=2.35
  • 发行说明中明确提到以下内容:

  • Supports Chrome v62-64


  • 您正在使用chrome = 70.0
  • ChromeDriver vv2.44
  • 发行说明中明确提到以下内容:

  • Supports Chrome v69-71


  • 您的Selenium Client版本是3.9.1,几乎比大了2 年。

  • 因此,Selenium Client v3.9.1,ChromeDriver v2.35和Chrome浏览器v70.0之间显然存在不匹配

    解决方案

    确保这件事:
  • JDK已升级到当前级别JDK 8u241
  • Selenium已升级到当前级别Version 3.141.59
  • ChromeDriver已更新为当前ChromeDriver v80.0级别。
  • Chrome已更新到当前的Chrome版本80.0。 (按照ChromeDriver v80.0 release notes)
  • 如果您的基本Web客户端版本太旧,请通过Revo Uninstaller卸载它,并安装最新的GA和Web客户端的发行版本。
  • 进行系统重新引导。
  • 始终在driver.quit()方法中调用tearDown(){}以优雅地关闭和销毁WebDriver和Web Client实例。


  • tl;博士

    How to set memory limit for OOM Killer for chrome?

    关于java - java.lang.OutOfMemoryError : unable to create new native thread error using ChromeDriver and Chrome through Selenium in Spring boot,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60318473/

    相关文章:

    java - 一个类可以同时具有公共(public)和私有(private)构造函数吗?

    java - 将 DOCX 转换为 XML 文件

    java - 我为什么要使用通知?

    java - 暂停 SwingWorker

    java - 如何测试 Spring-boot 应用程序的主类

    java - 在 Spring boot security 中使用公钥/私钥创建和验证 JWT 签名

    java - 在应用程序类中注册时存在广播接收器泄漏的风险

    java - 在导出的 csv 文件中添加新行?

    linux - save_stack_trace_tsk 和 struct stack_trace 在 Linux 5.2+ 中不再可用

    java - Spring REST 从路由中获取 Controller +方法?