JAI ImageIO NoClassDefFoundError for RawImageInputStream [英] JAI ImageIO NoClassDefFoundError for RawImageInputStream

查看:76
本文介绍了JAI ImageIO NoClassDefFoundError for RawImageInputStream的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对这个问题很困惑.我在 jai-imageio-core 上使用 1.3.0 版本,请检查下面的依赖关系,我完全无法从 jar 中找出一个类文件 (RawImageReaderSpi) 是如何加载到 JVM 中的,但未加载 RawImageInputStream.

我已经在 tomcat 7 容器中部署了我的 Spring Boot Web 服务.

这个问题是随机弹出的,我注意到当我重新启动 TC 容器并部署新版本的服务时,这个问题会间歇性地出现.

任何线索都受到高度赞赏.

我花了一天的时间试图找出问题所在,结果却觉得自己很愚蠢

<依赖><groupId>com.github.jai-imageio</groupId><artifactId>jai-imageio-core</artifactId><version>1.3.0</version></依赖><依赖><groupId>com.github.jai-imageio</groupId><artifactId>jai-imageio-jpeg2000</artifactId><version>1.3.0</version></依赖>

java.lang.NoClassDefFoundError: com/github/jaiimageio/stream/RawImageInputStream在 com.github.jaiimageio.impl.plugins.raw.RawImageReaderSpi.canDecodeInput(RawImageReaderSpi.java:102) ~[jai-imageio-core-1.3.0.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) ~[na: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.a.b(a.java:155) ~[classes/:na]在 my-package.a.b(a.java:181) ~[classes/:na]在 my-package.a.b(a.java:84) ~[classes/:na]在 my-package.a$$FastClassBySpringCGLIB$$5f66283f.invoke() ~[spring-core-4.1.3.RELEASE.jar:na]在 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.proceed(ReflectiveMethodInvocation.java:157) ~[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]在 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.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.1.3.RELEASE.jar:4.1.3.RELEASE]在 org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653) ~[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.a.b(c.java:165) ~[classes/:na]在 my-package.a$$FastClassBySpringCGLIB$$67dbe4b2.invoke() ~[spring-core-4.1.3.RELEASE.jar:na]在 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.proceed(ReflectiveMethodInvocation.java:157) ~[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]在 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.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.1.3.RELEASE.jar:4.1.3.RELEASE]在 org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653) ~[spring-aop-4.1.3.RELEASE.jar:4.1.3.RELEASE]在 my-package.a$$EnhancerBySpringCGLIB$$d153236a.processApprovedApplications() ~[spring-core-4.1.3.RELEASE.jar:na]在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_121]在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java: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]在 org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-4.1.3.RELEASE.jar:4.1.3.RELEASE]在 org.springframework.scheduling.concurrent.ReschedulingRunnable.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:180) [na:1.8.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_121]在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_121]

解决方案

这里的问题是 ImageIO 插件和容器(如 web/servlet 容器)的一个已知问题.ImageIO 不太支持将插件部署为 Web 应用程序的一部分.

ImageIO registry 跟踪已注册的插件实际上是 JVM 全局的(它实际上是每个应用程序上下文的注册表,但是,通常只有一个应用程序上下文*).

  • 最安全的选择是将插件(及其所有依赖项)安装在容器的共享"或公共"lib 文件夹中.这确保插件只安装一次,并且它们可用于所有容器的上下文.这需要控制容器环境,并且由于需要手动安装和完整的容器重启,升级起来也很麻烦.

  • 如果您更喜欢将插件部署为 Web 应用程序的一部分,我所知道的唯一选择是使用 com.twelvemonkeys.servlet.image.IIOProviderContextListener 作为在此处进行了描述.

    或者,要在没有 web.xml 文件的 Spring Boot 项目中使用它,您可以将以下行添加到 onStartup() 方法中的 >SpringBootServletInitializer 子类,如此处:

    servletContext.addListener(IIOProviderContextListener.class);

    请注意,您必须在第一次启用上下文侦听器后完全重新启动容器,因为 ImageIO 可能已经从早期部署中污染"了.

*) 不要与容器的 Web 应用程序上下文混淆,后者可能有很多.

<小时><块引用>

[怎么可能] JVM 中加载了一个类文件(RawImageReaderSpi),但是RawImageInputStream 未加载?

这是链接中提到的情况,Web 应用程序的一个较早部署已在注册表中注册了 RawImageReaderSpi 类,而该部署中的其余类已被删除,原因是重新部署.RawImageInputStream可能在新部署中可用,但由于新的 Web 应用程序上下文使用不同的 ClassLoader 实例,原始 Spi 类可以不把它看作是它正在寻找的同一个类.

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]

解决方案

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.

这篇关于JAI ImageIO NoClassDefFoundError for RawImageInputStream的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆