使用java.net.http.HttpClient时HttpResponse.body为null是什么原因?
问题根因与修复方案
触发原因
你遇到的是OpenJDK 11早期维护版本的已知缺陷,该缺陷在Amazon Corretto 11.0.13中仍然存在:当服务端返回无响应体的HTTP响应(包括204 No Content、304 Not Modified,或者网络链路中代理返回的1xx类信息响应未被正常过滤的场景)时,BodyHandlers.ofInputStream()会直接返回null而非空的InputStream实例,导致后续构造InputStreamReader时触发空指针。该缺陷在11.0.16及更高版本的Corretto 11中已经被官方修复。
偶发无法复现的原因是该场景仅在目标服务端/链路代理返回无体响应时才会触发,正常业务请求下服务端返回200带响应体的逻辑不受影响。
修复方案
临时兼容方案
在处理响应体前先做空校验,同时提前记录响应状态码、响应头等上下文信息,方便定位故障,示例修改代码如下:
try { final HttpResponse<InputStream> response = HttpClient.newHttpClient().send(HttpRequest.newBuilder(new URI( "https://api.cognitive.microsofttranslator.com/languages?api-version=3.0&scope=translation")).GET() .build(), BodyHandlers.ofInputStream()); // 先记录全链路上下文信息,生产环境可替换为对应日志框架输出 int statusCode = response.statusCode(); System.out.printf("请求返回状态码:%d%n", statusCode); response.headers().map().forEach((k, v) -> System.out.printf("响应头%s:%s%n", k, String.join(",", v))); InputStream responseBody = response.body(); if (responseBody == null) { // 封装上下文抛出业务异常,避免直接捕获NPE丢失故障信息 throw new IOException(String.format("请求返回空响应体,状态码:%d", statusCode)); } try (BufferedReader reader = new BufferedReader(new InputStreamReader(responseBody))) { reader.lines().forEach(System.out::println); } } catch (IOException | InterruptedException | URISyntaxException e) { e.printStackTrace(); }
长期修复方案
将运行环境的Amazon Corretto 11版本升级到11.0.16及以上的更新版本,官方在该版本中修复了该缺陷,无响应体场景下BodyHandlers.ofInputStream()会返回空输入流而非null,不会再触发空指针异常。
内容的提问来源于stack exchange,提问作者JackPGreen
相关产品推荐
相关产品推荐

