我在使用多线程环境中的
Image IO帮助读取
Java图像时遇到问题.只有多个线程尝试读取图像时才会出现问题.
java.awt.color.CMMException: LCMS error 13: Couldn't link the profiles
无论我如何阅读图像,通过ImageIO.read或使用ImageReader.
源数据(图像)完全隔离且不可变.
这个问题可能与:
https://bugs.openjdk.java.net/browse/JDK-8041429和
https://bugs.openjdk.java.net/browse/JDK-8032243
问题是有没有其他方法可以使用具有多个线程的ImageIO读取JPEG文件.看起来ImageIO中存在问题,共享我无法控制的图像颜色配置文件的可变状态.我看到的唯一解决方案是在JVM级别完全隔离它,这听起来不错.
我使用的是Oracle JDK 8u25.更改JDK更新版本对问题没有影响(不是主要版本),我不能在不重写大块代码的情况下使用JDK 7.
代码供参考.
ImageInputStream input = new MemoryCacheImageInputStream(inputStream); Iterator<ImageReader> readers = ImageIO.getImageReaders(input); if (!readers.hasNext()) { throw new IllegalArgumentException("No reader for: " + dataUuid.toString()); } ImageReader reader = readers.next(); try { reader.setInput(input); BufferedImage image = reader.read(0,reader.getDefaultReadParam());
解决方法
在JVM start上添加一个钩子.在钩子中,只需:
Class.forName("javax.imageio.ImageIO");
这将强制类加载器加载类并执行它需要的任何静态初始化.我认为你的问题是在线程上加载了类,而第二个线程正在尝试使用ImageIO,这会导致在颜色配置文件上获得锁定(或缺少锁定)的冲突.
编辑:您也可以将此行添加到您的主页.确保它是您拨打的第一行.
ImageIO不是负责ColorSpace初始化的类.
Class.forName("java.awt.color.ICC_ColorSpace"); Class.forName("sun.java2d.cmm.lcms.LCMS");
诀窍很难.