JAI ImageIO NoClassDefFoundError for RawImageInputStream

ぐ巨炮叔叔 提交于 2021-02-07 08:55:04

问题


I am very confused with this issue. I am using 1.3.0 version on jai-imageio-core please check the dependecy below and I am at complete loss to figure out from the jar how can one class file (RawImageReaderSpi) is loaded in JVM but RawImageInputStream is not loaded.

I have deployed my spring boot web service in tomcat 7 container.

This issue pops up randomly and I have noticed that when I have restarted the TC container and deployed new version of my service, this issue shows up intermittently.

Any lead is highly appreciated.

I have spent a day trying to figure out what is wrong and ended up feeling stupid

<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) ~[jai-imageio-core-1.3.0.jar:1.3.0]
        at javax.imageio.ImageIO$CanDecodeInputFilter.filter(ImageIO.java:567) ~[na:1.8.0_121]
        at javax.imageio.spi.FilterIterator.advance(ServiceRegistry.java:821) ~[na:1.8.0_121]
        at javax.imageio.spi.FilterIterator.(ServiceRegistry.java:815) ~[na:1.8.0_121]
        at javax.imageio.spi.ServiceRegistry.getServiceProviders(ServiceRegistry.java:516) ~[na:1.8.0_121]
        at javax.imageio.ImageIO.getImageReaders(ImageIO.java:646) ~[na:1.8.0_121]
        at javax.imageio.ImageIO.read(ImageIO.java:1438) ~[na:1.8.0_121]
        at javax.imageio.ImageIO.read(ImageIO.java:1352) ~[na:1.8.0_121]
        at my-package.a.b(a.java:155) ~[classes/:na]
        at my-package.a.b(a.java:181) ~[classes/:na]
        at my-package.a.b(a.java:84) ~[classes/:na]
        at my-package.a$$FastClassBySpringCGLIB$$5f66283f.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]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717) ~[spring-aop-4.1.3.RELEASE.jar:4.1.3.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.1.3.RELEASE.jar:4.1.3.RELEASE]
        at 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]
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.1.3.RELEASE.jar:4.1.3.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.1.3.RELEASE.jar:4.1.3.RELEASE]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653) ~[spring-aop-4.1.3.RELEASE.jar:4.1.3.RELEASE]
        at my-package.a$$EnhancerBySpringCGLIB$$dfc04a57.b() ~[spring-core-4.1.3.RELEASE.jar:na]
        at my-package.a.b(c.java:165) ~[classes/:na]
        at 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]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717) ~[spring-aop-4.1.3.RELEASE.jar:4.1.3.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.1.3.RELEASE.jar:4.1.3.RELEASE]
        at 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]
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.1.3.RELEASE.jar:4.1.3.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.1.3.RELEASE.jar:4.1.3.RELEASE]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653) ~[spring-aop-4.1.3.RELEASE.jar:4.1.3.RELEASE]
        at my-package.a$$EnhancerBySpringCGLIB$$d153236a.processApprovedApplications() ~[spring-core-4.1.3.RELEASE.jar:na]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_121]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_121]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_121]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_121]
        at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65) ~[spring-context-4.1.3.RELEASE.jar:4.1.3.RELEASE]
        at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-4.1.3.RELEASE.jar:4.1.3.RELEASE]
        at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81) [spring-context-4.1.3.RELEASE.jar:4.1.3.RELEASE]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_121]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_121]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_121]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [na:1.8.0_121]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_121]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_121]

回答1:


The problem here, is a known issue with ImageIO plug-ins and containers (like a web/servlet container). Deploying plug-ins as part of the web application is not well supported by ImageIO.

The ImageIO registry that keeps track of registered plug-ins is in effect JVM global (it is actually a registry per application context, however, there is usually only a single application context*).

  • The safest option is install the plug-ins (and all their dependencies) in the container's "shared" or "common" lib folder. This ensures that the plug-ins are only installed once, and that they are available to all the container's contexts. This requires control of the container environment, and also may be a hassle to upgrade, due to manual install and full container restart required.

  • If you prefer to deploy the plug-ins as part of the web application, the only option I know of, is to use the com.twelvemonkeys.servlet.image.IIOProviderContextListener as described here.

    Altenatively, to use it in a Spring Boot project without a web.xml file, you can add the following line to the onStartup() method in your SpringBootServletInitializer subclass as described here:

    servletContext.addListener(IIOProviderContextListener.class);
    

    Note that you must do a full restart of the container after enabling the context listener for the first time, as the ImageIO may already be "polluted" from earlier deployments.

*) Not to be confused with the container's web application contexts, which there may be many of.


[How can it be that] one class file (RawImageReaderSpi) is loaded in JVM but RawImageInputStream is not loaded?

This is the case mentioned in the link, where one earlier deployment of the web application has registered the RawImageReaderSpi class in the registry, while the rest of the classes from that deployment has been removed, due to a re-deployement. The RawImageInputStream class may be available from the new deployment, but as the new web application context uses a different ClassLoader instance, the original Spi class can't see it as the same class it's looking for.



来源:https://stackoverflow.com/questions/48295907/jai-imageio-noclassdeffounderror-for-rawimageinputstream

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!