我的工作项目使用kotlin +spring。
当我试图在MacBook apple-m1计算机上运行一个具有类似于apple-m1的空间的测试用例时,我发现了这个问题。
示例
@Test
@Transactional
fun `should success when setting key is api updatable`()然后JVM抛出包含堆栈跟踪的异常,如下所示
Caused by: java.lang.ClassFormatError: Illegal method name "should success when setting key is api updatable" in class com/xxx/xxx/web/rest/CompanySettingResourceIntTest$$EnhancerBySpringCGLIB$$f0902682这种情况发生在我的MacBook m1机器上,但从没有发生在英特尔机器上。
我试图研究这个问题,然后我发现当在bean中使用@Transactional时,spring-aop将使用方法java.lang.ClassLoader.defineClass创建代理类。
我有很多这样的方法,很容易读懂。我是否可以使用包含space的方法名在m1机器中运行,如何修复它?
谢谢。
环境
(我尝试使用spring-boot2+JUnit5 5测试用例来实现POC,用例名称包含空间是可以的。)但是bean中的一个方法也抛出了Illegal method name。)
JUnit日志(运行测试)
Could not generate CGLIB subclass of class com.xxx.xxx.web.rest.CompanySettingResourceIntTest: Common causes of this problem include using a final class or a non-visible class; nested exception is org.springframework.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class com.xxx.xxx.web.rest.CompanySettingResourceIntTest: Common causes of this problem include using a final class or a non-visible class; nested exception is org.springframework.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:204)
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:109)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:466)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:349)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:298)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:421)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1635)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:398)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:119)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at org.junit.vintage.engine.execution.RunnerExecutor.execute(RunnerExecutor.java:40)
at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.Iterator.forEachRemaining(Iterator.java:116)
at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:485)
at org.junit.vintage.engine.VintageTestEngine.executeAllChildren(VintageTestEngine.java:80)
at org.junit.vintage.engine.VintageTestEngine.execute(VintageTestEngine.java:71)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:92)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$100(JUnitPlatformTestClassProcessor.java:77)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:73)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
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.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
at com.sun.proxy.$Proxy2.stop(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:131)
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.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:155)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:137)
at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.springframework.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:345)
at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:492)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:93)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:91)
at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61)
at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:116)
at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:291)
at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:480)
at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:337)
at org.springframework.aop.framework.ObjenesisCglibAopProxy.createProxyClassAndInstance(ObjenesisCglibAopProxy.java:55)
at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:201)
... 73 more
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.GeneratedMethodAccessor82.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:459)
at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:336)
... 86 more
Caused by: java.lang.ClassFormatError: Illegal method name "should success when setting key is api updatable" in class com/xxx/xxx/web/rest/CompanySettingResourceIntTest$$EnhancerBySpringCGLIB$$f0902682
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:756)
... 91 more发布于 2022-01-11 01:52:35
您可能会碰到在Spring5.1中修复的春季一期#21674。如果这是一个选项,您可能想升级。似乎有一种解决办法忽略了这些方法。如果你不介意的话,我不知道。
一些背景信息:您的目标方法是事务性的,因此Spring试图为它创建一个CGLIB代理。我在一个简单的Spock ( Groovy )测试中很快证实,CGLIB似乎无法正确地处理包含空格的方法,因为它根本不知道Groovy和Kotlin这样的语言允许这样的东西。这里是一个概念的证明。我使用Groovy和Spock,因为我很懒,不想设置Kotlin项目。但我希望结果是一样的。
测试中的Java类:
package de.scrum_master.stackoverflow.q70654015;
public class SampleJava {
public String greet(String input) {
return "Hello " + input + "!";
}
}测试中的Groovy类:
package de.scrum_master.stackoverflow.q70654015
class SampleGroovy {
String "say hello to"(String input) {
"Hello $input!"
}
}Spock测试创建CGLIB代理:
package de.scrum_master.stackoverflow.q70654015
import net.sf.cglib.proxy.Enhancer
import net.sf.cglib.proxy.MethodInterceptor
import spock.lang.Specification
class CGLIBProxyTest extends Specification {
def "create CGLIB proxy for Java class"() {
given:
Enhancer enhancer = new Enhancer()
enhancer.superclass = SampleJava
enhancer.callback = { obj, method, args, proxy ->
method.getDeclaringClass() != Object.class && method.getReturnType() == String.class
? "Hello cglib!"
: proxy.invokeSuper(obj, args)
} as MethodInterceptor
when:
SampleJava proxy = enhancer.create()
then:
proxy.greet("world") == "Hello cglib!"
}
def "create CGLIB proxy for Groovy class with spaces in method name"() {
given:
Enhancer enhancer = new Enhancer()
enhancer.superclass = SampleGroovy
enhancer.callback = { obj, method, args, proxy ->
method.getDeclaringClass() != Object.class && method.getReturnType() == String.class
? "Hello cglib!"
: proxy.invokeSuper(obj, args)
} as MethodInterceptor
when:
SampleGroovy proxy = enhancer.create()
then:
proxy."say hello to"("world") == "Hello cglib!"
}
}第一个测试通过,第二个测试失败:
net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:345)
at net.sf.cglib.proxy.Enhancer.generate(Enhancer.java:492)
at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:93)
at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:91)
at net.sf.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at net.sf.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61)
at net.sf.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:116)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:291)
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:480)
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:305)
at de.scrum_master.stackoverflow.q70654015.CGLIBProxyTest.create CGLIB proxy for Groovy class with spaces in method name(CGLIBProxyTest.groovy:36)
Caused by: java.lang.reflect.InvocationTargetException
at net.sf.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:459)
at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:336)
... 12 more
Caused by: java.lang.ClassFormatError: Illegal method name "say hello to" in class de/scrum_master/stackoverflow/q70654015/SampleGroovy$$EnhancerByCGLIB$$ef703cf1
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
... 14 more这是你所经历过的同样的错误。一旦将Groovy方法重命名为JVM中的合法方法,测试就会通过。
关于你说这种行为应该取决于硬件或操作系统平台的说法,我不同意。我认为您的运行时环境可能存在差异。你如何建立和运行你的项目?Maven,Gradle,还有别的事吗?
更新:我有好消息要告诉您:我已经在JDK 8和15以及cglib:cglib-nodep:3.2.6上运行了我的测试。升级到CGLIB 3.3.0时,测试开始通过。因此,您可能希望在Maven POM的<dependencyManagement>部分(或任何与Gradle等效的版本)中管理CGLIB。也许能帮上忙。请注意,有些工具也可能依赖于cglib:cglib,所以您也想要对其进行版本管理。也就是说,确保您使用这些版本:
cglib:cglib-nodep:3.3.0cglib:cglib:3.3.0 (如果它在应用程序中使用)更新2:我不是一个普通的用户,所以我忘记了Spring (工件org.springframework:spring-core)包含自己的CGLIB版本,重新定位到基本包名org.springframework.cglib。在我的独立示例中,请注意从堆栈跟踪到原始net.sf.cglib的包名差异。
我为您检查并发现,自版本5.2.0.RELEASE以来,Spring是升级到CGLIB 3.3.0。因此,如果您可以使用SpringVersion5.2.0或更近期的版本,那么它很可能适合您。
https://stackoverflow.com/questions/70654015
复制相似问题