Java-сервлеты и ошибка ImageIO
Я пытаюсь написать веб-приложение, которое просматривает некоторые файлы DICOM. Моя идея состояла в том, чтобы преобразовать файлы DICOM в JPEG на лету, вызвав мой сервлет. Я использую dcm4che 2.0.27 для конвертации файлов.
Сервлет называется как
<img src="pathToServlet/PathToDICOMFile">.
Проблема: Когда у меня много тегов (конечно, для разных файлов DICOM), иногда я получаю исключение типа java.util.ConcurrentModificationException
Вот метод, который вызывает мой сервлет:
void convertFile(String path, OutputStream to) throws IOException {
File myDicomFile = new File(path);
BufferedImage myJpegImage = null;
ImageIO.scanForPlugins();
Iterator<ImageReader> iter = ImageIO.getImageReadersByFormatName("DICOM");
ImageReader reader = (ImageReader) iter.next();
DicomImageReadParam param = (DicomImageReadParam) reader.getDefaultReadParam();
ImageInputStream iis = ImageIO.createImageInputStream(myDicomFile);
reader.setInput(iis, false);
myJpegImage = reader.read(0, param);
iis.close();
ImageIO.write(myJpegImage, "JPEG", to);
to.close();
}
"путь" - это абсолютный путь к файлу dicom, а "out" - просто response.getOutputStream().
Исключение можно выбросить в 3 местах:
- ImageIO.getImageReadersByFormatName ("DICOM");
- myJpegImage = reader.read (0, param);
- ImageIO.write (myJpegImage, "JPEG", to);
Вот трассировка стека, куда она была брошена при вызове ImageIO.getImageReadersByFormatName("DICOM"):
java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:806)
at java.util.HashMap$ValueIterator.next(HashMap.java:835)
at javax.imageio.spi.PartialOrderIterator.<init>(PartiallyOrderedSet.java:177)
at javax.imageio.spi.PartiallyOrderedSet.iterator(PartiallyOrderedSet.java:85)
at javax.imageio.spi.SubRegistry.getServiceProviders(ServiceRegistry.java:759)
at javax.imageio.spi.ServiceRegistry.getServiceProviders(ServiceRegistry.java:451)
at javax.imageio.spi.ServiceRegistry.getServiceProviders(ServiceRegistry.java:507)
at javax.imageio.ImageIO.getImageReadersByFormatName(ImageIO.java:708)
at example.project.dicomtest.myDicomConverter.ConvertHelper.convertFile(ConvertHelper.java:32)
at example.project.dicomtest.myDicomConverter.GetImage.doGet(GetImage.java:40)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:185)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:151)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
at org.apache.catalina.core.StandardEnginateValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:405)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:269)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:515)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Это потому, что ImageIO не является потокобезопасным? Что я могу сделать, чтобы решить эту проблему? Большое спасибо за любую помощь и наилучшие пожелания!
2 ответа
Эти две строки:
ImageIO.scanForPlugins();
Iterator<ImageReader> iter = ImageIO.getImageReadersByFormatName("DICOM");
Это нужно сделать только один раз, когда ваше приложение загружается или ваш сервлет инициализирован. В частности, первая строка ImageIO.scanForPlugins()
мутирует совместно используемые данные, используемые классом ImageIO внутри. Вероятно, это причина ваших одновременных исключений модификации. Попробуйте переместить эти две строки либо в фильтр сервлета, либо в init(ServletConfig)
метод вашего сервлета.
Используйте синхронизированные методы, чтобы предотвратить одновременную модификацию. прочитайте этот вопрос
stackru.com/questions/9884148/use-of-synchronized-method-in-affable-bean-shopping-cart