JAI ImageIO NoClassDefFoundError для RawImageInputStream
Я очень смущен этим вопросом. Я использую версию 1.3.0 на jai-imageio-core. Пожалуйста, проверьте зависимость ниже, и я совершенно не могу понять, как из jar-файла можно загрузить один файл класса (RawImageReaderSpi) в JVM, но RawImageInputStream не загружен.
Я развернул свой весенний загрузочный веб-сервис в контейнере Tomcat 7.
Эта проблема появляется случайным образом, и я заметил, что после перезапуска контейнера TC и развертывания новой версии моей службы эта проблема периодически появляется.
Любое руководство высоко ценится.
Я провел день, пытаясь выяснить, что не так, и в итоге почувствовал себя глупо
<dependency>
<groupId>com.github.jai-imageio</groupId>
<artifactId>jai-imageio-core</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>com.github.jai-imageio</groupId>
<artifactId>jai-imageio-jpeg2000</artifactId>
<version>1.3.0</version>
</dependency>
java.lang.NoClassDefFoundError: com/github/jaiimageio/stream/RawImageInputStream at com.github.jaiimageio.impl.plugins.raw.RawImageReaderSpi.canDecodeInput(RawImageReaderSpi.java:102) ~ core-jai-image 1.3. core-jai-image jar:1.3.0] в javax.imageio.ImageIO$CanDecodeInputFilter.filter(ImageIO.java:567) ~[na:1.8.0_121] в javax.imageio.spi.FilterIterator.advance(ServiceRegistry.java:821) ~[na:1.8.0_121] в javax.imageio.spi.FilterIterator.(ServiceRegistry.java:815) ~[na:1.8.0_121] в javax.imageio.spi.ServiceRegistry.getServiceProviders(ServiceRegistry.java:516) ~[нет: 1.8.0_121] в javax.imageio.ImageIO.getImageReaders(ImageIO.java:646) ~[na:1.8.0_121] в javax.imageio.ImageIO.read(ImageIO.java:1438) ~[na:1.8.0_121] в javax.imageio.ImageIO.read(ImageIO.java:1352) ~[na:1.8.0_121] в my-package.ab(a.java:155) ~[classes/:na] в my-package.ab(a.java:181) ~[classes/:na] в my-package.ab(a.java:84) ~[classes/:na] в my-package.a$$FastClassBySpringCGLIB$$5f66283f.invoke() ~[весна-ядро-4.1.3.RELEASE.jar: на ] в org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-4.1.3.RELEASE.jar:4.1.3.RELEASE] в org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717) ~[spring-aop-4.1.3.RELEASE.jar:4.1.3.RELEASE] в org.springframework.aop.framework.ReflectiveMethodInvocation.Mevation.Meoc.js: proce ~ [spring-aop-4.1.3.RELEASE.jar: 4.1.3.RELEASE] в org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) ~[spring-tx-4.1.3.RELEASE.jar:4.1.3.RELEASE] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:267) ~[spring-tx-4.1.3.RELEASE.jar:4.1.3.RELEASE] org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.1.3.RELEASE.jar:4.1.3.RELEASE] в org.springframework.aop.framework.ReflectiveMethodInvoc ion.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.1.3.RELEASE.jar:4.1.3.RELEASE] в org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAPro:) ~ [spring-aop-4.1.3.RELEASE.jar: 4.1.3.RELEASE] в my-package.a$$EnhancerBySpringCGLIB$$dfc04a57.b() ~[spring-core-4.1.3.RELEASE.jar:na] в my-package.ab(c.java:165) ~[classes/:na] в my-package.a$$FastClassBySpringCGLIB$$67dbe4b2.invoke() ~[spring-core-4.1.3.RELEASE.jar:na] at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-4.1.3.RELEASE.jar:4.1.3.RELEASE] в org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717) ~[spring-aop-4.1.3.RELEASE.jar:4.1.3.RELEASE] в org.springframework.aoc Java:157) ~[spring-aop-4.1.3.RELEASE.jar:4.1.3.RELEASE] в org.springframework.transaction.interceptor.TransactionInterceptor $ 1.proceedWith Вызов (TransactionInterceptor.java:99) ~ [spring-tx-4.1.3.RELEASE.jar: 4.1.3.RELEASE] в org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction (TransactionAspectSupport.java:267) -tx-4.1.3.RELEASE.jar: 4.1.3.RELEASE] в org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.1.3.RELEASE.jar:4.1.3.RELEASE] в org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.1.3.RELEASE.jar:4.1.3.RELEASE] в org.springframe.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653) ~[spring-aop-4.1.3.RELEASE.jar:4.1.3.RELEASE] в my-package.a $$ EnhancerBySpringCGLIBved.processA3636 () ~ [spring-core-4.1.3.RELEASE.jar: na] в sun.reflect.NativeMethodAccessorImpl.invoke0(собственный метод) ~ [na: 1.8.0_121] в sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.I:62) ~[na:1.8.0_121] в sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_121] в java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_121] в org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65) ~[spring-context-4.1.3.RELEASE.jar:4.1.3.RELEASE] в организации.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-4.1.3.RELEASE.jar:4.1.3.RELEASE] в org.springframework.schedulingRchedunr.run ReschedulingRunnable.java:81) [spring-context-4.1.3.RELEASE.jar:4.1.3.RELEASE] в java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_121] в java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_121] в java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:1.) 0_121] на java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [na:1.8.0_121] в java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_ur.til].ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_121]
2 ответа
Проблема здесь, это известная проблема с ImageIO
плагины и контейнеры (например, контейнер web/servlet). Развертывание плагинов как части веб-приложения не очень хорошо поддерживается ImageIO
,
ImageIO
Реестр, который отслеживает зарегистрированные подключаемые модули, в действительности является глобальным JVM (это фактически реестр для контекста приложения, однако обычно существует только один контекст приложения *).
Самый безопасный вариант - установить плагины (и все их зависимости) в "общую" или "общую" папку lib контейнера. Это гарантирует, что плагины устанавливаются только один раз, и что они доступны для всех контекстов контейнера. Это требует контроля над контейнерной средой, а также может затруднить обновление из-за ручной установки и полного перезапуска контейнера.
Если вы предпочитаете развертывать подключаемые модули как часть веб-приложения, единственный вариант, о котором я знаю, - это использовать
com.twelvemonkeys.servlet.image.IIOProviderContextListener
как описано здесь.В качестве альтернативы, чтобы использовать его в проекте Spring Boot без
web.xml
файл, вы можете добавить следующую строку вonStartup()
метод в вашемSpringBootServletInitializer
подкласс, как описано здесь:servletContext.addListener(IIOProviderContextListener.class);
Обратите внимание, что вы должны выполнить полный перезапуск контейнера после первого включения прослушивателя контекста, так как
ImageIO
может быть уже "загрязнен" от более ранних развертываний.
*) Не путать с контекстами веб-приложения контейнера, которых может быть много.
[Как это может быть, что] один файл класса (
RawImageReaderSpi
) загружается в JVM, ноRawImageInputStream
не загружается?
Это тот случай, упомянутый в ссылке, где одно более раннее развертывание веб-приложения зарегистрировало RawImageReaderSpi
класс в реестре, в то время как остальные классы из этого развертывания были удалены из-за повторного развертывания. RawImageInputStream
класс может быть доступен из нового развертывания, но в качестве нового контекста веб-приложения используется другой ClassLoader
Например, оригинальный класс Spi не может видеть его как тот же класс, который он ищет.
To use this in a Maven project, you need this additional dependency:
<dependency>
<groupId>com.twelvemonkeys.servlet</groupId>
<artifactId>servlet</artifactId>
<version>3.3.2</version>
</dependency>
To use it in a Spring Boot project without a web.xml file, you want to add the following line to the onStartup method in your SpringBootServletInitializer subclass:
servletContext.addListener(IIOProviderContextListener.class);
of course with the following import:
import com.twelvemonkeys.servlet.image.IIOProviderContextListener;
retart tomcat, and it´s work!