项目

一般

简介

应用点击系统某个功能时抛出异常:java.lang.NoClassDefFoundError: Could not initialize class org.apache.http.conn.ssl.SSLConnectionSocketFactory

由 何 善才 在 超过 2 年 之前添加

项目:深圳南山证数局

异常现象:tomcat正常,apusic v10点击系统某个功能时抛出异常

异常信息:

[2022-06-23T09:37:09] [] [WARNING] [] [javax.enterprise.web] [tid: _ThreadID=67 _ThreadName=ApusicLogManager] [timeMillis: 1655948229449] [levelValue: 900] [[
  StandardWrapperValve[xhr]: Servlet.service() for servlet xhr threw exception
java.lang.NoClassDefFoundError: Could not initialize class org.apache.http.conn.ssl.SSLConnectionSocketFactory
    at org.apache.http.impl.client.HttpClientBuilder.build(HttpClientBuilder.java:912)
    at com.yh.scofd.agent.HTTPAgent.createHttpClient(HTTPAgent.java:450)
    at com.yh.scofd.agent.HTTPAgent.<init>(HTTPAgent.java:122)
    at com.neusoft.nda.basic.FormatConversion.module.FormatConversionUtil.officeFormatToOFD(FormatConversionUtil.java:40)
    at com.neusoft.nda.basic.FormatConversion.service.FormatConversionOFDServiceImpl.convertEleFile(FormatConversionOFDServiceImpl.java:374)
    at com.neusoft.nda.basic.FormatConversion.service.FormatConversionOFDServiceImpl.convertRecord(FormatConversionOFDServiceImpl.java:111)
    at com.neusoft.nda.basic.FormatConversion.module.FormatConversionOFDModule.execute(FormatConversionOFDModule.java:47)
    at com.neusoft.nda.basic.FormatConversion.module.FormatConversionOFDModule.execute(FormatConversionOFDModule.java:1)
    at com.neusoft.nda.selfframe.frame.service.ModuleProcessorImpl.processModulePerform(ModuleProcessorImpl.java:510)
    at com.neusoft.nda.selfframe.frame.service.ModuleProcessorImpl.process(ModuleProcessorImpl.java:115)
    at com.neusoft.nda.core.web.servlet.JSONRequestProcessor._$1(Unknown Source)
    at com.neusoft.nda.core.web.servlet.JSONRequestProcessor._$2(Unknown Source)
    at com.neusoft.nda.core.web.servlet.JSONRequestProcessor.processXHRRequestPerform(Unknown Source)
    at com.neusoft.nda.core.web.servlet.JSONRequestProcessor.process(Unknown Source)
    at com.neusoft.talentbase.platform.core.web.servlet.XHRServlet.process(XHRServlet.java:48)
    at com.neusoft.talentbase.platform.core.web.servlet.XHRServlet.doPost(XHRServlet.java:44)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:665)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1579)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:297)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:167)
    at com.neusoft.nda.login.filter.SecurityFilter.doFilter(SecurityFilter.java:513)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:209)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:167)
    at com.neusoft.nda.login.filter.UserContextFilter.doFilter(UserContextFilter.java:208)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:209)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:167)
    at com.neusoft.nda.login.filter.UserContextFilter.doFilter(UserContextFilter.java:208)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:209)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:167)
    at com.neusoft.uniflow.web.common.filter.EncodingFilter.doFilter(EncodingFilter.java:46)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:209)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:167)
    at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:123)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:209)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:167)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:215)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:119)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:611)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:550)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:75)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:114)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:333)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:200)
    at com.apusic.enterprise.v10.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:439)
    at com.apusic.enterprise.v10.services.impl.ContainerMapper.service(ContainerMapper.java:144)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:195)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:162)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:218)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:95)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:261)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:178)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:110)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:89)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:53)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:549)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:89)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:94)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:33)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:114)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:569)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:549)
    at java.lang.Thread.run(Thread.java:748)
]]
 

排查过程:与研发同事经过漫长debug,后发现问题

1、找到对应的包jar,找到 at org.apache.http.impl.client.HttpClientBuilder.build(HttpClientBuilder.java:912)该类该方法进行断点调试,

build 方法中,走到了 

new SSLConnectionSocketFactory(SSLContexts.createDefault(), (HostnameVerifier)proxyAuthStrategyCopy); 该代码进行对SSLConnectionSocketFactory实例化操作

进入代码查看该代码的构造方法,进入该方法后,再进去为jdk的源码信息,并没能找到问题所在

最后看代码发现在构造方法之前还有一个静态代码块优先执行,最终将断点打在静态代码块中

补充知识:对象进行初始化时顺序

初始化顺序如下:

1、基类静态代码块,基类静态成员字段(并列优先级,按照代码中出现的先后顺序执行,且只有第一次加载时执行);
2、派生类静态代码块,派生类静态成员字段(并列优先级,按照代码中出现的先后顺序执行,且只有第一次加载时执行);
3、基类普通代码块,基类普通成员字段(并列优先级,按代码中出现先后顺序执行);
3、基类构造函数;
4、派生类(子类)普通代码块,派生类普通成员字段(并列优先级,按代码中出现先后顺序执行);
5、派生类(子类)构造函数。
 

发现调用到ALLOW_ALL_HOSTNAME_VERIFIER = AllowAllHostnameVerifier.INSTANCE;该代码时出现问题,进入debug 该代码查看


发现ALLOW_ALL_HOSTNAME_VERIFIER = AllowAllHostnameVerifier.INSTANCE 代码中AllowAllHostnameVerifier调用INSTANCE属性时抛出异常NoSuchFieldERROR (上图),

意思是在new SSLConnectionSocketFactory 创建工厂对象之前就已经出现问题,继续向下查看发现 AllowAllHostnameVerifier该类源码

但是查看该jar的源码发现是有INSTANCE该属性的代码:public static final AllowAllHostnameVerifier INSTANCE = new AllowAllHostnameVerifier();为何会抛出没有该属性的异常的呢

debug发现AllowAllHostnameVerifier调用INSTANCE ,codesource(源码)AllowAllHostnameVerifier 来自是另一个包tika-app-1.14.jar.

原因:

tika-app-1.14.jar 与httpclient-4.4.1  存在相同全类名(AllowAllHostnameVerifier),代码调用时调用到了tika-app-1.14.jar 中的属性,

但是该jar并没有该属性:public static final AllowAllHostnameVerifier INSTANCE = new AllowAllHostnameVerifier();

tika-app-1.14.jar源码信息:

httpclient-4.4.1源码信息:

解决:

1、先是直接将 tika-app-1.14.jar 删除,发现还是没能解决问题,还是抛出 java.lang.NoClassDefFoundError: Could not initialize class org.apache.http.conn.ssl.SSLConnectionSocketFactory,发现还是没有用到自己(httpclient-4.4.1) AllowAllHostnameVerifier 信息

2、最后将 tika-app-1.14.jar升级到 1.27版本的,解决问题

 

3、问题:为何使用 AllowAllHostnameVerifier该类时,不优先使用自己的呢,会去寻找其他jar的类进行使用,查看源码该httpclient-4.4.1.jar的该类(AllowAllHostnameVerifier)已过时,

而tika-app-1.14.jarr的该类(AllowAllHostnameVerifier)正常使用中,猜测:当有相同全类名时,类加载器会优先使用未过时的api

4、建议:尽可能不使用过时的api或者较低版本的jar,会衍生出其他问题