我对这个问题很困惑。我在 jai-imageio-core 上使用 1.3.0 版本,请检查下面的依赖项,我完全无法从 jar 中弄清楚如何在 JVM 中加载一个类文件 (RawImageReaderSpi) 但未加载 RawImageInputStream。
我已在 tomcat 7 容器中部署了 Spring Boot Web 服务。
这个问题是随机出现的,我注意到当我重新启动 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) ~[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]
这里的问题是一个已知问题ImageIO
插件和容器(如 Web/servlet 容器)。将插件部署为 Web 应用程序的一部分并没有得到很好的支持ImageIO
.
The ImageIO
registry https://docs.oracle.com/javase/8/docs/api/javax/imageio/spi/IIORegistry.html跟踪注册的插件实际上是 JVM 全局的(它实际上是每个应用程序上下文的注册表,但是,通常只有一个应用程序上下文*)。
最安全的选择是将插件(及其所有依赖项)安装在容器的“共享”或“公共”lib 文件夹中。这可确保插件仅安装一次,并且它们可用于所有容器的上下文。这需要对容器环境进行控制,并且由于需要手动安装和完整的容器重新启动,因此升级也可能很麻烦。
-
如果您更喜欢将插件部署为 Web 应用程序的一部分,我知道的唯一选择是使用com.twelvemonkeys.servlet.image.IIOProviderContextListener
如上所述here https://github.com/haraldk/TwelveMonkeys#deploying-the-plugins-in-a-web-app.
或者,在 Spring Boot 项目中使用它而无需web.xml
文件中,您可以将以下行添加到onStartup()
方法在你的SpringBootServletInitializer
所描述的子类here https://github.com/haraldk/TwelveMonkeys/issues/16#issuecomment-326128071:
servletContext.addListener(IIOProviderContextListener.class);
请注意,您必须完全重启容器第一次启用上下文监听器后,ImageIO
可能已经受到早期部署的“污染”。
*) 不要与容器的 Web 应用程序上下文混淆,容器的 Web 应用程序上下文可能有很多。
[怎么可能]一个类文件(RawImageReaderSpi
) 已加载到 JVM 中,但是RawImageInputStream
没有加载?
这是链接中提到的情况,其中 Web 应用程序的早期部署已注册RawImageReaderSpi
注册表中的类,而由于重新部署,该部署中的其余类已被删除。这RawImageInputStream
class may be可从新部署中使用,但由于新的 Web 应用程序上下文使用不同的ClassLoader
例如,原始 Spi 类无法将其视为它正在查找的同一类。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)