近期在做甲方的项目,里面用的技术体系很老,非 spring boot项目,是 jdk 8 + spring + spring mvc + tomcat + jsp 的方式。遇到了一个问题,在这里记录一下。

自己加了一部分代码功能,启动后报错,如下

24-Jun-2026 20:34:58.436 严重 [RMI TCP Connection(2)-127.0.0.1] org.apache.catalina.core.StandardContext.listenerStart Exception sending context initialized event to listener instance of class [com.sinoservices.xframework.core.context.ContextLoaderListener]
 org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: URL [jar:file:/F:/code/pj-oms/orr-java-webapps/target/orr-java-webapps-0.0.1-SNAPSHOT/WEB-INF/lib/orr-java-0.0.1-SNAPSHOT.jar!/com/sinoservices/orr/edi/send/bean/EipBusinessPriceRequest.class]; nested exception is java.lang.IllegalArgumentException: INVOKESPECIAL/STATIC on interfaces require ASM 5
	at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.findCandidateComponents(ClassPathScanningCandidateComponentProvider.java:290)
	at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:242)
	at org.springframework.context.annotation.ComponentScanBeanDefinitionParser.parse(ComponentScanBeanDefinitionParser.java:84)
	at org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse(NamespaceHandlerSupport.java:73)
	at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1438)
	at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1428)
	at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:195)
	at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:139)
	at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:108)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:493)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:390)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:334)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:174)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:209)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:180)
	at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:125)
	at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.java:94)
	at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:130)
	at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:537)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:451)
	at com.sinoservices.xframework.core.context.module.Module.start(SourceFile:77)
	at com.sinoservices.xframework.core.context.archives.ModuleDeploymentArchives.buildDeploymentArchive(SourceFile:70)
	at com.sinoservices.xframework.core.context.archives.DeploymentArchives.scanArchives(SourceFile:147)
	at com.sinoservices.xframework.core.context.archives.DeploymentArchives.deploy(SourceFile:164)
	at com.sinoservices.xframework.core.context.ContextLoaderListener.contextInitialized(SourceFile:124)
	at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4817)
	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5283)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
	at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:754)
	at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:730)
	at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:734)
	at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1736)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
	at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
	at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
	at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:483)
	at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:432)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
	at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
	at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
	at com.sun.jmx.remote.security.MBeanServerAccessController.invoke(MBeanServerAccessController.java:468)
	at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1468)
	at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:76)
	at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1309)
	at java.security.AccessController.doPrivileged(Native Method)
	at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1408)
	at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:829)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:346)
	at sun.rmi.transport.Transport$1.run(Transport.java:200)
	at sun.rmi.transport.Transport$1.run(Transport.java:197)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:683)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalArgumentException: INVOKESPECIAL/STATIC on interfaces require ASM 5
	at org.springframework.asm.MethodVisitor.visitMethodInsn(Unknown Source)
	at org.springframework.asm.ClassReader.a(Unknown Source)
	at org.springframework.asm.ClassReader.b(Unknown Source)
	at org.springframework.asm.ClassReader.accept(Unknown Source)
	at org.springframework.asm.ClassReader.accept(Unknown Source)
	at org.springframework.core.type.classreading.SimpleMetadataReader.<init>(SimpleMetadataReader.java:64)
	at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:80)
	at org.springframework.core.type.classreading.CachingMetadataReaderFactory.getMetadataReader(CachingMetadataReaderFactory.java:102)
	at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.findCandidateComponents(ClassPathScanningCandidateComponentProvider.java:266)
	... 72 more

只知道是asm字节码增强的问题,具体哪里的问题不清楚。

有一个同事协助看了一下,说是我写的代码方式的问题。如下

Map<String, PurchaseItem> materialCodeAndPurchaseItemMap = ListUtils.emptyIfNull(itemList).stream().collect(Collectors.toMap(PurchaseItem::getProductCode, Function.identity()));

后面我改成了非 java stream 的方式,启动正常,接下来我思考,为什么出现了这个问题

INVOKESTATIC 这个字节码在 jvm 中原来就有的,突然间报这个问题不应该。

问了AI,这么回复的

  • 在 Java 8 之前,接口中只能有抽象方法,invokestatic 指令只用于调用普通类中的静态方法。Java 8 的一个重大语言特性,就是允许在接口中定义静态方法。为了支持这个新特性,JVM 规范修改了 invokestatic 指令,使其能够识别并调用接口中定义的静态方法

这也就是为什么你在使用 Function.identity()(它是 java.util.function.Function 接口的静态方法)时,会触发你之前遇到的 ASM 错误。老版本的 ASM(低于 5.0)不知道 Java 8 这种新玩法,把它当成了错误用法。

又看了一下 asm 与 jdk 的对应关系

ASM 版本 主要支持的 Java 版本 字节码版本
ASM 4.x Java 7 51
ASM 5.x Java 7, 对 Java 8 支持不完整 51
ASM 6.x Java 8 52
ASM 7.x Java 9 53
ASM 8.x Java 11 55
ASM 9.x Java 15 - Java 17, 及更高版本 59 - 61+
ASM 10.x Java 17 61

看这个意思,如果 asm 升级到 6.x 的话就正常了,经过实际验证,启动正常。

鉴于目前甲方的项目里加 maven 依赖和配置都需要告知一下,为了不给自己找麻烦,就只能这样了。

更多推荐