我正在开发一个在JBoss 7环境中运行的应用程序,因此必须最大限度地使用Java 7(AFAIK JBoss 7.没有在Java 8+上运行,因为他们做了一些肮脏的把戏,或者使用了从Java 7变为8的东西(源代码(。
我面临的问题是:我请求某个只支持TLSv1.2的远程https url,并且第一个请求成功。
任何进一步的请求都会失败,但以下情况除外:
Caused by: java.lang.NullPointerException
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:986)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:177)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1092)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:250)
at <our code>
<our code>
看起来像这样:
URL url = new URL( "https://..." );
URLConnection urlConnection = url.openConnection();
urlConnection.setUseCaches( false );
urlConnection.setRequestProperty( "User-Agent", "java.net.URLConnection/" );
//Here's where we finally get the exception
OuputStream out = urlConnection.getOutputStream();
通常情况下,NPE并不是什么大问题,只要进行一点调试就可以帮助发现错误。然而,由于它发生在专有类(sun.net…..(中,我无法获得这些类的源代码,至少在一个看起来正确的版本中是这样的(一个版本看起来像986:connected = true;
——几乎不是NPE的源代码(。
这在Oracle JDK 1.7.0u80和OpenJDK 7u75中都会发生。
有什么想法吗?
在@yole的帮助下,终于找到了错误。
来源并不准确,所以我不能100%确定实际原因,但在我们的案例中,注册了一个自定义ProxySelector
,在调用该代码时似乎引发了异常,该代码是plainConnect()
的一部分,大约在986:行
ProxySelector sel =
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<ProxySelector>() {
public ProxySelector run() {
return ProxySelector.getDefault();
}
});
正如我所说,源代码被关闭是因为我找不到确切的版本,但寻找与ProxySelector相关的自定义代码帮助很大(在99.9%的情况下,是我们的代码以某种方式造成了问题(。
这仍然不能解释NPE,因为我能找到的所有版本都设置了一些boolen标志、注释或处理IOException
(catch子句或纯rethrow(,但由于删除了自定义选择器解决了问题,我很高兴。
我希望,如果其他人遇到类似的问题,这将有助于减轻他们的头痛。