Java调用setFromTree偶发StringTokenizer空指针异常问题咨询
偶发StringTokenizer空指针异常问题排查结论
问题现象
开发过程中偶发位于java.base/java.util.StringTokenizer.isDelimiter的NullPointerException,无法稳定复现。
异常堆栈:
java.base/java.util.StringTokenizer.isDelimiter(Unknown Source), java.base/java.util.StringTokenizer.scanToken(Unknown Source), java.base/java.util.StringTokenizer.countTokens(Unknown Source), com.sun.media.imageio.plugins.tiff.TIFFField.createFromMetadataNode(TIFFField.java:476), com.sun.media.imageioimpl.plugins.tiff.TIFFImageMetadata.parseIFD(TIFFImageMetadata.java:1576), com.sun.media.imageioimpl.plugins.tiff.TIFFImageMetadata.mergeNativeTree(TIFFImageMetadata.java:1600), com.sun.media.imageioimpl.plugins.tiff.TIFFImageMetadata.mergeTree(TIFFImageMetadata.java:1624), java.desktop/javax.imageio.metadata.IIOMetadata.setFromTree(Unknown Source)
触发调用代码:
// metaData 类型为 javax.imageio.metadata.IIOMetadata // node 类型为 org.w3c.dom.Node // formatName 值为 "com_sun_media_imageio_plugins_tiff_image_1.0" metaData.setFromTree(formatName, node);
运行环境为Adopt OpenJDK OpenJ9 11.0.4。
根因判断
该异常不是JVM本身Bug导致,核心原因有两点:
StringTokenizer.isDelimiter触发空指针的唯一前置条件是构造时传入的分隔符参数为null,此时方法内调用delim.charAt()会直接抛出NPE。- 对应堆栈中旧版本
com.sun.media.imageioTIFF处理包的TIFFField.createFromMetadataNode逻辑,读取TIFF节点属性值后直接传入StringTokenizer做分隔处理,没有做非空校验。当传入的DOM节点存在属性值为null的情况时,就会触发该异常。
问题偶发无法复现通常由两类场景触发:
- 待解析的TIFF文件元数据偶发损坏、字段缺失
- 代码中存在多线程并发操作
IIOMetadata或DOMNode实例的情况:这两类对象都不是线程安全的,并发读写时会随机出现属性读取为null的异常。
目前公开的JDK 11.0.4 OpenJ9版本缺陷列表中,不存在会触发该场景StringTokenizer空指针的已知Bug。
修复建议
- 排查代码中IIOMetadata、DOM Node实例的使用逻辑,禁止跨线程共享这两类非线程安全对象,保证同一时间只有一个线程操作对应实例。
- 升级TwelveMonkeys TIFF图像插件到最新稳定版本,新版本已经补充了TIFF字段解析的空值校验逻辑,不会因为单个属性为null直接抛出空指针。
- 传入解析逻辑前先对Node节点做合法性校验,提前过滤结构损坏、必填属性缺失的元数据节点。
内容的提问来源于stack exchange,提问作者extremecoder85
相关产品推荐
相关产品推荐

