【问题标题】:TLS upgrade, Stackoverflow error while using CustomHttpsSocketFactoryTLS 升级,使用 CustomHttpsSocketFactory 时出现 Stackoverflow 错误
【发布时间】:2016-08-12 14:01:18
【问题描述】:

使用this 链接尝试升级到 TLSv1.2。唯一的区别是到目前为止支持所有 TLS,所以使用了这个:

sslSocket.setEnabledProtocols(new String[]{"TLSv1","TLSv1.1","TLSv1.2"});

奇怪的是得到这个错误:

java.lang.StackOverflowError
        at com.myorg.my.utils.Myfile$CustomHttpsSocketFactory.createSocket(Myfile.java:101)

如果 Myfile.java 有这样的内容,注意下面提到的第 101 行

//...non useful code above
public Myfile(){
        String scheme = "https";
        Protocol baseHttps = Protocol.getProtocol(scheme);
        int defaultPort = baseHttps.getDefaultPort();

        ProtocolSocketFactory baseFactory = baseHttps.getSocketFactory();
        ProtocolSocketFactory customFactory = new CustomHttpsSocketFactory(baseFactory);

        Protocol customHttps = new Protocol(scheme, customFactory, defaultPort);
        Protocol.registerProtocol(scheme, customHttps); 
    }

    class CustomHttpsSocketFactory implements SecureProtocolSocketFactory
    {

       private final SecureProtocolSocketFactory base;

       public CustomHttpsSocketFactory(ProtocolSocketFactory base)
       {
          if(base == null || !(base instanceof SecureProtocolSocketFactory)) throw new IllegalArgumentException();
          this.base = (SecureProtocolSocketFactory) base;
       }

       private Socket acceptAllTLS(Socket socket)
       {
          if(!(socket instanceof SSLSocket)) return socket;
          SSLSocket sslSocket = (SSLSocket) socket;
          sslSocket.setEnabledProtocols(new String[]{"TLSv1","TLSv1.1","TLSv1.2"});
          return sslSocket;
       } 
   @Override
   public Socket createSocket(String host, int port) throws IOException
   {
      return acceptAllTLS(base.createSocket(host, port));
   }
   @Override
   public Socket createSocket(String host, int port, InetAddress localAddress, int localPort) throws IOException
   {
      return acceptAllTLS(base.createSocket(host, port, localAddress, localPort));
   }
   @Override
   public Socket createSocket(String host, int port, InetAddress localAddress, int localPort, HttpConnectionParams params) throws IOException
   {
      // The following line is 101 where the error occurs     
      return acceptAllTLS(base.createSocket(host, port, localAddress, localPort, params));
   }
   @Override
   public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException
   {
      return acceptAllTLS(base.createSocket(socket, host, port, autoClose));
   }  // ...non  useful code below}

我的问题

  1. 看起来很明显,base.createSocket 正在递归调用它自己的方法。看不懂怎么办?

  2. 无法在我的本地计算机上复制,这些日志仅在生产中出现。因此,我该如何复制它(使用与生产中相同的 Java 版本、tomcat 版本、lib 版本)

编辑

根据 cmets 的堆栈跟踪:

java.util.concurrent.ExecutionException: java.lang.StackOverflowError 在 java.util.concurrent.FutureTask.report(FutureTask.java:122) 在 java.util.concurrent.FutureTask.get(FutureTask.java:206) 在 com.myorg.cs.aggregator.ciscoivr.services.IvrServiceImpl$1.getStatusList(IvrServiceImpl.java:519) 在 com.myorg.cs.aggregator.ciscoivr.services.IvrServiceImpl.getCustomerInfo_aroundBody30(IvrServiceImpl.java:380) 在 com.myorg.cs.aggregator.ciscoivr.services.IvrServiceImpl$AjcClosure31.run(IvrServiceImpl.java:1) 在 org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96cproceed(AbstractTransactionAspect.aj:66) 在 org.springframework.transaction.aspectj.AbstractTransactionAspect$AbstractTransactionAspect$1.proceedWithInvocation(AbstractTransactionAspect.aj:72) 在 org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281) 在 org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96c(AbstractTransactionAspect.aj:70) 在 com.myorg.cs.aggregator.ciscoivr.services.IvrServiceImpl.getCustomerInfo(IvrServiceImpl.java:335) 在 sun.reflect.GeneratedMethodAccessor660.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:497) 在 org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) 在 org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) 在 org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281) 在 org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 在 org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) 在 com.sun.proxy.$Proxy156.getCustomerInfo(未知来源) com.myorg.cs.aggregator.controller.IVRController.getCustomerInfo(IVRController.java:106) 在 com.myorg.cs.aggregator.controller.IVRController$$FastClassBySpringCGLIB$$e1f912c1.invoke() 在 org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) 在 org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:718) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) 在 com.myorg.cs.aggregator.interceptor.ResponseTimeInterceptor.invokeUnderTrace(ResponseTimeInterceptor.java:38) 在 org.springframework.aop.interceptor.AbstractTraceInterceptor.invoke(AbstractTraceInterceptor.java:112) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 在 org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:85) 在 com.myorg.base.aspect.RequestContextProcessingAspect.forwardRequestContext(RequestContextProcessingAspect.java:113) 在 sun.reflect.GeneratedMethodAccessor419.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:497) 在 org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621) 在 org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610) 在 org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:68) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168) 在 org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 在 org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:654) 在 com.myorg.cs.aggregator.controller.IVRController$$EnhancerBySpringCGLIB$$a764c904.getCustomerInfo() 在 sun.reflect.GeneratedMethodAccessor659.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:497) 在 org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:222) 在 org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137) 在 org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110) 在 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:814) 在 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:737) 在 org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) 在 org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959) 在 org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) 在 org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) 在 org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) 在 javax.servlet.http.HttpServlet.service(HttpServlet.java:622) 在 org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) 在 javax.servlet.http.HttpServlet.service(HttpServlet.java:729) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 在 org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 在 org.tukey.web.filters.urlrewrite.RuleChain.handleRewrite(RuleChain.java:176) 在 org.tukey.web.filters.urlrewrite.RuleChain.doRules(RuleChain.java:145) 在 org.tukey.web.filters.urlrewrite.UrlRewriter.processRequest(UrlRewriter.java:92) 在 org.tukey.web.filters.urlrewrite.UrlRewriteFilter.doFilter(UrlRewriteFilter.java:381) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 在 com.myorg.cs.aggregator.filter.RequestIdentifierFilter.doFilterInternal(RequestIdentifierFilter.java:54) 在 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 在 org.apache.catalina.filters.CorsFilter.handleNonCORS(CorsFilter.java:438) 在 org.apache.catalina.filters.CorsFilter.doFilter(CorsFilter.java:179) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:316) 在 org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126) 在 org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 在 org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 在 org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:122) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 在 org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 在 org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:168) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 在 org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:48) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 在 org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:120) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 在 org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:205) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 在 org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:205) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 在 org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) 在 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 在 org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 在 org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53) 在 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 在 org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 在 org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213) 在 org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176) 在 org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) 在 org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 在 org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) 在 org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) 在 org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) 在 org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) 在 org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) 在 org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:617) 在 org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:673) 在 org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) 在 org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518) 在 org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091) 在 org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:668) 在 org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1521) 在 org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1478) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 在 org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 在 java.lang.Thread.run(Thread.java:745)

原因:java.lang.StackOverflowError 在 com.myorg.my.utils.Myfile$CustomHttpsSocketFactory.createSocket(Myfile.ja> va:101)

【问题讨论】:

  • 请提供堆栈跟踪。
  • 11thdimension : stacktrace 'caused by',重复这一行:在 com.myorg.my.utils.Myfile$CustomHttpsSocketFactory.createSocket(Myfile.java:101),大约 100 多次并退出
  • 我们需要看看在那之前会发生什么。
  • 这里:java.util.concurrent.ExecutionException:java.util.concurrent.FutureTask.report(FutureTask.java:122)处的 java.lang.StackOverflowError 在 java.util.concurrent.FutureTask.get (FutureTask.java:206) 在 com.myorg.services.SomefileCallingMyMethod$1.getStatusList(SomefileCallingMyMethod.java:519) 在 com.myorg.services.SomefileCallingMyMethod.getCustomerInfo_aroundBody30(SomefileCallingMyMethod.java:380) 在 com.myorg.services.SomefileCallingMyMethod .$AjcClosure31.run(IvrServiceImpl.java:1)
  • @Danyal 而不是将堆栈跟踪添加为评论,请将其添加到问题本身:)

标签: java tls1.2 apache-commons-httpclient


【解决方案1】:

如果您使用的是 JRE8(除非您已替换 JRE8 附带的默认 SunJSSE),则有一个系统属性“jdk.tls.client.protocols”。默认情况下,您在此处提到的任何内容都将用于所有客户端通信。我刚刚在你提到的other post 下添加了我的 cmets。

【讨论】:

  • 我尝试使用这个 java -XshowSettings:properties -version,但对您的属性的引用不存在。无论如何,谢谢拉杰什。还有它如何解释 Stackoverflow 错误?
  • 代码看起来不错...我没有看到任何递归调用。如果有任何递归调用,每次都会导致堆栈溢出。堆栈溢出可能只是偶然发生在那个时候......可能有一些流有太多的函数调用,并且偶然它在这一点上达到了堆栈限制。除非我们可以看到整个堆栈跟踪,否则我们不能排除这种可能性。您可能还想检查堆栈帧大小,如果太小则更改它。在生产和您的设置之间,堆栈框架也可能存在差异。
  • 如果没有看到“jdk.tls.client.protocols”,您可能没有使用 JRE8。它记录在这里 - docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/…
  • 公平点 Rajesh,几乎每次。我在本地尝试了太多的调用,24 REQ/persec 20k 请求(比我的 1 req/sec 在 prod 中预期的要多得多),仍然无法复制
  • 我们正在使用 JRE8 Rajesh :)
【解决方案2】:

我遇到了同样的问题 java.util.concurrent.ExecutionException: java.lang.StackOverflowError

类加载器使 private final SecureProtocolSocketFactory base 多次base = CustomHttpsSocketFactory 并且对该方法的递归调用会导致 StackOverflowError。

在我的情况下,我的 CustomHttpsSocketFactory 扩展了 SSLProtocolSocketFactory,问题就消失了

【讨论】:

    【解决方案3】:

    我也有同样的问题。您将多次注册 HTTPS 协议。我认为注册操作就像堆栈一样工作。

    String scheme = "https";
    Protocol baseHttps = Protocol.getProtocol(scheme);
    int defaultPort = baseHttps.getDefaultPort();
    
    ProtocolSocketFactory baseFactory = baseHttps.getSocketFactory();
    ProtocolSocketFactory customFactory = new CustomHttpsSocketFactory(baseFactory);
    
    Protocol customHttps = new Protocol(scheme, customFactory, defaultPort);
    Protocol.registerProtocol(scheme, customHttps); 
    

    Protocol.registerProptocol 方法必须在 JVM 中调用一次。每个 registerProtocol 在时间堆栈溢出后会导致一次方法调用。

    解决方案:添加一个像init这样的同步方法并调用它。

    public static boolean INITIALIZED = false; 
    
    private static synchronized void init() {
        if (!INITIALIZED) {
            INITIALIZED = true;
            String scheme = "https";
            Protocol baseHttps = Protocol.getProtocol(scheme);
            int defaultPort = baseHttps.getDefaultPort();
    
            ProtocolSocketFactory baseFactory = baseHttps.getSocketFactory();
            ProtocolSocketFactory customFactory = new CustomHttpsSocketFactory(baseFactory);
    
            Protocol customHttps = new Protocol(scheme, customFactory, defaultPort);
            Protocol.registerProtocol(scheme, customHttps); 
        }
    }
    ...
    ...
    init();
    ...
    ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-22
      • 1970-01-01
      • 2018-12-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多