From 67b215357ff8c7d4035a38c609349dcd5305930d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deleuze?= Date: Fri, 19 Jun 2020 10:15:28 +0200 Subject: [PATCH] Disable and remove unsupported features from native images GraalDetector has been removed for now because of https://github.com/oracle/graal/issues/2594. It should be reintroduced when this bug will be fixed with NativeImageDetector class name. Closes gh-25179 --- .../aop/framework/DefaultAopProxyFactory.java | 12 +++++- .../AbstractAutowireCapableBeanFactory.java | 16 +++++++- .../ConfigurationClassPostProcessor.java | 10 +++++ .../support/AbstractApplicationContext.java | 9 ++++- .../core/DefaultParameterNameDiscoverer.java | 9 ++++- .../springframework/core/GraalDetector.java | 39 ------------------- .../core/SerializableTypeWrapper.java | 11 +++++- 7 files changed, 61 insertions(+), 45 deletions(-) delete mode 100644 spring-core/src/main/java/org/springframework/core/GraalDetector.java diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/DefaultAopProxyFactory.java b/spring-aop/src/main/java/org/springframework/aop/framework/DefaultAopProxyFactory.java index d304397b568d..d84df2f4c9e8 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/DefaultAopProxyFactory.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/DefaultAopProxyFactory.java @@ -38,6 +38,7 @@ * * @author Rod Johnson * @author Juergen Hoeller + * @author Sebastien Deleuze * @since 12.03.2004 * @see AdvisedSupport#setOptimize * @see AdvisedSupport#setProxyTargetClass @@ -46,9 +47,18 @@ @SuppressWarnings("serial") public class DefaultAopProxyFactory implements AopProxyFactory, Serializable { + /** + * Whether this environment lives within a native image. + * Exposed as a private static field rather than in a {@code NativeImageDetector.inNativeImage()} static method due to https://github.com/oracle/graal/issues/2594. + * @see ImageInfo.java + */ + private static final boolean IN_NATIVE_IMAGE = (System.getProperty("org.graalvm.nativeimage.imagecode") != null); + + @Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { - if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { + if (!IN_NATIVE_IMAGE && + (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) { Class targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java index 93b145c521ad..4defe323d461 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java @@ -123,8 +123,16 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory { + /** + * Whether this environment lives within a native image. + * Exposed as a private static field rather than in a {@code NativeImageDetector.inNativeImage()} static method due to https://github.com/oracle/graal/issues/2594. + * @see ImageInfo.java + */ + private static final boolean IN_NATIVE_IMAGE = (System.getProperty("org.graalvm.nativeimage.imagecode") != null); + + /** Strategy for creating bean instances. */ - private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy(); + private InstantiationStrategy instantiationStrategy; /** Resolver strategy for method parameter names. */ @Nullable @@ -176,6 +184,12 @@ public AbstractAutowireCapableBeanFactory() { ignoreDependencyInterface(BeanNameAware.class); ignoreDependencyInterface(BeanFactoryAware.class); ignoreDependencyInterface(BeanClassLoaderAware.class); + if (IN_NATIVE_IMAGE) { + this.instantiationStrategy = new SimpleInstantiationStrategy(); + } + else { + this.instantiationStrategy = new CglibSubclassingInstantiationStrategy(); + } } /** diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java index d590317cec8c..1865ec2095dc 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java @@ -101,6 +101,13 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo private static final String IMPORT_REGISTRY_BEAN_NAME = ConfigurationClassPostProcessor.class.getName() + ".importRegistry"; + /** + * Whether this environment lives within a native image. + * Exposed as a private static field rather than in a {@code NativeImageDetector.inNativeImage()} static method due to https://github.com/oracle/graal/issues/2594. + * @see ImageInfo.java + */ + private static final boolean IN_NATIVE_IMAGE = (System.getProperty("org.graalvm.nativeimage.imagecode") != null); + private final Log logger = LogFactory.getLog(getClass()); @@ -412,6 +419,9 @@ else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) { // nothing to enhance -> return immediately return; } + if (IN_NATIVE_IMAGE) { + throw new BeanDefinitionStoreException("@Configuration classes need to be marked as proxyBeanMethods=false. Found: " + configBeanDefs.keySet()); + } ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer(); for (Map.Entry entry : configBeanDefs.entrySet()) { diff --git a/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java b/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java index 13c635c668c5..69a88ae0fdcd 100644 --- a/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java +++ b/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java @@ -161,6 +161,13 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader */ private static final boolean shouldIgnoreSpel = SpringProperties.getFlag("spring.spel.ignore"); + /** + * Whether this environment lives within a native image. + * Exposed as a private static field rather than in a {@code NativeImageDetector.inNativeImage()} static method due to https://github.com/oracle/graal/issues/2594. + * @see ImageInfo.java + */ + private static final boolean IN_NATIVE_IMAGE = (System.getProperty("org.graalvm.nativeimage.imagecode") != null); + static { // Eagerly load the ContextClosedEvent class to avoid weird classloader issues @@ -681,7 +688,7 @@ protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); // Detect a LoadTimeWeaver and prepare for weaving, if found. - if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { + if (!IN_NATIVE_IMAGE && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); // Set a temporary ClassLoader for type matching. beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); diff --git a/spring-core/src/main/java/org/springframework/core/DefaultParameterNameDiscoverer.java b/spring-core/src/main/java/org/springframework/core/DefaultParameterNameDiscoverer.java index 337a38080c2f..283e5ba0f314 100644 --- a/spring-core/src/main/java/org/springframework/core/DefaultParameterNameDiscoverer.java +++ b/spring-core/src/main/java/org/springframework/core/DefaultParameterNameDiscoverer.java @@ -39,8 +39,15 @@ */ public class DefaultParameterNameDiscoverer extends PrioritizedParameterNameDiscoverer { + /** + * Whether this environment lives within a native image. + * Exposed as a private static field rather than in a {@code NativeImageDetector.inNativeImage()} static method due to https://github.com/oracle/graal/issues/2594. + * @see ImageInfo.java + */ + private static final boolean IN_NATIVE_IMAGE = (System.getProperty("org.graalvm.nativeimage.imagecode") != null); + public DefaultParameterNameDiscoverer() { - if (KotlinDetector.isKotlinReflectPresent() && !GraalDetector.inImageCode()) { + if (KotlinDetector.isKotlinReflectPresent() && !IN_NATIVE_IMAGE) { addDiscoverer(new KotlinReflectionParameterNameDiscoverer()); } addDiscoverer(new StandardReflectionParameterNameDiscoverer()); diff --git a/spring-core/src/main/java/org/springframework/core/GraalDetector.java b/spring-core/src/main/java/org/springframework/core/GraalDetector.java deleted file mode 100644 index afb1fbd7ee92..000000000000 --- a/spring-core/src/main/java/org/springframework/core/GraalDetector.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.core; - -/** - * A common delegate for detecting a GraalVM native image environment. - * - * @author Juergen Hoeller - * @author Sebastien Deleuze - * @since 5.1 - */ -abstract class GraalDetector { - - // See https://github.com/oracle/graal/blob/master/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/ImageInfo.java - private static final boolean imageCode = (System.getProperty("org.graalvm.nativeimage.imagecode") != null); - - - /** - * Return whether this runtime environment lives within a native image. - */ - public static boolean inImageCode() { - return imageCode; - } - -} diff --git a/spring-core/src/main/java/org/springframework/core/SerializableTypeWrapper.java b/spring-core/src/main/java/org/springframework/core/SerializableTypeWrapper.java index b241f0cfc741..8a3a18e2092a 100644 --- a/spring-core/src/main/java/org/springframework/core/SerializableTypeWrapper.java +++ b/spring-core/src/main/java/org/springframework/core/SerializableTypeWrapper.java @@ -59,6 +59,13 @@ final class SerializableTypeWrapper { private static final Class[] SUPPORTED_SERIALIZABLE_TYPES = { GenericArrayType.class, ParameterizedType.class, TypeVariable.class, WildcardType.class}; + /** + * Whether this environment lives within a native image. + * Exposed as a private static field rather than in a {@code NativeImageDetector.inNativeImage()} static method due to https://github.com/oracle/graal/issues/2594. + * @see ImageInfo.java + */ + private static final boolean IN_NATIVE_IMAGE = (System.getProperty("org.graalvm.nativeimage.imagecode") != null); + static final ConcurrentReferenceHashMap cache = new ConcurrentReferenceHashMap<>(256); @@ -109,9 +116,9 @@ static Type forTypeProvider(TypeProvider provider) { // No serializable type wrapping necessary (e.g. for java.lang.Class) return providedType; } - if (GraalDetector.inImageCode() || !Serializable.class.isAssignableFrom(Class.class)) { + if (IN_NATIVE_IMAGE || !Serializable.class.isAssignableFrom(Class.class)) { // Let's skip any wrapping attempts if types are generally not serializable in - // the current runtime environment (even java.lang.Class itself, e.g. on Graal) + // the current runtime environment (even java.lang.Class itself, e.g. on GraalVM native images) return providedType; }