java NIO SSO 处理器中的空指针

Posted

技术标签:

【中文标题】java NIO SSO 处理器中的空指针【英文标题】:null pointer in java NIO SSO processor 【发布时间】:2020-08-22 07:01:03 【问题描述】:

尝试在 tomcat 9 上运行 gitblit,偶尔使用 JDK 11 会导致此堆栈跟踪:

gitblit    | 07-May-2020 04:30:39.247 SEVERE [https-jsse-nio-8443-exec-10] org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun Error running socket processor
gitblit    |    java.lang.NullPointerException
gitblit    |            at java.base/sun.security.ssl.HKDF.extract(HKDF.java:93)
gitblit    |            at java.base/sun.security.ssl.HKDF.extract(HKDF.java:119)
gitblit    |            at java.base/sun.security.ssl.ServerHello.setUpPskKD(ServerHello.java:1167)
gitblit    |            at java.base/sun.security.ssl.ServerHello$T13ServerHelloProducer.produce(ServerHello.java:545)
gitblit    |            at java.base/sun.security.ssl.SSLHandshake.produce(SSLHandshake.java:436)
gitblit    |            at java.base/sun.security.ssl.ClientHello$T13ClientHelloConsumer.goServerHello(ClientHello.java:1234)
gitblit    |            at java.base/sun.security.ssl.ClientHello$T13ClientHelloConsumer.consume(ClientHello.java:1170)
gitblit    |            at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.onClientHello(ClientHello.java:852)
gitblit    |            at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.consume(ClientHello.java:813)
gitblit    |            at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
gitblit    |            at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:444)
gitblit    |            at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1061)
gitblit    |            at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1048)
gitblit    |            at java.base/java.security.AccessController.doPrivileged(Native Method)
gitblit    |            at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask.run(SSLEngineImpl.java:995)
gitblit    |            at org.apache.tomcat.util.net.SecureNioChannel.tasks(SecureNioChannel.java:443)
gitblit    |            at org.apache.tomcat.util.net.SecureNioChannel.handshakeUnwrap(SecureNioChannel.java:507)
gitblit    |            at org.apache.tomcat.util.net.SecureNioChannel.handshake(SecureNioChannel.java:238)
gitblit    |            at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1616)
gitblit    |            at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
gitblit    |            at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
gitblit    |            at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
gitblit    |            at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
gitblit    |            at java.base/java.lang.Thread.run(Thread.java:834)

当客户端试图从 gitblit GUI 拉取文件时。

可能感兴趣,在我更新到 JDF 的 11.0.7 版本之前,我看到了这个错误: Open JDK 11 HTTP/2 Handshake ServerHello java.util.NoSuchElementException

这里修复了 Optional 的误用:https://bugs.openjdk.java.net/browse/JDK-8218889 但也许实际上并没有解决根本问题?

或者关于触发此错误的任何其他想法?我在这里使用自签名证书,仅供参考。客户端是火狐,java版本是

openjdk 版本“11.0.7” 2020-04-14 OpenJDK 运行时环境 AdoptOpenJDK (build 11.0.7+10) OpenJDK 64-Bit Server VM AdoptOpenJDK(build 11.0.7+10,混合模式)

在 alpine linux docker 系统中运行。

追查 gitblit 偶尔出现 1 分钟超时的问题,并在日志中找到此问题。不确定是否相关....

貌似在tomcathttps://bz.apache.org/bugzilla/show_bug.cgi?id=64105中也找到了,这里报告了

https://bugs.openjdk.java.net/browse/JDK-8241248

由于我无法提供有关 openjdk 错误跟踪器的信息,因此我可以告诉您,通常会导致该问题的客户端是 linux 上的 Firefox 75。

【问题讨论】:

我同意你的观点,OpenJDK 错误跟踪器是一个持续不断的刺激源。可以得出结论,不欢迎参与 OpenJDK。还是这只是 Oracle 的默认行为? 【参考方案1】:

正如您提供的 bugtracker 引用所指出的,这是一个与会话恢复相关的错误。

虽然此答案并未解决错误本身,但有可能要求 SSLEngine 禁止恢复特定连接。这会降低未来连接的性能,因为客户端需要为新连接重做握手,而不是利用会话恢复机制。

握手建立后的任何时候,您都可以在 SSLSession 上调用invalidate()。正如文档中指出的那样:

未来的连接将无法恢复或加入此会话。但是,任何使用此会话的现有连接都可以继续使用该会话,直到连接关闭。

意味着它对当前连接没有影响,但会阻止会话恢复,从而避免 JDK 错误。

我的握手循环的 sn-p:

case NOT_HANDSHAKING:
case FINISHED:

    if( !sslEngine.getSession().isValid() || sslEngine.getSession().getId().length == 0 )
        throw new SSLHandshakeException("Handshake failed");

    // prevent bug with rejoin session
    sslEngine.getSession().invalidate();

    return;

【讨论】:

以上是关于java NIO SSO 处理器中的空指针的主要内容,如果未能解决你的问题,请参考以下文章

使用 Spring Boot 服务作为批处理作业中的依赖项的空指针异常

java中的空指针异常怎么解决

Kotlinkotlin中的空指针检查

处理来自 JsonReader 的空指针

Kotlin小笔记kotlin中的空指针检查

nullpointerxception——处理思路