java与asm的字节码适配问题

发布时间:2026/6/26 5:48:53
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字节码增强的问题具体哪里的问题不清楚。有一个同事协助看了一下说是我写的代码方式的问题。如下MapString, 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.xJava 751ASM 5.xJava 7,对 Java 8 支持不完整51ASM 6.xJava 852ASM 7.xJava 953ASM 8.xJava 1155ASM 9.xJava 15 - Java 17, 及更高版本59 - 61ASM 10.xJava 1761看这个意思如果 asm 升级到 6.x 的话就正常了经过实际验证启动正常。鉴于目前甲方的项目里加 maven 依赖和配置都需要告知一下为了不给自己找麻烦就只能这样了。