From 69e3491f6b19cf69b3d4f728a7b642952ffdf692 Mon Sep 17 00:00:00 2001 From: AlexanderScherbatiy Date: Fri, 23 Sep 2022 17:19:38 +0300 Subject: [PATCH 1/4] Do not load java.awt.Component and java.beans.Customizer classes when they are not used --- substratevm/mx.substratevm/suite.py | 1 + .../svm/core/jdk/JavaBeansSubstitutions.java | 62 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaBeansSubstitutions.java diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index 2d61fbc57df7..a21b87cf9048 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -267,6 +267,7 @@ "java.desktop": [ "sun.java2d", "sun.java2d.pipe", + "com.sun.beans.finder", ], "java.management": [ "com.sun.jmx.mbeanserver", diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaBeansSubstitutions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaBeansSubstitutions.java new file mode 100644 index 000000000000..0b5830008892 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaBeansSubstitutions.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2022, BELLSOFT. All rights reserved. + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.core.jdk; + +import com.oracle.svm.core.annotate.Substitute; +import com.oracle.svm.core.annotate.TargetClass; +import com.sun.beans.finder.ClassFinder; + +@SuppressWarnings({"static-method", "unused"}) +public final class JavaBeansSubstitutions { + // Checkstyle: stop + + // Do not make string final to avoid class name interception + // in Class.forName(...) call + private static String COMPONENT_CLASS = "java.awt.Component"; + private static String CUSTOMIZER_CLASS = "java.beans.Customizer"; + + @TargetClass(className = "java.beans.Introspector") + static final class Target_java_beans_Introspector { + + // Do not load java.awt.Component and java.beans.Customizer classes + // when they are not used + @Substitute + private static Class findCustomizerClass(Class type) { + String name = type.getName() + "Customizer"; + try { + type = ClassFinder.findClass(name, type.getClassLoader()); + if (Class.forName(COMPONENT_CLASS).isAssignableFrom(type) + && Class.forName(CUSTOMIZER_CLASS).isAssignableFrom(type)) { + return type; + } + } catch (Exception exception) { + // ignore any exceptions + } + return null; + } + } + // Checkstyle: resume +} From ee603e400eb24023d69ca2eb8d3ba4de03a3a69a Mon Sep 17 00:00:00 2001 From: AlexanderScherbatiy Date: Tue, 4 Oct 2022 15:24:52 +0300 Subject: [PATCH 2/4] Change the ordinary comment to a doc comment --- .../src/com/oracle/svm/core/jdk/JavaBeansSubstitutions.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaBeansSubstitutions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaBeansSubstitutions.java index 0b5830008892..16a75a26cb5f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaBeansSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaBeansSubstitutions.java @@ -41,8 +41,10 @@ public final class JavaBeansSubstitutions { @TargetClass(className = "java.beans.Introspector") static final class Target_java_beans_Introspector { - // Do not load java.awt.Component and java.beans.Customizer classes - // when they are not used + /** + * Do not load java.awt.Component and java.beans.Customizer classes + * when they are not used + */ @Substitute private static Class findCustomizerClass(Class type) { String name = type.getName() + "Customizer"; From a1a4c6e9a12dca96a9555bb6ecf812a6b95782ae Mon Sep 17 00:00:00 2001 From: AlexanderScherbatiy Date: Wed, 12 Oct 2022 21:56:11 +0300 Subject: [PATCH 3/4] Add reachability handler for java.awt.Component class --- ...bstitutions.java => JavaBeansSupport.java} | 45 ++++++++---- .../oracle/svm/hosted/JavaBeansFeature.java | 71 +++++++++++++++++++ 2 files changed, 104 insertions(+), 12 deletions(-) rename substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/{JavaBeansSubstitutions.java => JavaBeansSupport.java} (60%) create mode 100644 substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/JavaBeansFeature.java diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaBeansSubstitutions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaBeansSupport.java similarity index 60% rename from substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaBeansSubstitutions.java rename to substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaBeansSupport.java index 16a75a26cb5f..9544c414fe79 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaBeansSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaBeansSupport.java @@ -25,33 +25,41 @@ */ package com.oracle.svm.core.jdk; +import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; + import com.oracle.svm.core.annotate.Substitute; import com.oracle.svm.core.annotate.TargetClass; + +import java.awt.Component; +import java.beans.Customizer; import com.sun.beans.finder.ClassFinder; @SuppressWarnings({"static-method", "unused"}) -public final class JavaBeansSubstitutions { - // Checkstyle: stop +public final class JavaBeansSupport { - // Do not make string final to avoid class name interception - // in Class.forName(...) call - private static String COMPONENT_CLASS = "java.awt.Component"; - private static String CUSTOMIZER_CLASS = "java.beans.Customizer"; + /** Remains null as long as the reachability handler has not triggered. */ + private Class COMPONENT_CLASS = null; + // Checkstyle: stop @TargetClass(className = "java.beans.Introspector") static final class Target_java_beans_Introspector { - /** - * Do not load java.awt.Component and java.beans.Customizer classes - * when they are not used - */ @Substitute private static Class findCustomizerClass(Class type) { String name = type.getName() + "Customizer"; try { type = ClassFinder.findClass(name, type.getClassLoader()); - if (Class.forName(COMPONENT_CLASS).isAssignableFrom(type) - && Class.forName(CUSTOMIZER_CLASS).isAssignableFrom(type)) { + // Each customizer should inherit java.awt.Component and implement java.beans.Customizer + // according to the section 9.3 of JavaBeans specification + Class componentClass = lookupComponentClass(); + // The Customizer does not extend java.awt.Component because + // java.awt.Component class is not reachable. + if (componentClass == null) { + return null; + } + if (componentClass.isAssignableFrom(type) && Customizer.class.isAssignableFrom(type)) { return type; } } catch (Exception exception) { @@ -61,4 +69,17 @@ private static Class findCustomizerClass(Class type) { } } // Checkstyle: resume + + private static Class lookupComponentClass() { + return ImageSingletons.lookup(JavaBeansSupport.class).COMPONENT_CLASS; + } + + private Class getComponentClass() { + return COMPONENT_CLASS; + } + + @Platforms(Platform.HOSTED_ONLY.class) + public static void enableComponentClass() { + ImageSingletons.lookup(JavaBeansSupport.class).COMPONENT_CLASS = Component.class; + } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/JavaBeansFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/JavaBeansFeature.java new file mode 100644 index 000000000000..6307bdd6762b --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/JavaBeansFeature.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2022, BELLSOFT. All rights reserved. + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.hosted; + +import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; + +import com.oracle.svm.core.jdk.JavaBeansSupport; +import com.oracle.svm.core.feature.InternalFeature; +import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; +import com.oracle.svm.hosted.FeatureImpl.DuringAnalysisAccessImpl; +import com.oracle.svm.hosted.FeatureImpl.DuringSetupAccessImpl; + +import java.beans.Introspector; +import java.lang.reflect.Field; + +@AutomaticallyRegisteredFeature +final class JavaBeansFeature implements InternalFeature { + + private Field componentClassField; + + @Override + public void afterRegistration(AfterRegistrationAccess access) { + ImageSingletons.add(JavaBeansSupport.class, new JavaBeansSupport()); + } + + @Override + public void duringSetup(DuringSetupAccess a) { + DuringSetupAccessImpl access = (DuringSetupAccessImpl) a; + componentClassField = access.findField(JavaBeansSupport.class, "COMPONENT_CLASS"); + } + + @Override + public void beforeAnalysis(BeforeAnalysisAccess access) { + access.registerReachabilityHandler(this::enableComponentClass, access.findClassByName("java.awt.Component")); + } + + @Platforms(Platform.HOSTED_ONLY.class) + void enableComponentClass(DuringAnalysisAccess a) { + DuringAnalysisAccessImpl access = (DuringAnalysisAccessImpl) a; + JavaBeansSupport.enableComponentClass(); + access.rescanField(ImageSingletons.lookup(JavaBeansSupport.class), componentClassField); + if (!access.concurrentReachabilityHandlers()) { + access.requireAnalysisIteration(); + } + } +} From deed713a1697d6b4a1fceb137ed449cb69c58410 Mon Sep 17 00:00:00 2001 From: AlexanderScherbatiy Date: Wed, 12 Oct 2022 22:05:32 +0300 Subject: [PATCH 4/4] Remove unused getComponentClass() method --- .../src/com/oracle/svm/core/jdk/JavaBeansSupport.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaBeansSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaBeansSupport.java index 9544c414fe79..161e703190ec 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaBeansSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaBeansSupport.java @@ -74,10 +74,6 @@ private static Class lookupComponentClass() { return ImageSingletons.lookup(JavaBeansSupport.class).COMPONENT_CLASS; } - private Class getComponentClass() { - return COMPONENT_CLASS; - } - @Platforms(Platform.HOSTED_ONLY.class) public static void enableComponentClass() { ImageSingletons.lookup(JavaBeansSupport.class).COMPONENT_CLASS = Component.class;