java与asm的字节码适配问题
·
近期在做甲方的项目,里面用的技术体系很老,非 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 依赖和配置都需要告知一下,为了不给自己找麻烦,就只能这样了。
更多推荐

所有评论(0)