首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >苹果硅上的spring (M1):非法方法名称

苹果硅上的spring (M1):非法方法名称
EN

Stack Overflow用户
提问于 2022-01-10 14:30:42
回答 1查看 416关注 0票数 1

我的工作项目使用kotlin +spring。

当我试图在MacBook apple-m1计算机上运行一个具有类似于apple-m1的空间的测试用例时,我发现了这个问题。

示例

代码语言:javascript
复制
@Test
@Transactional
fun `should success when setting key is api updatable`()

然后JVM抛出包含堆栈跟踪的异常,如下所示

代码语言:javascript
复制
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机器中运行,如何修复它?

谢谢。

环境

  • JDK版本1.8 (AArch64)
  • 弹簧引导1.5.16
  • JUnit 4

(我尝试使用spring-boot2+JUnit5 5测试用例来实现POC,用例名称包含空间是可以的。)但是bean中的一个方法也抛出了Illegal method name。)

JUnit日志(运行测试)

代码语言:javascript
复制
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
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-01-11 01:52:35

您可能会碰到在Spring5.1中修复的春季一期#21674。如果这是一个选项,您可能想升级。似乎有一种解决办法忽略了这些方法。如果你不介意的话,我不知道。

一些背景信息:您的目标方法是事务性的,因此Spring试图为它创建一个CGLIB代理。我在一个简单的Spock ( Groovy )测试中很快证实,CGLIB似乎无法正确地处理包含空格的方法,因为它根本不知道Groovy和Kotlin这样的语言允许这样的东西。这里是一个概念的证明。我使用Groovy和Spock,因为我很懒,不想设置Kotlin项目。但我希望结果是一样的。

测试中的Java类:

代码语言:javascript
复制
package de.scrum_master.stackoverflow.q70654015;

public class SampleJava {
  public String greet(String input) {
    return "Hello " + input + "!";
  }
}

测试中的Groovy类:

代码语言:javascript
复制
package de.scrum_master.stackoverflow.q70654015

class SampleGroovy {
  String "say hello to"(String input) {
    "Hello $input!"
  }
}

Spock测试创建CGLIB代理:

代码语言:javascript
复制
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!"
  }
}

第一个测试通过,第二个测试失败:

代码语言:javascript
复制
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.0
  • cglib: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或更近期的版本,那么它很可能适合您。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70654015

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档