最近,Opensource.com 的同事 James Farrell 撰写了一篇精彩的文章,题为 Ansible 如何给我的家庭带来了和平。 除了这篇很棒的文章,我真的很喜欢这个标题,这是一个意想不到的短语,我相信它给很多人带来了微笑。
最近,我也有过一次奇怪但积极的经历,这也需要一个类似的意想不到的标签。在升级一些服务器和网络基础设施时,我遇到了一个难题,这导致我自 2000 年代初以来一直支持的一个 Java 应用程序崩溃了。奇怪的是,我在一篇关于 Kubernetes 的文章中找到了解决方案,这似乎是一篇非常informative和出色的文章。
废话不多说,这是我的问题

我猜大多数读者看到这条消息会想,“我希望日志文件中有更多信息”,或者“我真的很高兴我从来没有收到过这样的消息。”
不幸的是,日志文件中没有太多信息,实际上只有相同的消息。为了调试这个问题,我做了三件事
-
我在网上搜索了这条消息。有趣的是,或者说可能是不祥的是,只有大约 200 个关于这个字符串的搜索结果,其中一个建议 打开更多调试输出,这涉及到添加设置
-Djavax.net.debug=ssl:handshake:verbose
到运行应用程序的 java 命令。
-
我尝试了这个建议,结果产生了很多输出(很好),其中大部分对我来说只是模糊地有意义,因为我不是 SSL 等底层技术的专家。但我确实注意到的一件事是,在所有这些输出中,没有关于服务器响应的信息;
-
所以我搜索了更多。
这个问题的另一个有趣之处在于,当使用 OpenJDK 中捆绑的 Java 命令执行时,代码运行良好,但当使用以这种方式从同一 OpenJDK 创建的定制运行时时,代码会失败并出现此错误。因此,从上面搜索 #1 中出现的相对较少的明显相似问题实际上并不都那么相关,因为它们似乎主要处理服务器上错误的 SSL 证书,以及 PostgreSQL JDBC 检查服务器凭据的能力。
我还应该提到,我花了一段时间才意识到问题是由使用自定义 Java 运行时引入的,因为我在此过程中设法检查了许多其他可能性(事实上,我也修复了一些小错误)。我的努力包括获取最新的 OpenJDK,检查并重新检查所有 URL 以防出现拼写错误等等。
正如经常发生的那样,在将问题搁置几个小时后,我突然想到一个主意——也许我在自定义 Java 运行时中缺少某些模块。虽然我没有收到任何直接表明该问题的错误,但标准 OpenJDK 环境有效而自定义环境失败这一可观察的事实似乎暗示了这种可能性。我在 OpenJDK 安装的 jmods/ 文件夹中快速看了一下,但那里大约有 70 个模块,没有什么引起我的注意。
但同样,奇怪的是,在打开调试的情况下(参见上面的 #1),没有迹象表明服务器会接受什么,只是客户端主要无法提供什么,很多行都像这样
Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
所以此时我至少在想,也许缺少的是提供这些类型的密码套件的模块。所以我开始使用“jdbc crypto”之类的字符串进行搜索,在搜索过程中,最不可能的文章出现了:优化 Kubernetes 服务—第 2 部分:Spring Web,由 Juan Medina 撰写。在文章的中途,我发现了以下内容

哈!想象一下,他的脚本正在创建一个自定义 Java 运行时,就像我的脚本一样。但他说他需要手动添加模块 jdk.crypto.ec 才能通过 SSL 连接到他的 PostgreSQL 环境。听起来很熟悉。
事实上,这也是我问题的解决方案;缺少的模块是 jdk.crypto.ec,我能够按如下方式将其添加到我的构建中
DEPS=$(JAVA_HOME)/bin/jdeps --print-module-deps $(TEST_HOME)/MyApp.jar \ $(TEST_HOME)/lib/*.jar,jdk.crypto.ec;
$(JAVA_HOME)/bin/jlink --module-path $(W64_JAVA_HOME)/jmods
–no-header-files --no-man-pages --compress=2 –strip-debug
–add-modules $$DEPS --output $(TEST_HOME)/java-runtime
(我在这里交叉构建 Windows Java 运行时;有关更多信息,请参阅我之前关于此主题的文章)。
结论
对于像我这样不太了解加密技术的人来说,这真是一个很大的躲避。再一次,开源,以及更重要的是,与开源相关的共享意愿,是非常重要的。哇,使用 Kubernetes 来修复 Java 桌面应用程序,这也太棒了!再次感谢 Juan Medina!
6 条评论