This exception only throw in the native-image.
When running spring-aot-mode without native-image, this exception will not be thrown.
Through adding logs and debugging, found that the root cause is that the JDK proxy object cannot perform the 'getMethod' operation in the native-image, it will threw the NoSuchMethodException, resulting in the method obtained by the 'ClassUtils. getMostSpecificMethod (...)' method is not as expected.
For example: jdkProxy.getClass().getMethod(methodName); will throw NoSuchMethodException in native-image, even if the method exists in the proxied interface.
I also report another issue: https://github.com/oracle/graal/issues/6079
The simplest example:
https://github.com/wangliang181230/example__spring-projects_spring-boot_issue-34388
Classes:
My FeignClient
@FeignClient(name = "openfeign-example", url = "https://httpbin.org", contextId = "openfeign-example")
public interface HttpbinClient {
@GetMapping("/delay/3")
String delay();
@GetMapping("/status/500")
String status500();
@GetMapping("/get")
String get();
}
My Aspect
@Aspect
@Component
public class SentinelResourceAspect extends AbstractSentinelAspectSupport {
private static final Logger LOGGER = LoggerFactory.getLogger(SentinelResourceAspect.class);
@Pointcut("@annotation(com.alibaba.csp.sentinel.annotation.SentinelResource)")
public void sentinelResourceAnnotationPointcut() {
}
@Around("sentinelResourceAnnotationPointcut()")
public Object invokeResourceWithSentinel(ProceedingJoinPoint pjp) throws Throwable {
LOGGER.info("Start aspect");
// do something......
}
}
Modified AspectJExpressionPointcut and print error log:
I modified the AspectJExpressionPointcut to catch the exception and print exception log.
Otherwise, the application will not start.
The modified AspectJExpressionPointcut:
public class AspectJExpressionPointcut extends AbstractExpressionPointcut
implements ClassFilter, IntroductionAwareMethodMatcher, BeanFactoryAware {
......
private ShadowMatch getTargetShadowMatch(Method method, Class<?> targetClass) {
Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
if (targetClass.getName().startsWith("jdk.")) {
// In `native image`, the value of `targetMethod.getDeclaringClass()` is the FeignClient interface: `HttpbinClient.class`,
// In 'spring-aot-mode', the value of `targetMethod.getDeclaringClass()` is the proxy type: `jdk.proxy4.$Proxy46`.
logger.info("\r\n getTargetShadowMatch:" + " targetClass: " + targetClass.getName() + ", targetMethod: " + targetMethod.toGenericString()
+ ", targetMethod.getDeclaringClass(): " + targetMethod.getDeclaringClass().getName()
);
}
if (targetMethod.getDeclaringClass().isInterface()) {
// Try to build the most specific interface possible for inherited methods to be
// considered for sub-interface matches as well, in particular for proxy classes.
// Note: AspectJ is only going to take Method.getDeclaringClass() into account.
Set<Class<?>> ifcs = ClassUtils.getAllInterfacesForClassAsSet(targetClass);
if (ifcs.size() > 1) {
Class<?>[] interfaces = ClassUtils.toClassArray(ifcs);
try {
Class<?> compositeInterface = ClassUtils.createCompositeInterface(
interfaces, targetClass.getClassLoader());
targetMethod = ClassUtils.getMostSpecificMethod(targetMethod, compositeInterface);
}
catch (IllegalArgumentException ex) {
// Implemented interfaces probably expose conflicting method signatures...
// Proceed with original target method.
}
catch (Throwable t) {
// Catch the exception, and print the log
// Otherwise, the application will not start
logger.error(Arrays.toString(interfaces) + " for class '"+targetClass.getName()+"' is createCompositeInterface failed", t);
}
}
}
return getShadowMatch(targetMethod, method);
}
......
}
The error log in native-image:
// Reason for the BUG
2023-02-27T15:22:59.474+08:00 WARN 9980 --- [main] org.springframework.util.ClassUtils : No such method 'status500' by the target class 'jdk.proxy4.$Proxy46'
// For observation
2023-02-27T15:22:59.474+08:00 INFO 9980 --- [main] o.s.a.aspectj.AspectJExpressionPointcut :
getTargetShadowMatch: targetClass: jdk.proxy4.$Proxy46, targetMethod: public abstract java.lang.String cn.wangliang181230.spring_projects__spring_boot__issue_34388.openfeign.HttpbinClient.status500(), targetMethod.getDeclaringClass(): cn.wangliang181230.spring_projects__spring_boot__issue_34388.openfeign.HttpbinClient
// The error log
2023-02-27T15:22:59.475+08:00 ERROR 9980 --- [main] o.s.a.aspectj.AspectJExpressionPointcut :
[interface cn.wangliang181230.spring_projects__spring_boot__issue_34388.openfeign.HttpbinClient, interface java.io.Serializable]
for class 'jdk.proxy4.$Proxy46' is createCompositeInterface failed
com.oracle.svm.core.jdk.UnsupportedFeatureError: Proxy class defined by interfaces [interface cn.wangliang181230.spring_projects__spring_boot__issue_34388.openfeign.HttpbinClient, interface java.io.Serializable] not found. Generating proxy classes at runtime is not supported. Proxy classes need to be defined at image build time by specifying the list of interfaces that they implement. To define proxy classes use -H:DynamicProxyConfigurationFiles=<comma-separated-config-files> and -H:DynamicProxyConfigurationResources=<comma-separated-config-resources> options.
at org.graalvm.nativeimage.builder/com.oracle.svm.core.util.VMError.unsupportedFeature(VMError.java:89) ~[na:na]
at org.graalvm.nativeimage.builder/com.oracle.svm.core.reflect.proxy.DynamicProxySupport.getProxyClass(DynamicProxySupport.java:171) ~[na:na]
at java.base@17.0.6/java.lang.reflect.Proxy.getProxyConstructor(Proxy.java:47) ~[spring-projects_spring-boot_issue-34388.exe:na]
at java.base@17.0.6/java.lang.reflect.Proxy.getProxyClass(Proxy.java:398) ~[spring-projects_spring-boot_issue-34388.exe:na]
at org.springframework.util.ClassUtils.createCompositeInterface(ClassUtils.java:783) ~[na:na]
at org.springframework.aop.aspectj.AspectJExpressionPointcut.getTargetShadowMatch(AspectJExpressionPointcut.java:432) ~[na:na]
at org.springframework.aop.aspectj.AspectJExpressionPointcut.matches(AspectJExpressionPointcut.java:289) ~[na:na]
at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:251) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:288) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.aop.support.AopUtils.findAdvisorsThatCanApply(AopUtils.java:320) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply(AbstractAdvisorAutoProxyCreator.java:128) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(AbstractAdvisorAutoProxyCreator.java:97) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(AbstractAdvisorAutoProxyCreator.java:78) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:366) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:318) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:435) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.postProcessObjectFromFactoryBean(AbstractAutowireCapableBeanFactory.java:1866) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:105) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1823) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getObjectForBeanInstance(AbstractAutowireCapableBeanFactory.java:1265) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:259) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.addCandidateEntry(DefaultListableBeanFactory.java:1628) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1585) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1368) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1325) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.beans.factory.aot.AutowiredFieldValueResolver.resolveValue(AutowiredFieldValueResolver.java:189) ~[na:na]
at org.springframework.beans.factory.aot.AutowiredFieldValueResolver.resolveAndSet(AutowiredFieldValueResolver.java:167) ~[na:na]
at cn.wangliang181230.spring_projects__spring_boot__issue_34388.controller.TestController__Autowiring.apply(TestController__Autowiring.java:14) ~[na:na]
at org.springframework.beans.factory.support.InstanceSupplier$1.get(InstanceSupplier.java:82) ~[na:na]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainInstanceFromSupplier(AbstractAutowireCapableBeanFactory.java:1225) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1210) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1157) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:561) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:961) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:915) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:584) ~[spring-projects_spring-boot_issue-34388.exe:6.0.2]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-projects_spring-boot_issue-34388.exe:3.0.0]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730) ~[spring-projects_spring-boot_issue-34388.exe:3.0.0]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:432) ~[spring-projects_spring-boot_issue-34388.exe:3.0.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[spring-projects_spring-boot_issue-34388.exe:3.0.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302) ~[spring-projects_spring-boot_issue-34388.exe:3.0.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1291) ~[spring-projects_spring-boot_issue-34388.exe:3.0.0]
at cn.wangliang181230.spring_projects__spring_boot__issue_34388.ExampleApplication.main(ExampleApplication.java:16) ~[spring-projects_spring-boot_issue-34388.exe:na]
Other DEBUG information
Recurrence steps:
git clone https://github.com/wangliang181230/spring-projects_spring-boot_issue-34388.gitmvn clean native:compile -Pnativestart ./target/spring-projects_spring-boot_issue-34388.exe, it will print the error log 3 times.- Browse
http://localhost:8080/confirm-bugto confirm the BUG.
Environment and versions:
OS: Windows 10
JDK: graalvm-ce-java17-22.3.1
Spring Boot: 3.0.0
Native maven plugin: 0.9.20
Comment From: wilkinsona
I think this should have been fixed by https://github.com/spring-projects/spring-framework/issues/29519. Please test with the latest version of Spring Boot. If the problem still occurs, please open a Spring Framework issue.
Comment From: wangliang181230
Fixed, Thanks.