From 9a5f3115a55364bdabdd93d4365801a03e9c4847 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksandar=20Pejovi=C4=87?= Date: Mon, 5 Sep 2022 15:48:39 +0200 Subject: [PATCH 1/3] Remove support for static linking of AWT libraries --- substratevm/mx.substratevm/suite.py | 6 - .../svm/core/jdk/JavaAWTSubstitutions.java | 976 ------------------ .../svm/hosted/jdk/JNIRegistrationAwt.java | 210 ---- .../jdk/JNIRegistrationManagementExt.java | 30 +- .../SubstrateGraphBuilderPlugins.java | 22 - 5 files changed, 6 insertions(+), 1238 deletions(-) delete mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaAWTSubstitutions.java delete mode 100644 substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationAwt.java diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index 6fd0c34f89eb..efbe38041df8 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -282,10 +282,6 @@ "jdk.internal.reflect", "jdk.internal.util", ], - "java.desktop": [ - "sun.java2d", - "sun.java2d.pipe", - ], "java.management": [ "com.sun.jmx.mbeanserver", "sun.management", @@ -610,7 +606,6 @@ "com.oracle.graal.reachability" ], "requires" : [ - "java.desktop", "java.instrument", "java.security.sasl", "java.smartcardio", @@ -1342,7 +1337,6 @@ "java.management", "jdk.management", "java.xml.crypto", - "java.desktop", "java.security.sasl", "java.smartcardio", "java.net.http", diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaAWTSubstitutions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaAWTSubstitutions.java deleted file mode 100644 index 490115527939..000000000000 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaAWTSubstitutions.java +++ /dev/null @@ -1,976 +0,0 @@ -/* - * Copyright (c) 2017, 2017, 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 java.awt.GraphicsEnvironment; -import java.io.FilenameFilter; -import java.util.function.BooleanSupplier; - -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; - -import com.oracle.svm.core.SubstrateOptions; -import com.oracle.svm.core.SubstrateUtil; -import com.oracle.svm.core.annotate.Alias; -import com.oracle.svm.core.annotate.Delete; -import com.oracle.svm.core.annotate.Substitute; -import com.oracle.svm.core.annotate.TargetClass; - -@Platforms(Platform.LINUX.class) -@SuppressWarnings({"static-method", "unused"}) -public final class JavaAWTSubstitutions { - // Checkstyle: stop - @TargetClass(className = "sun.awt.DebugSettings") - static final class Target_sun_awt_DebugSettings { - - @Substitute - void setCTracingOn(boolean enabled) { - throw new UnsupportedOperationException(); - } - - @Substitute - void setCTracingOn(boolean enabled, String file) { - throw new UnsupportedOperationException(); - } - - @Substitute - void setCTracingOn(boolean enabled, String file, int line) { - throw new UnsupportedOperationException(); - } - } - - @TargetClass(className = "sun.java2d.loops.TransformBlit") - static final class Target_sun_java2d_loops_TransformBlit { - - // Could not find JNI method Java_sun_java2d_loops_TransformBlit_Transform - @Substitute - void Transform(sun.java2d.SurfaceData src, sun.java2d.SurfaceData dst, - java.awt.Composite comp, sun.java2d.pipe.Region clip, - java.awt.geom.AffineTransform at, int hint, - int srcx, int srcy, int dstx, int dsty, - int width, int height) { - throw new UnsupportedOperationException(); - } - } - - @TargetClass(className = "sun.font.FileFontStrike") - static final class Target_sun_font_FileFontStrike { - - // Java_sun_font_FileFontStrike_initNative belongs to Windows static lib - @Substitute - static boolean initNative() { - throw new UnsupportedOperationException(); - } - - // Java_sun_font_FileFontStrike_initNative belongs to Windows static lib - @Substitute - long _getGlyphImageFromWindows(String family, - int style, - int size, - int glyphCode, - boolean fracMetrics, - int fontDataSize) { - throw new UnsupportedOperationException(); - } - } - - @TargetClass(className = "sun.awt.FontConfiguration") - static final class Target_sun_awt_FontConfiguration { - - // To prevent an attempt to load fonts from java.home - @Substitute - public boolean foundOsSpecificFile() { - return false; - } - - // Original method throws an exception if java.home is null - @Substitute - private void findFontConfigFile() { - } - - // Called from Target_sun_font_FcFontConfiguration#init() - original method is protected - @Alias - protected native void setFontConfiguration(); - } - - // Used in Target_sun_font_FcFontConfiguration#init() - @TargetClass(className = "sun.font.FontConfigManager", innerClass = "FcCompFont") - static final class Target_sun_font_FontConfigManager_FcCompFont { - } - - private static final class SunFontManagerEnabled implements BooleanSupplier { - - @Override - public boolean getAsBoolean() { - return !SubstrateOptions.StaticExecutable.getValue(); - } - - } - - // Used in Target_sun_font_FcFontConfiguration#init() - @TargetClass(className = "sun.font.SunFontManager", onlyWith = SunFontManagerEnabled.class) - static final class Target_sun_font_SunFontManager { - } - - // Used in Target_sun_font_FcFontConfiguration#init() - @TargetClass(className = "sun.awt.FcFontManager") - static final class Target_sun_awt_FcFontManager { - // Called from Target_sun_font_FcFontConfiguration#init() - @Alias - public synchronized native Target_sun_font_FontConfigManager getFontConfigManager(); - } - - // Used in Target_sun_font_FcFontConfiguration#init() - @TargetClass(className = "sun.font.FontConfigManager") - static final class Target_sun_font_FontConfigManager { - // Called from Target_sun_font_FcFontConfiguration#init() - original method not visible - @Alias - native Target_sun_font_FontConfigManager_FcCompFont[] loadFontConfig(); - - // Called from Target_sun_font_FcFontConfiguration#init() - original method not visible - @Alias - native void populateFontConfig(Target_sun_font_FontConfigManager_FcCompFont[] fcInfo); - } - - // Used in Target_sun_font_FcFontConfiguration#init() - @TargetClass(className = "sun.font.FontUtilities") - static final class Target_sun_font_FontUtilities { - // Called from Target_sun_font_FcFontConfiguration#init() - @Alias - public static native boolean debugFonts(); - } - - @TargetClass(className = "sun.font.FcFontConfiguration") - static final class Target_sun_font_FcFontConfiguration { - // Accessed from #init() - original field is private - @Alias// - private Target_sun_font_FontConfigManager_FcCompFont[] fcCompFonts; - - // Accessed from #init() - original field is protected - @Alias// - protected Target_sun_font_SunFontManager fontManager; - - // Called from #init() - original method is private - @Alias - private native void readFcInfo(); - - // Called from #init() - original method is private - @Alias - private native void writeFcInfo(); - - // Called from #init() - original method is private - @Alias - private native static void warning(String msg); - - // Original method throws an exception if java.home is null - @Substitute - public synchronized boolean init() { - if (fcCompFonts != null) { - return true; - } - - SubstrateUtil.cast(this, Target_sun_awt_FontConfiguration.class).setFontConfiguration(); - readFcInfo(); - Target_sun_awt_FcFontManager fm = SubstrateUtil.cast(fontManager, Target_sun_awt_FcFontManager.class); - Target_sun_font_FontConfigManager fcm = fm.getFontConfigManager(); - if (fcCompFonts == null) { - fcCompFonts = fcm.loadFontConfig(); - if (fcCompFonts != null) { - try { - writeFcInfo(); - } catch (Exception e) { - if (Target_sun_font_FontUtilities.debugFonts()) { - warning("Exception writing fcInfo " + e); - } - } - } else if (Target_sun_font_FontUtilities.debugFonts()) { - warning("Failed to get info from libfontconfig"); - } - } else { - fcm.populateFontConfig(fcCompFonts); - } - - /*- - The below code was part of the original method but has been removed in the substitution. In a native-image, - java.home is set to null, so executing it would result in an exception. - The #getInstalledFallbackFonts method is in charge of installing fallback fonts shipped with the JDK. If the - fallback font directory does not exist, it is a no-op. As we do not have a JDK available at native-image - runtime, we can safely remove the call. - - // NB already in a privileged block from SGE - String javaHome = System.getProperty("java.home"); - if (javaHome == null) { - throw new Error("java.home property not set"); - } - String javaLib = javaHome + File.separator + "lib"; - getInstalledFallbackFonts(javaLib); - */ - - return fcCompFonts != null; // couldn't load fontconfig. - } - - } - - /* - * To prevent AWT linkage error that happens with 'awt_headless' in headless mode, we substitute - * native methods that depend on 'awt_xawt' library in the call-tree. - */ - @TargetClass(className = "sun.awt.X11.XToolkit", onlyWith = IsHeadless.class) - static final class Target_sun_awt_X11_XToolkit { - - @Substitute - static String getEnv(String key) { - throw new UnsupportedOperationException(); - } - - @Substitute - static void wakeup_poll() { - throw new UnsupportedOperationException(); - } - - @Substitute - void run() { - throw new UnsupportedOperationException(); - } - - @Substitute - int getNumberOfButtons() { - throw new UnsupportedOperationException(); - } - - @Substitute - static long getDefaultXColormap() { - throw new UnsupportedOperationException(); - } - } - - @TargetClass(className = "java.awt.Window", onlyWith = IsHeadless.class) - static final class Target_java_awt_Window { - - @Substitute - void dispose() { - throw new UnsupportedOperationException(); - } - - @Substitute - void doDispose() { - throw new UnsupportedOperationException(); - } - - @Substitute - void closeSplashScreen() { - throw new UnsupportedOperationException(); - } - } - - @TargetClass(className = "sun.awt.X11.XWindow", onlyWith = IsHeadless.class) - static final class Target_sun_awt_X11_XWindow { - - @Substitute - private static void initIDs() { - throw new UnsupportedOperationException(); - } - } - - @TargetClass(className = "sun.awt.X11.XBaseWindow", onlyWith = IsHeadless.class) - @Delete - static final class Target_sun_awt_X11_XBaseWindow { - } - - @TargetClass(className = "sun.awt.X11.XlibWrapper", onlyWith = IsHeadless.class) - static final class Target_sun_awt_X11_XlibWrapper { - - @Substitute - static long DisplayWidth(long display, long screen) { - throw new UnsupportedOperationException(); - } - - @Substitute - static long DefaultScreen(long display) { - throw new UnsupportedOperationException(); - } - - @Substitute - static long DisplayWidthMM(long display, long screen) { - throw new UnsupportedOperationException(); - } - - @Substitute - static long InternAtom(long display, String string, int only_if_exists) { - throw new UnsupportedOperationException(); - } - - @Substitute - static void XSync(long display, int discard) { - throw new UnsupportedOperationException(); - } - - @Substitute - static long XAllocSizeHints() { - throw new UnsupportedOperationException(); - } - - @Substitute - static String[] XTextPropertyToStringList(byte[] bytes, long encoding_atom) { - throw new UnsupportedOperationException(); - } - - @Substitute - static String XGetAtomName(long display, long atom) { - throw new UnsupportedOperationException(); - } - - @Substitute - static byte[] getStringBytes(long str_ptr) { - throw new UnsupportedOperationException(); - } - - @Substitute - static long XAllocWMHints() { - throw new UnsupportedOperationException(); - } - - @Substitute - static void XFree(long ptr) { - throw new UnsupportedOperationException(); - } - - @Substitute - static void memcpy(long dest_ptr, long src_ptr, long length) { - throw new UnsupportedOperationException(); - } - - @Substitute - static long SetToolkitErrorHandler() { - throw new UnsupportedOperationException(); - } - - @Substitute - static long XMaxRequestSize(long display) { - throw new UnsupportedOperationException(); - } - - @Substitute - static void XChangePropertyS(long display, long window, long atom, - long type, int format, int mode, String value) { - throw new UnsupportedOperationException(); - } - - @Substitute - static int XGetWindowProperty(long display, long window, long atom, - long long_offset, long long_length, - long delete, long req_type, long actualy_type, - long actualy_format, long nitems_ptr, - long bytes_after, long data_ptr) { - throw new UnsupportedOperationException(); - } - - @Substitute - static boolean XAllocColor(long display, long colormap, long screen_in_out) { - throw new UnsupportedOperationException(); - } - - @Substitute - static long XGetSelectionOwner(long display, long selection) { - throw new UnsupportedOperationException(); - } - - @Substitute - static long XCreateBitmapFromData(long display, long drawable, long data, int width, int height) { - throw new UnsupportedOperationException(); - } - - @Substitute - static void XFreePixmap(long display, long pixmap) { - throw new UnsupportedOperationException(); - } - - @Substitute - static void XChangeWindowAttributes(long display, long window, long valuemask, long attributes) { - throw new UnsupportedOperationException(); - } - - @Substitute - static long RootWindow(long display, long screen_number) { - throw new UnsupportedOperationException(); - } - - @Substitute - static long XCreatePixmapCursor(long display, long source, long mask, long fore, long back, int x, int y) { - throw new UnsupportedOperationException(); - } - - @Substitute - static String ServerVendor(long display) { - throw new UnsupportedOperationException(); - } - - @Substitute - static boolean XQueryBestCursor(long display, long drawable, int width, int height, long width_return, long height_return) { - throw new UnsupportedOperationException(); - } - - @Substitute - static void XResizeWindow(long display, long window, int width, int height) { - throw new UnsupportedOperationException(); - } - - @Substitute - static void XReparentWindow(long display, long window, long parent, int x, int y) { - throw new UnsupportedOperationException(); - } - - @Substitute - static void XDeleteProperty(long display, long window, long atom) { - throw new UnsupportedOperationException(); - } - - @Substitute - static int XGetWMNormalHints(long display, long window, long hints, long supplied_return) { - throw new UnsupportedOperationException(); - } - - @Substitute - static void XBell(long display, int percent) { - throw new UnsupportedOperationException(); - } - - @Substitute - static boolean XShapeQueryExtension(long display, long event_base_return, long error_base_return) { - throw new UnsupportedOperationException(); - } - - @Substitute - static void XMoveResizeWindow(long display, long window, int x, int y, int width, int height) { - throw new UnsupportedOperationException(); - } - - @Substitute - static void XMoveWindow(long display, long window, int x, int y) { - throw new UnsupportedOperationException(); - } - - @Substitute - static void SetZOrder(long display, long window, long above) { - throw new UnsupportedOperationException(); - } - - @Substitute - static int XQueryTree(long display, long window, long root_return, long parent_return, long children_return, long nchildren_return) { - throw new UnsupportedOperationException(); - } - - @Substitute - static void SetRectangularShape(long display, long window, - int lox, int loy, int hix, int hiy, - sun.java2d.pipe.Region region) { - throw new UnsupportedOperationException(); - } - - @Substitute - static void XFlush(long display) { - throw new UnsupportedOperationException(); - } - - @Substitute - static void XMapRaised(long display, long window) { - throw new UnsupportedOperationException(); - } - - @Substitute - static int XSendEvent(long display, long window, boolean propagate, long event_mask, long event) { - throw new UnsupportedOperationException(); - } - - @Substitute - static void XChangePropertyImpl(long display, long window, long atom, - long type, int format, int mode, long data, - int nelements) { - throw new UnsupportedOperationException(); - } - - @Substitute - static void XUnmapWindow(long display, long window) { - throw new UnsupportedOperationException(); - } - - @Substitute - static boolean XQueryPointer(long display, long window, long root_return, long child_return, long root_x_return, long root_y_return, long win_x_return, long win_y_return, long mask_return) { - throw new UnsupportedOperationException(); - } - - @Substitute - static int XGetWindowAttributes(long display, long window, long attr_ptr) { - throw new UnsupportedOperationException(); - } - - @Substitute - static void XUngrabServer(long display) { - throw new UnsupportedOperationException(); - } - - @Substitute - static int XKeysymToKeycode(long display, long keysym) { - throw new UnsupportedOperationException(); - } - - @Substitute - static long XGetModifierMapping(long display) { - throw new UnsupportedOperationException(); - } - - @Substitute - static int ScreenCount(long display) { - throw new UnsupportedOperationException(); - } - - @Substitute - static int XCreateFontCursor(long display, int shape) { - throw new UnsupportedOperationException(); - } - - @Substitute - static void XFreeModifiermap(long keymap) { - throw new UnsupportedOperationException(); - } - - @Substitute - static void XSelectInput(long display, long window, long event_mask) { - throw new UnsupportedOperationException(); - } - - @Substitute - static void XGrabServer(long display) { - throw new UnsupportedOperationException(); - } - } - - @TargetClass(className = "sun.java2d.xr.XRBackendNative", onlyWith = IsHeadless.class) - static final class Target_sun_java2d_xr_XRBackendNative { - - @Substitute - static void initIDs() { - throw new UnsupportedOperationException(); - } - - @Substitute - private static void XRAddGlyphsNative(int glyphSet, - long[] glyphInfoPtrs, - int glyphCnt, - byte[] pixelData, - int pixelDataLength) { - throw new UnsupportedOperationException(); - } - - @Substitute - private static int XRCreateLinearGradientPaintNative(float[] fractionsArray, - short[] pixelsArray, - int x1, int y1, int x2, int y2, - int numStops, int repeat) { - throw new UnsupportedOperationException(); - } - - @Substitute - private static void XRSetClipNative(long dst, - int x1, int y1, int x2, int y2, - sun.java2d.pipe.Region clip, boolean isGC) { - throw new UnsupportedOperationException(); - } - - @Substitute - private static void XRenderCompositeTextNative(int op, int src, int dst, - int srcX, int srcY, long maskFormat, - int[] eltArray, int[] glyphIDs, int eltCnt, - int glyphCnt) { - throw new UnsupportedOperationException(); - } - - @Substitute - private static void GCRectanglesNative(int drawable, long gc, - int[] rectArray, int rectCnt) { - throw new UnsupportedOperationException(); - } - - @Substitute - private static void XRFreeGlyphsNative(int glyphSet, - int[] gids, int idCnt) { - throw new UnsupportedOperationException(); - } - - @Substitute - private static void XRenderRectanglesNative(int dst, byte op, - short red, short green, - short blue, short alpha, - int[] rects, int rectCnt) { - throw new UnsupportedOperationException(); - } - - @Substitute - private static int XRCreateRadialGradientPaintNative(float[] fractionsArray, - short[] pixelsArray, int numStops, - int centerX, int centerY, - int innerRadius, int outerRadius, - int repeat) { - throw new UnsupportedOperationException(); - } - - @Substitute - public void renderComposite(byte op, int src, int mask, - int dst, int srcX, int srcY, - int maskX, int maskY, int dstX, int dstY, - int width, int height) { - throw new UnsupportedOperationException(); - } - - @Substitute - public void setGCMode(long gc, boolean copy) { - throw new UnsupportedOperationException(); - } - - @Substitute - public void freePicture(int picture) { - throw new UnsupportedOperationException(); - } - - @Substitute - public void setPictureRepeat(int picture, int repeat) { - throw new UnsupportedOperationException(); - } - - @Substitute - public void setGCForeground(long gc, int pixel) { - throw new UnsupportedOperationException(); - } - - @Substitute - public void setFilter(int picture, int filter) { - throw new UnsupportedOperationException(); - } - - @Substitute - private void renderRectangle(int dst, byte op, - short red, short green, - short blue, short alpha, - int x, int y, int width, int height) { - throw new UnsupportedOperationException(); - } - - @Substitute - private void XRSetTransformNative(int pic, - int m00, int m01, int m02, - int m10, int m11, int m12) { - throw new UnsupportedOperationException(); - } - - @Substitute - public void setGCExposures(long gc, boolean exposure) { - throw new UnsupportedOperationException(); - } - - @Substitute - public void copyArea(int src, int dst, long gc, - int srcx, int srcy, int width, int height, - int dstx, int dsty) { - throw new UnsupportedOperationException(); - } - } - - @TargetClass(className = "sun.awt.X11InputMethodBase", onlyWith = IsHeadless.class) - static final class Target_sun_awt_X11InputMethodBase { - - @Substitute - static void initIDs() { - throw new UnsupportedOperationException(); - } - - @Substitute - void turnoffStatusWindow() { - throw new UnsupportedOperationException(); - } - - @Substitute - boolean setCompositionEnabledNative(boolean enable) { - throw new UnsupportedOperationException(); - } - - @Substitute - boolean isCompositionEnabledNative() { - throw new UnsupportedOperationException(); - } - - @Substitute - String resetXIC() { - throw new UnsupportedOperationException(); - } - - @Substitute - void disposeXIC() { - throw new UnsupportedOperationException(); - } - } - - @TargetClass(className = "sun.awt.UNIXToolkit", onlyWith = IsHeadless.class) - static final class Target_sun_awt_UNIXToolkit { - - @Substitute - private static boolean load_gtk(int version, boolean verbose) { - throw new UnsupportedOperationException(); - } - - @Substitute - public void sync() { - throw new UnsupportedOperationException(); - } - - @Substitute - public java.awt.image.BufferedImage getStockIcon(final int widgetType, final String stockId, - final int iconSize, final int direction, - final String detail) { - throw new UnsupportedOperationException(); - } - - @Substitute - public boolean isNativeGTKAvailable() { - throw new UnsupportedOperationException(); - } - - @Substitute - private boolean gtkCheckVersionImpl(int major, int minor, int micro) { - throw new UnsupportedOperationException(); - } - } - - @TargetClass(className = "sun.awt.X11GraphicsConfig", onlyWith = IsHeadless.class) - static final class Target_sun_awt_X11GraphicsConfig { - - @Substitute - static void initIDs() { - throw new UnsupportedOperationException(); - } - - } - - /** - * This is necessary to workaround `javac` warnings that cannot be suppressed. For example: - * - *
-     * JavaAWTSubstitutions.java:574: warning: ComponentPeer is internal proprietary API and may be removed in a future release
-     *       private void nativeSetSource(java.awt.peer.ComponentPeer peer) {
-     *                                                 ^
-     * 
- */ - @TargetClass(className = "java.awt.peer.ComponentPeer", onlyWith = IsHeadless.class) - static final class Target_java_awt_peer_ComponentPeer { - } - - @TargetClass(className = "java.awt.AWTEvent", onlyWith = IsHeadless.class) - static final class Target_java_awt_AWTEvent { - - @Substitute - private void nativeSetSource(Target_java_awt_peer_ComponentPeer peer) { - throw new UnsupportedOperationException(); - } - } - - @TargetClass(className = "sun.java2d.opengl.OGLSurfaceData", onlyWith = IsHeadless.class) - static final class Target_sun_java2d_opengl_OGLSurfaceData { - - @Substitute - protected boolean initFlipBackbuffer(long pData) { - throw new UnsupportedOperationException(); - } - - @Substitute - protected boolean initTexture(long pData, - boolean isOpaque, boolean texNonPow2, - boolean texRect, - int width, int height) { - throw new UnsupportedOperationException(); - } - - @Substitute - protected boolean initFBObject(long pData, - boolean isOpaque, boolean texNonPow2, - boolean texRect, - int width, int height) { - throw new UnsupportedOperationException(); - } - } - - @TargetClass(className = "sun.java2d.opengl.OGLRenderQueue", onlyWith = IsHeadless.class) - static final class Target_sun_java2d_opengl_OGLRenderQueue { - - @Substitute - private void flushBuffer(long buf, int limit) { - throw new UnsupportedOperationException(); - } - } - - @TargetClass(className = "sun.awt.X11.XTaskbarPeer", onlyWith = IsHeadless.class) - static final class Target_sun_awt_X11_XTaskbarPeer { - - @Substitute - private static void initWithLock() { - throw new UnsupportedOperationException(); - } - } - - @TargetClass(className = "sun.awt.X11.XDesktopPeer", onlyWith = IsHeadless.class) - static final class Target_sun_awt_X11_XDesktopPeer { - - @Substitute - private static void initWithLock() { - throw new UnsupportedOperationException(); - } - } - - @TargetClass(className = "sun.awt.X11.GtkFileDialogPeer", onlyWith = IsHeadless.class) - static final class Target_sun_awt_X11_GtkFileDialogPeer { - - @Substitute - private static void initIDs() { - throw new UnsupportedOperationException(); - } - - @Substitute - private void quit() { - throw new UnsupportedOperationException(); - } - - @Substitute - private void run(String title, int mode, String dir, String file, - FilenameFilter filter, boolean isMultipleMode, int x, int y) { - throw new UnsupportedOperationException(); - } - - @Substitute - public void setBounds(int x, int y, int width, int height, int op) { - throw new UnsupportedOperationException(); - } - - @Substitute - public void toFront() { - throw new UnsupportedOperationException(); - } - } - - @TargetClass(className = "sun.awt.X11.XRobotPeer", onlyWith = IsHeadless.class) - static final class Target_sun_awt_X11_XRobotPeer { - - @Substitute - private static void loadNativeLibraries() { - throw new UnsupportedOperationException(); - } - } - - @TargetClass(className = "sun.awt.X11.XInputMethod", onlyWith = IsHeadless.class) - static final class Target_sun_awt_X11_XInputMethod { - - @Substitute - private boolean openXIMNative(long display) { - throw new UnsupportedOperationException(); - } - } - - /* - * These classes transitively use libfontconfig. All libfontconfig uses are done through dlsym, - * which doesn't work in a static executable. Simply not linking against fontconfig is not - * enough - we must @Delete these classes to prevent linker errors. - */ - - @TargetClass(className = "sun.java2d.loops.DrawGlyphListAA", onlyWith = FontsDisabled.class) - @Delete(value = FontsDisabled.FONTS_DISABLED_REASON) - static final class Target_sun_java2d_loops_DrawGlyphListAA { - } - - @TargetClass(className = "sun.java2d.loops.DrawGlyphList", onlyWith = FontsDisabled.class) - @Delete(value = FontsDisabled.FONTS_DISABLED_REASON) - static final class Target_sun_java2d_loops_DrawGlyphList { - } - - @TargetClass(className = "sun.java2d.loops.DrawGlyphListLCD", onlyWith = FontsDisabled.class) - @Delete(value = FontsDisabled.FONTS_DISABLED_REASON) - static final class Target_sun_java2d_loops_DrawGlyphListLCD { - } - - @TargetClass(className = "sun.font.SunLayoutEngine", onlyWith = FontsDisabled.class) - @Delete(value = FontsDisabled.FONTS_DISABLED_REASON) - static final class Target_sun_font_SunLayoutEngine { - } - - @TargetClass(className = "sun.font.FreetypeFontScaler", onlyWith = FontsDisabled.class) - @Delete(value = FontsDisabled.FONTS_DISABLED_REASON) - static final class Target_sun_font_FreetypeFontScaler { - } - - @TargetClass(className = "sun.font.NativeFont", onlyWith = FontsDisabled.class) - @Delete(value = FontsDisabled.FONTS_DISABLED_REASON) - static final class Target_sun_font_NativeFont { - } - - @TargetClass(className = "sun.font.StrikeCache", onlyWith = FontsDisabled.class) - @Delete(value = FontsDisabled.FONTS_DISABLED_REASON) - static final class Target_sun_font_StrikeCache { - } - - @TargetClass(className = "sun.font.NativeStrikeDisposer", onlyWith = FontsDisabled.class) - @Delete(value = FontsDisabled.FONTS_DISABLED_REASON) - static final class Target_sun_font_NativeStrikeDisposer { - } - - @TargetClass(className = "sun.font.NativeStrike", onlyWith = FontsDisabled.class) - @Delete(value = FontsDisabled.FONTS_DISABLED_REASON) - static final class Target_sun_font_NativeStrike { - } - - @TargetClass(className = "sun.font.SunFontManager", onlyWith = FontsDisabled.class) - @Delete(value = FontsDisabled.FONTS_DISABLED_REASON) - static final class Target_sun_font_SunFontManagerDeleted { - } - - @TargetClass(className = "sun.font.NullFontScaler", onlyWith = FontsDisabled.class) - @Delete(value = FontsDisabled.FONTS_DISABLED_REASON) - static final class Target_sun_font_NullFontScaler { - } - - // To support headless mode - static class IsHeadless implements BooleanSupplier { - @Override - public boolean getAsBoolean() { - return GraphicsEnvironment.isHeadless(); - } - } - // Checkstyle: resume - - static class FontsDisabled implements BooleanSupplier { - @Override - public boolean getAsBoolean() { - return SubstrateOptions.StaticExecutable.getValue(); - } - - public static final String FONTS_DISABLED_REASON = "AWT uses fontconfig to implement font related functionality on Linux. All fontconfig uses happen through dlsym which doesn't work in a static executable. " + - "Try avoiding the use of this class in the project or turn off static executable generation."; - } -} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationAwt.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationAwt.java deleted file mode 100644 index 3c823411b12a..000000000000 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationAwt.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (c) 2020, 2020, 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.jdk; - -import java.awt.GraphicsEnvironment; - -import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.hosted.RuntimeJNIAccess; -import org.graalvm.nativeimage.impl.ConfigurationCondition; -import org.graalvm.nativeimage.impl.InternalPlatform; -import org.graalvm.nativeimage.impl.RuntimeResourceSupport; - -import com.oracle.svm.core.SubstrateOptions; -import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; -import com.oracle.svm.core.feature.InternalFeature; -import com.oracle.svm.core.jdk.JNIRegistrationUtil; -import com.oracle.svm.core.jdk.NativeLibrarySupport; -import com.oracle.svm.core.jdk.PlatformNativeLibrarySupport; -import com.oracle.svm.hosted.FeatureImpl; -import com.oracle.svm.hosted.c.NativeLibraries; - -@Platforms({InternalPlatform.PLATFORM_JNI.class}) -@AutomaticallyRegisteredFeature -@SuppressWarnings({"unused"}) -public class JNIRegistrationAwt extends JNIRegistrationUtil implements InternalFeature { - - @Override - public void beforeAnalysis(BeforeAnalysisAccess access) { - if (Platform.includedIn(Platform.LINUX.class)) { - access.registerReachabilityHandler(JNIRegistrationAwt::handlePreferencesClassReachable, - clazz(access, "java.awt.Toolkit"), - clazz(access, "sun.java2d.cmm.lcms.LCMS"), - clazz(access, "java.awt.event.NativeLibLoader"), - clazz(access, "sun.awt.NativeLibLoader"), - clazz(access, "sun.awt.image.NativeLibLoader"), - clazz(access, "java.awt.image.ColorModel"), - clazz(access, "sun.awt.X11GraphicsEnvironment"), - clazz(access, "sun.font.FontManagerNativeLibrary"), - clazz(access, "sun.print.CUPSPrinter"), - clazz(access, "sun.java2d.Disposer")); - PlatformNativeLibrarySupport.singleton().addBuiltinPkgNativePrefix("java_awt"); - PlatformNativeLibrarySupport.singleton().addBuiltinPkgNativePrefix("sun_awt"); - PlatformNativeLibrarySupport.singleton().addBuiltinPkgNativePrefix("sun_java2d"); - PlatformNativeLibrarySupport.singleton().addBuiltinPkgNativePrefix("sun_print"); - - access.registerReachabilityHandler(JNIRegistrationAwt::registerFreeType, - clazz(access, "sun.font.FontManagerNativeLibrary")); - PlatformNativeLibrarySupport.singleton().addBuiltinPkgNativePrefix("sun_font"); - - access.registerReachabilityHandler(JNIRegistrationAwt::registerLCMS, - clazz(access, "sun.java2d.cmm.lcms.LCMS")); - - access.registerReachabilityHandler(JNIRegistrationAwt::registerImagingLib, - clazz(access, "sun.awt.image.ImagingLib")); - - access.registerReachabilityHandler(JNIRegistrationAwt::registerJPEG, - clazz(access, "sun.awt.image.JPEGImageDecoder"), - clazz(access, "com.sun.imageio.plugins.jpeg.JPEGImageReader"), - clazz(access, "com.sun.imageio.plugins.jpeg.JPEGImageWriter")); - PlatformNativeLibrarySupport.singleton().addBuiltinPkgNativePrefix("com_sun_imageio_plugins_jpeg"); - - access.registerReachabilityHandler(JNIRegistrationAwt::registerColorProfiles, - clazz(access, "java.awt.color.ICC_Profile")); - - access.registerReachabilityHandler(JNIRegistrationAwt::registerFlavorMapProps, - clazz(access, "java.awt.datatransfer.SystemFlavorMap")); - - access.registerReachabilityHandler(JNIRegistrationAwt::registerRTFReaderCharsets, - clazz(access, "javax.swing.text.rtf.RTFReader")); - - access.registerReachabilityHandler(JNIRegistrationAwt::registerOceanThemeIcons, - clazz(access, "javax.swing.plaf.metal.OceanTheme")); - } - } - - private static void handlePreferencesClassReachable(DuringAnalysisAccess access) { - - RuntimeJNIAccess.register(method(access, "java.lang.System", "setProperty", String.class, String.class)); - RuntimeJNIAccess.register(method(access, "java.lang.System", "loadLibrary", String.class)); - - RuntimeJNIAccess.register(GraphicsEnvironment.class); - RuntimeJNIAccess.register(method(access, "java.awt.GraphicsEnvironment", "isHeadless")); - - NativeLibraries nativeLibraries = getNativeLibraries(access); - - NativeLibrarySupport.singleton().preregisterUninitializedBuiltinLibrary("awt"); - nativeLibraries.addStaticJniLibrary("awt"); - - if (isHeadless()) { - NativeLibrarySupport.singleton().preregisterUninitializedBuiltinLibrary("awt_headless"); - nativeLibraries.addStaticJniLibrary("awt_headless", "awt"); - } else { - NativeLibrarySupport.singleton().preregisterUninitializedBuiltinLibrary("awt_xawt"); - nativeLibraries.addStaticJniLibrary("awt_xawt", "awt"); - - nativeLibraries.addDynamicNonJniLibrary("X11"); - nativeLibraries.addDynamicNonJniLibrary("Xrender"); - nativeLibraries.addDynamicNonJniLibrary("Xext"); - nativeLibraries.addDynamicNonJniLibrary("Xi"); - } - - nativeLibraries.addDynamicNonJniLibrary("stdc++"); - nativeLibraries.addDynamicNonJniLibrary("m"); - - access.registerReachabilityHandler(JNIRegistrationAwt::registerHtml32bdtd, - clazz(access, "javax.swing.text.html.HTMLEditorKit")); - } - - private static void registerJPEG(DuringAnalysisAccess access) { - NativeLibraries nativeLibraries = getNativeLibraries(access); - - NativeLibrarySupport.singleton().preregisterUninitializedBuiltinLibrary("javajpeg"); - nativeLibraries.addStaticJniLibrary("javajpeg"); - } - - private static void registerImagingLib(DuringAnalysisAccess access) { - NativeLibraries nativeLibraries = getNativeLibraries(access); - - NativeLibrarySupport.singleton().preregisterUninitializedBuiltinLibrary("mlib_image"); - nativeLibraries.addStaticJniLibrary("mlib_image"); - } - - private static void registerLCMS(DuringAnalysisAccess access) { - NativeLibraries nativeLibraries = getNativeLibraries(access); - - NativeLibrarySupport.singleton().preregisterUninitializedBuiltinLibrary("lcms"); - nativeLibraries.addStaticJniLibrary("lcms"); - } - - private static void registerFreeType(DuringAnalysisAccess access) { - if (SubstrateOptions.StaticExecutable.getValue()) { - /* - * Freetype uses fontconfig through dlsym. This may not work in a statically linked - * executable - */ - return; - } - NativeLibraries nativeLibraries = getNativeLibraries(access); - - NativeLibrarySupport.singleton().preregisterUninitializedBuiltinLibrary("fontmanager"); - nativeLibraries.addStaticJniLibrary("fontmanager", isHeadless() ? "awt_headless" : "awt_xawt"); - nativeLibraries.addDynamicNonJniLibrary("freetype"); - - RuntimeJNIAccess.register(clazz(access, "sun.font.FontConfigManager$FontConfigInfo")); - RuntimeJNIAccess.register(fields(access, "sun.font.FontConfigManager$FontConfigInfo", "fcVersion", "cacheDirs")); - RuntimeJNIAccess.register(clazz(access, "sun.font.FontConfigManager$FcCompFont")); - RuntimeJNIAccess.register(fields(access, "sun.font.FontConfigManager$FcCompFont", "fcName", "firstFont", "allFonts")); - RuntimeJNIAccess.register(clazz(access, "sun.font.FontConfigManager$FontConfigFont")); - RuntimeJNIAccess.register(constructor(access, "sun.font.FontConfigManager$FontConfigFont")); - RuntimeJNIAccess.register(fields(access, "sun.font.FontConfigManager$FontConfigFont", "familyName", "styleStr", "fullName", "fontFile")); - } - - private static void registerColorProfiles(DuringAnalysisAccess duringAnalysisAccess) { - ImageSingletons.lookup(RuntimeResourceSupport.class).addResources(ConfigurationCondition.alwaysTrue(), "sun.java2d.cmm.profiles.*"); - } - - private static void registerFlavorMapProps(DuringAnalysisAccess duringAnalysisAccess) { - ImageSingletons.lookup(RuntimeResourceSupport.class).addResources(ConfigurationCondition.alwaysTrue(), "sun.datatransfer.resources.flavormap.properties"); - } - - private static void registerRTFReaderCharsets(DuringAnalysisAccess duringAnalysisAccess) { - ImageSingletons.lookup(RuntimeResourceSupport.class).addResources(ConfigurationCondition.alwaysTrue(), "javax.swing.text.rtf.charsets.*"); - } - - private static void registerOceanThemeIcons(DuringAnalysisAccess duringAnalysisAccess) { - ImageSingletons.lookup(RuntimeResourceSupport.class).addResources(ConfigurationCondition.alwaysTrue(), "javax.swing.plaf.metal.icons.*"); - ImageSingletons.lookup(RuntimeResourceSupport.class).addResources(ConfigurationCondition.alwaysTrue(), "javax.swing.plaf.basic.icons.*"); - } - - private static void registerHtml32bdtd(DuringAnalysisAccess duringAnalysisAccess) { - ImageSingletons.lookup(RuntimeResourceSupport.class).addResources(ConfigurationCondition.alwaysTrue(), "javax.swing.text.html.parser.html32.bdtd"); - } - - private static void registerDefaultCSS(DuringAnalysisAccess duringAnalysisAccess) { - ImageSingletons.lookup(RuntimeResourceSupport.class).addResources(ConfigurationCondition.alwaysTrue(), "javax.swing.text.html.default.css"); - } - - private static NativeLibraries getNativeLibraries(DuringAnalysisAccess access) { - FeatureImpl.DuringAnalysisAccessImpl a = (FeatureImpl.DuringAnalysisAccessImpl) access; - return a.getNativeLibraries(); - } - - private static boolean isHeadless() { - return GraphicsEnvironment.isHeadless(); - } -} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationManagementExt.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationManagementExt.java index c7af55bb1e1d..0be48e4f9af6 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationManagementExt.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationManagementExt.java @@ -29,13 +29,12 @@ import org.graalvm.nativeimage.IsolateThread; import org.graalvm.nativeimage.c.type.CCharPointer; +import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; import com.oracle.svm.core.feature.InternalFeature; import com.oracle.svm.core.jdk.JNIRegistrationUtil; -import com.oracle.svm.core.jdk.NativeLibrarySupport; import com.oracle.svm.core.jdk.PlatformNativeLibrarySupport; import com.oracle.svm.core.jdk.management.LibManagementExtSupport; -import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; -import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl; +import com.oracle.svm.hosted.FeatureImpl.DuringAnalysisAccessImpl; import com.oracle.svm.hosted.c.NativeLibraries; import com.oracle.svm.hosted.code.CEntryPointCallStubSupport; import com.oracle.svm.hosted.code.CEntryPointData; @@ -43,21 +42,16 @@ @AutomaticallyRegisteredFeature public class JNIRegistrationManagementExt extends JNIRegistrationUtil implements InternalFeature { - - private static final String OPERATING_SYSTEM_IMPL = "com.sun.management.internal.OperatingSystemImpl"; - private NativeLibraries nativeLibraries; - @Override public void beforeAnalysis(BeforeAnalysisAccess access) { - nativeLibraries = ((BeforeAnalysisAccessImpl) access).getNativeLibraries(); - - rerunClassInit(access, OPERATING_SYSTEM_IMPL); + rerunClassInit(access, "com.sun.management.internal.OperatingSystemImpl"); - access.registerReachabilityHandler(this::linkManagementExt, clazz(access, OPERATING_SYSTEM_IMPL)); + access.registerReachabilityHandler(this::linkManagementExt, clazz(access, "com.sun.management.internal.OperatingSystemImpl")); PlatformNativeLibrarySupport.singleton().addBuiltinPkgNativePrefix("com_sun_management_internal_OperatingSystemImpl"); } - private void linkManagementExt(@SuppressWarnings("unused") DuringAnalysisAccess access) { + private void linkManagementExt(DuringAnalysisAccess access) { + NativeLibraries nativeLibraries = ((DuringAnalysisAccessImpl) access).getNativeLibraries(); /* * Note that we register `management_ext` as a non-JNI static library. This avoids pulling * in `JNI_OnLoad`, which is fine since we're only interested in the native methods of the @@ -76,16 +70,4 @@ private void linkManagementExt(@SuppressWarnings("unused") DuringAnalysisAccess CEntryPointCallStubSupport.singleton().registerStubForMethod(method, () -> CEntryPointData.create(method)); } } - - @Override - public void afterAnalysis(AfterAnalysisAccess access) { - boolean managementExtNeeded = access.isReachable(clazz(access, OPERATING_SYSTEM_IMPL)); - if (managementExtNeeded && NativeLibrarySupport.singleton().isPreregisteredBuiltinLibrary("awt_headless")) { - /* - * Ensure that `management_ext` comes before `awt_headless` on the linker command line. - * This is necessary to prevent linker errors such as JDK-8264047. - */ - nativeLibraries.addStaticNonJniLibrary("management_ext", "awt_headless"); - } - } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java index 6be78bd9eb87..f54dad72d016 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java @@ -24,7 +24,6 @@ */ package com.oracle.svm.hosted.snippets; -import java.awt.GraphicsEnvironment; import java.lang.ref.Reference; import java.lang.reflect.Array; import java.lang.reflect.Field; @@ -116,7 +115,6 @@ import com.oracle.svm.common.meta.MultiMethod; import com.oracle.svm.core.FrameAccess; import com.oracle.svm.core.NeverInline; -import com.oracle.svm.core.OS; import com.oracle.svm.core.ParsingReason; import com.oracle.svm.core.RuntimeAssertionsSupport; import com.oracle.svm.core.StaticFieldsSupport; @@ -201,7 +199,6 @@ public static void registerInvocationPlugins(AnnotationSubstitutionProcessor ann registerEdgesPlugins(metaAccess, plugins); registerVMConfigurationPlugins(snippetReflection, plugins); registerPlatformPlugins(snippetReflection, plugins); - registerAWTPlugins(plugins); registerSizeOfPlugins(snippetReflection, plugins); registerReferencePlugins(plugins, parsingReason); registerReferenceAccessPlugins(plugins); @@ -1059,25 +1056,6 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec }); } - /** - * To prevent AWT linkage error on {@link OS#LINUX} that happens with 'awt_headless' in headless - * mode, we eliminate native methods that depend on 'awt_xawt' library in the call-tree. - */ - private static void registerAWTPlugins(InvocationPlugins plugins) { - if (Platform.includedIn(Platform.LINUX.class)) { - Registration r = new Registration(plugins, GraphicsEnvironment.class); - r.register(new RequiredInvocationPlugin("isHeadless") { - @SuppressWarnings("unchecked") - @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - boolean isHeadless = GraphicsEnvironment.isHeadless(); - b.addPush(JavaKind.Boolean, ConstantNode.forBoolean(isHeadless)); - return true; - } - }); - } - } - private static void registerSizeOfPlugins(SnippetReflectionProvider snippetReflection, InvocationPlugins plugins) { Registration r = new Registration(plugins, SizeOf.class); r.register(new RequiredInvocationPlugin("get", Class.class) { From a57ef4efd8a336869778d416769d549ec00b91b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksandar=20Pejovi=C4=87?= Date: Fri, 9 Sep 2022 15:42:28 +0200 Subject: [PATCH 2/3] Add support for dynamic linking of AWT libraries on Linux --- .../svm/hosted/image/CCLinkerInvocation.java | 6 +- .../hosted/jdk/JNIRegistrationAWTSupport.java | 57 ++++++--- .../hosted/jdk/JNIRegistrationSupport.java | 121 +++++++++++------- 3 files changed, 119 insertions(+), 65 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/CCLinkerInvocation.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/CCLinkerInvocation.java index 8b696294e5a3..a6016f74923a 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/CCLinkerInvocation.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/CCLinkerInvocation.java @@ -57,6 +57,7 @@ import com.oracle.svm.hosted.c.NativeLibraries; import com.oracle.svm.hosted.c.codegen.CCompilerInvoker; import com.oracle.svm.hosted.c.libc.HostedLibCBase; +import com.oracle.svm.hosted.jdk.JNIRegistrationSupport; public abstract class CCLinkerInvocation implements LinkerInvocation { @@ -269,9 +270,8 @@ private static class BinutilsCCLinkerInvocation extends CCLinkerInvocation { exportedSymbols.append("{\n"); /* Only exported symbols are global ... */ exportedSymbols.append("global:\n"); - for (String symbol : getImageSymbols(true)) { - exportedSymbols.append('\"').append(symbol).append("\";\n"); - } + Stream.concat(getImageSymbols(true).stream(), JNIRegistrationSupport.getShimLibrarySymbols()) + .forEach(symbol -> exportedSymbols.append('\"').append(symbol).append("\";\n")); /* ... everything else is local. */ exportedSymbols.append("local: *;\n"); exportedSymbols.append("};"); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationAWTSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationAWTSupport.java index 358329c2e2e6..e0095bac7089 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationAWTSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationAWTSupport.java @@ -24,32 +24,28 @@ */ package com.oracle.svm.hosted.jdk; +import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; -import com.oracle.svm.core.feature.InternalFeature; import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; +import com.oracle.svm.core.feature.InternalFeature; +import com.oracle.svm.core.jdk.JNIRegistrationUtil; import com.oracle.svm.hosted.FeatureImpl.BeforeImageWriteAccessImpl; -@Platforms(Platform.WINDOWS.class) +@Platforms({Platform.WINDOWS.class, Platform.LINUX.class}) @AutomaticallyRegisteredFeature -public class JNIRegistrationAWTSupport implements InternalFeature { +public class JNIRegistrationAWTSupport extends JNIRegistrationUtil implements InternalFeature { @Override public void afterAnalysis(AfterAnalysisAccess access) { JNIRegistrationSupport jniRegistrationSupport = JNIRegistrationSupport.singleton(); if (jniRegistrationSupport.isRegisteredLibrary("awt")) { jniRegistrationSupport.addJvmShimExports( - "JVM_CurrentTimeMillis", - "JVM_RaiseSignal", "jio_snprintf"); jniRegistrationSupport.addJavaShimExports( - "JDK_LoadSystemLibrary", "JNU_CallMethodByName", - "JNU_CallMethodByNameV", "JNU_CallStaticMethodByName", - "JNU_ClassString", "JNU_GetEnv", - "JNU_GetFieldByName", "JNU_GetStaticFieldByName", "JNU_IsInstanceOfByName", "JNU_NewObjectByName", @@ -57,13 +53,36 @@ public void afterAnalysis(AfterAnalysisAccess access) { "JNU_SetFieldByName", "JNU_ThrowArrayIndexOutOfBoundsException", "JNU_ThrowByName", - "JNU_ThrowIOException", "JNU_ThrowIllegalArgumentException", "JNU_ThrowInternalError", "JNU_ThrowNullPointerException", - "JNU_ThrowOutOfMemoryError", - "getEncodingFromLangID", - "getJavaIDFromLangID"); + "JNU_ThrowOutOfMemoryError"); + if (isWindows()) { + jniRegistrationSupport.addJvmShimExports( + "JVM_CurrentTimeMillis", + "JVM_RaiseSignal"); + jniRegistrationSupport.addJavaShimExports( + "JDK_LoadSystemLibrary", + "JNU_CallMethodByNameV", + "JNU_ClassString", + "JNU_GetFieldByName", + "JNU_ThrowIOException", + "getEncodingFromLangID", + "getJavaIDFromLangID"); + } else { + jniRegistrationSupport.addJvmShimExports( + "jio_fprintf"); + jniRegistrationSupport.addJavaShimExports( + "JNU_GetStringPlatformChars", + "JNU_ReleaseStringPlatformChars"); + if (JavaVersionUtil.JAVA_SPEC == 11) { + jniRegistrationSupport.addJavaShimExports( + "JNU_ThrowNoSuchFieldError"); + } + /* Since `awt` loads either `awt_headless` or `awt_xawt`, we register them both. */ + jniRegistrationSupport.registerLibrary("awt_headless"); + jniRegistrationSupport.registerLibrary("awt_xawt"); + } } if (jniRegistrationSupport.isRegisteredLibrary("javaaccessbridge")) { /* Dependency on `jawt` is not expressed in Java, so we register it manually here. */ @@ -73,14 +92,20 @@ public void afterAnalysis(AfterAnalysisAccess access) { jniRegistrationSupport.addJavaShimExports( "JNU_GetEnv", "JNU_ThrowByName", - "JNU_ThrowNullPointerException", - "jio_snprintf"); + "JNU_ThrowNullPointerException"); + if (isWindows()) { + jniRegistrationSupport.addJavaShimExports( + "jio_snprintf"); + } else { + jniRegistrationSupport.addJvmShimExports( + "jio_snprintf"); + } } } @Override public void beforeImageWrite(BeforeImageWriteAccess access) { - if (JNIRegistrationSupport.singleton().isRegisteredLibrary("awt")) { + if (isWindows() && JNIRegistrationSupport.singleton().isRegisteredLibrary("awt")) { ((BeforeImageWriteAccessImpl) access).registerLinkerInvocationTransformer(linkerInvocation -> { /* * Add a Windows library that is pulled in as a side effect of exporting the diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationSupport.java index 0a884f74aabf..09fc3474c8fa 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationSupport.java @@ -31,10 +31,7 @@ import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.SortedMap; import java.util.SortedSet; @@ -42,6 +39,7 @@ import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.stream.Stream; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugContext.Activation; @@ -60,6 +58,7 @@ import com.oracle.svm.core.BuildArtifacts; import com.oracle.svm.core.ParsingReason; +import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; import com.oracle.svm.core.feature.InternalFeature; import com.oracle.svm.core.jdk.JNIRegistrationUtil; @@ -161,27 +160,40 @@ void addJavaShimExports(String... exports) { private void addShimExports(String shimName, String... exports) { assert exports != null && exports.length > 0; - shimExports.computeIfAbsent(shimName, s -> new TreeSet<>()).addAll(Arrays.asList(exports)); + shimExports.computeIfAbsent(shimName, s -> new TreeSet<>()).addAll(List.of(exports)); + } + + /** Returns symbols that are re-exported by shim libraries. */ + public static Stream getShimLibrarySymbols() { + if (ImageSingletons.contains(JNIRegistrationSupport.class)) { + return singleton().getShimExports(); + } + return Stream.empty(); } @Override public void beforeImageWrite(BeforeImageWriteAccess access) { + if (SubstrateOptions.StaticExecutable.getValue() || isDarwin()) { + return; /* Not supported. */ + } + if (shimExports.containsKey("jvm") || Options.CreateJvmShim.getValue()) { /* When making a `jvm` shim, also re-export the JNI functions that VM exports. */ addJvmShimExports("JNI_CreateJavaVM", "JNI_GetCreatedJavaVMs", "JNI_GetDefaultJavaVMInitArgs"); } - if (isWindows()) { - ((BeforeImageWriteAccessImpl) access).registerLinkerInvocationTransformer(linkerInvocation -> { - /* Make sure the native image exports all the symbols necessary for shim DLLs. */ - shimExports.values().stream() - .flatMap(Collection::stream) - .distinct() - .map("/export:"::concat) - .forEach(linkerInvocation::addNativeLinkerOption); - return linkerInvocation; - }); - } + ((BeforeImageWriteAccessImpl) access).registerLinkerInvocationTransformer(linkerInvocation -> { + /* Make sure the native image contains all symbols necessary for shim libraries. */ + getShimExports().map(isWindows() ? "/export:"::concat : "-Wl,-u,"::concat) + .forEach(linkerInvocation::addNativeLinkerOption); + return linkerInvocation; + }); + } + + private Stream getShimExports() { + return shimExports.values().stream() + .flatMap(Collection::stream) + .distinct(); } private AfterImageWriteAccessImpl accessImpl; @@ -189,20 +201,21 @@ public void beforeImageWrite(BeforeImageWriteAccess access) { @Override @SuppressWarnings("try") public void afterImageWrite(AfterImageWriteAccess access) { + if (SubstrateOptions.StaticExecutable.getValue() || isDarwin()) { + return; /* Not supported. */ + } + accessImpl = (AfterImageWriteAccessImpl) access; try (Scope s = accessImpl.getDebugContext().scope("JDKLibs")) { - if (isWindows()) { - /* On Windows, JDK libraries are in `\bin` directory. */ - Path jdkLibDir = Paths.get(System.getProperty("java.home"), "bin"); - /* Copy JDK libraries needed to run the native image. */ - copyJDKLibraries(jdkLibDir); - /* - * JDK libraries can depend on `jvm.dll` and `java.dll`, so to satisfy their - * dependencies, we create shim DLLs that re-export the actual functions from the - * native image itself. - */ - makeShimDLLs(); - } + /* On Windows, JDK libraries are in `\bin` directory. */ + Path jdkLibDir = Path.of(System.getProperty("java.home"), isWindows() ? "bin" : "lib"); + /* Copy JDK libraries needed to run the native image. */ + copyJDKLibraries(jdkLibDir); + /* + * JDK libraries can depend on `libjvm` and `libjava`, so to satisfy their dependencies + * we use shim libraries to re-export the actual functions from the native image itself. + */ + makeShimLibraries(); } finally { accessImpl = null; } @@ -247,35 +260,50 @@ private void copyJDKLibraries(Path jdkLibDir) { } } - /** Makes shim DLLs to satisfy dependencies of JDK libraries. */ + /** Makes shim libraries that are necessary to satisfy dependencies of JDK libraries. */ @SuppressWarnings("try") - private void makeShimDLLs() { + private void makeShimLibraries() { for (String shimName : shimExports.keySet()) { DebugContext debug = accessImpl.getDebugContext(); - try (Scope s = debug.scope(shimName + "ShimDLL")) { + try (Scope s = debug.scope(shimName + "Shim")) { if (debug.isLogEnabled(DebugContext.INFO_LEVEL)) { debug.log("exports: %s", String.join(", ", shimExports.get(shimName))); } - makeShimDLL(shimName); + makeShimLibrary(shimName); } } } - /** Makes a shim DLL by re-exporting the actual functions from the native image itself. */ + /** Makes a shim library that re-exports functions from the native image. */ @SuppressWarnings("try") - private void makeShimDLL(String shimName) { - Path shimDLL = accessImpl.getImagePath().resolveSibling(shimName + ".dll"); - /* Dependencies are the native image (so we can re-export from it) and C Runtime. */ - Path[] shimDLLDependencies = {getImageImportLib(), Paths.get("msvcrt.lib")}; - + private void makeShimLibrary(String shimName) { assert ImageSingletons.contains(CCompilerInvoker.class); - List linkerCommand = ImageSingletons.lookup(CCompilerInvoker.class) - .createCompilerCommand(Collections.emptyList(), shimDLL, shimDLLDependencies); - /* First add linker options ... */ - linkerCommand.addAll(Arrays.asList("/link", "/dll", "/implib:" + shimName + ".lib")); - /* ... and then the exports that were added for re-export. */ - for (String export : shimExports.get(shimName)) { - linkerCommand.add("/export:" + export); + + List linkerCommand; + Path image = accessImpl.getImagePath(); + Path shimLibrary = image.resolveSibling(System.mapLibraryName(shimName)); + if (isWindows()) { + /* Dependencies are the native image (so we can re-export from it) and C Runtime. */ + linkerCommand = ImageSingletons.lookup(CCompilerInvoker.class) + .createCompilerCommand(List.of(), shimLibrary, getImageImportLib(), Path.of("msvcrt.lib")); + /* First add linker options ... */ + linkerCommand.addAll(List.of("/link", "/dll", "/implib:" + shimName + ".lib")); + /* ... and then the exports that were added for re-export. */ + for (String export : shimExports.get(shimName)) { + linkerCommand.add("/export:" + export); + } + } else { + /* + * To satisfy the dynamic loader and enable re-export it is enough to have a library + * with the expected name. So we just create an empty one ... + */ + linkerCommand = ImageSingletons.lookup(CCompilerInvoker.class) + .createCompilerCommand(List.of("-shared", "-x", "c"), shimLibrary, Path.of("/dev/null")); + /* ... and add an explicit dependency on the native image if it is a shared library. */ + if (!accessImpl.getImageKind().isExecutable) { + linkerCommand.addAll(List.of("-Wl,-no-as-needed", "-L" + image.getParent(), "-l:" + image.getFileName(), + "-Wl,--enable-new-dtags", "-Wl,-rpath,$ORIGIN")); + } } DebugContext debug = accessImpl.getDebugContext(); @@ -284,8 +312,8 @@ private void makeShimDLL(String shimName) { if (FileUtils.executeCommand(linkerCommand) != 0) { VMError.shouldNotReachHere(); } - BuildArtifacts.singleton().add(ArtifactType.JDK_LIBRARY_SHIM, shimDLL); - debug.log("%s.dll: OK", shimName); + BuildArtifacts.singleton().add(ArtifactType.JDK_LIBRARY_SHIM, shimLibrary); + debug.log("%s: OK", shimLibrary.getFileName()); } catch (InterruptedException e) { throw new InterruptImageBuilding(); } catch (IOException e) { @@ -295,6 +323,7 @@ private void makeShimDLL(String shimName) { /** Returns the import library of the native image. */ private Path getImageImportLib() { + assert isWindows(); Path image = accessImpl.getImagePath(); String imageName = String.valueOf(image.getFileName()); String importLibName = imageName.substring(0, imageName.lastIndexOf('.')) + ".lib"; From 6c87bcd36ec498371113c98885149a45b07bf791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksandar=20Pejovi=C4=87?= Date: Tue, 21 Feb 2023 11:54:24 +0100 Subject: [PATCH 3/3] Add changelog entry --- substratevm/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/substratevm/CHANGELOG.md b/substratevm/CHANGELOG.md index 515d8dc22998..a11010892c34 100644 --- a/substratevm/CHANGELOG.md +++ b/substratevm/CHANGELOG.md @@ -22,6 +22,7 @@ This changelog summarizes major changes to GraalVM Native Image. * (GR-44216) Native Image is now shipped as part of the GraalVM JDK and thus no longer needs to be installed via `gu install native-image`. * (GR-44105) A warning is displayed when trying to generate debug info on macOS since that is not supported. It is now an error to use `-H:+StripDebugInfo` on macOS or `-H:-StripDebugInfo` on Windows since those values are not supported. * (GR-43966) Remove analysis options -H:AnalysisStatisticsFile and -H:ImageBuildStatisticsFile. Output files are now written to fixed subdirectories relative to image location (reports/image_build_statistics.json). +* (GR-40641) Dynamic linking of AWT libraries on Linux. ## Version 22.3.0 * (GR-35721) Remove old build output style and the `-H:±BuildOutputUseNewStyle` option.