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!
Другие вопросы по тегам