changeset 58048:b344cf155157

8221741: ClassCastException can happen when fontconfig.properties is used Reviewed-by: mbaesken, itakiguchi
author clanger
date Sun, 02 Feb 2020 17:41:33 +0100
parents 2777408b8281
children 2f9416465d1d
files src/java.desktop/share/classes/sun/font/SunFontManager.java src/java.desktop/share/classes/sun/font/TrueTypeFont.java test/jdk/java/awt/font/DefaultFontTest/DefaultFontTest.java
diffstat 3 files changed, 94 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.desktop/share/classes/sun/font/SunFontManager.java	Sat Jan 25 22:46:20 2020 -0800
+++ b/src/java.desktop/share/classes/sun/font/SunFontManager.java	Sun Feb 02 17:41:33 2020 +0100
@@ -129,6 +129,8 @@
         }
     }
 
+    private static Font2DHandle FONT_HANDLE_NULL = new Font2DHandle(null);
+
      public static final int FONTFORMAT_NONE = -1;
      public static final int FONTFORMAT_TRUETYPE = 0;
      public static final int FONTFORMAT_TYPE1 = 1;
@@ -949,7 +951,7 @@
                             .info("Opening deferred font file " + fileNameKey);
         }
 
-        PhysicalFont physicalFont;
+        PhysicalFont physicalFont = null;
         FontRegistrationInfo regInfo = deferredFontFiles.get(fileNameKey);
         if (regInfo != null) {
             deferredFontFiles.remove(fileNameKey);
@@ -959,21 +961,19 @@
                                             regInfo.javaRasterizer,
                                             regInfo.fontRank);
 
-
             if (physicalFont != null) {
                 /* Store the handle, so that if a font is bad, we
                  * retrieve the substituted font.
                  */
                 initialisedFonts.put(fileNameKey, physicalFont.handle);
             } else {
-                initialisedFonts.put(fileNameKey,
-                                     getDefaultPhysicalFont().handle);
+                initialisedFonts.put(fileNameKey, FONT_HANDLE_NULL);
             }
         } else {
             Font2DHandle handle = initialisedFonts.get(fileNameKey);
             if (handle == null) {
                 /* Probably shouldn't happen, but just in case */
-                physicalFont = getDefaultPhysicalFont();
+                initialisedFonts.put(fileNameKey, FONT_HANDLE_NULL);
             } else {
                 physicalFont = (PhysicalFont)(handle.font2D);
             }
@@ -1080,15 +1080,20 @@
      */
     public PhysicalFont getDefaultPhysicalFont() {
         if (defaultPhysicalFont == null) {
-            /* findFont2D will load all fonts before giving up the search.
-             * If the JRE Lucida isn't found (eg because the JRE fonts
-             * directory is missing), it could find another version of Lucida
-             * from the host system. This is OK because at that point we are
-             * trying to gracefully handle/recover from a system
-             * misconfiguration and this is probably a reasonable substitution.
-             */
-            defaultPhysicalFont = (PhysicalFont)
-                findFont2D(getDefaultFontFaceName(), Font.PLAIN, NO_FALLBACK);
+            String defaultFontName = getDefaultFontFaceName();
+            // findFont2D will load all fonts
+            Font2D font2d = findFont2D(defaultFontName, Font.PLAIN, NO_FALLBACK);
+            if (font2d != null) {
+                if (font2d instanceof PhysicalFont) {
+                    defaultPhysicalFont = (PhysicalFont)font2d;
+                } else {
+                    if (FontUtilities.isLogging()) {
+                        FontUtilities.getLogger()
+                            .warning("Font returned by findFont2D for default font name " +
+                                     defaultFontName + " is not a physical font: " + font2d.getFontName(null));
+                    }
+                }
+            }
             if (defaultPhysicalFont == null) {
                 /* Because of the findFont2D call above, if we reach here, we
                  * know all fonts have already been loaded, just accept any
@@ -1096,12 +1101,8 @@
                  * and I don't know how to recover from there being absolutely
                  * no fonts anywhere on the system.
                  */
-                Iterator<PhysicalFont> i = physicalFonts.values().iterator();
-                if (i.hasNext()) {
-                    defaultPhysicalFont = i.next();
-                } else {
-                    throw new Error("Probable fatal error:No fonts found.");
-                }
+                defaultPhysicalFont = physicalFonts.values().stream().findFirst()
+                    .orElseThrow(()->new Error("Probable fatal error: No physical fonts found."));
             }
         }
         return defaultPhysicalFont;
--- a/src/java.desktop/share/classes/sun/font/TrueTypeFont.java	Sat Jan 25 22:46:20 2020 -0800
+++ b/src/java.desktop/share/classes/sun/font/TrueTypeFont.java	Sun Feb 02 17:41:33 2020 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -39,6 +39,9 @@
 import java.nio.ShortBuffer;
 import java.nio.channels.ClosedChannelException;
 import java.nio.channels.FileChannel;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -321,15 +324,10 @@
                 FontUtilities.getLogger().info("open TTF: " + platName);
             }
             try {
-                RandomAccessFile raf = (RandomAccessFile)
-                java.security.AccessController.doPrivileged(
-                    new java.security.PrivilegedAction<Object>() {
-                        public Object run() {
-                            try {
-                                return new RandomAccessFile(platName, "r");
-                            } catch (FileNotFoundException ffne) {
-                            }
-                            return null;
+                RandomAccessFile raf = AccessController.doPrivileged(
+                    new PrivilegedExceptionAction<RandomAccessFile>() {
+                        public RandomAccessFile run() throws FileNotFoundException {
+                            return new RandomAccessFile(platName, "r");
                     }
                 });
                 disposerRecord.channel = raf.getChannel();
@@ -340,9 +338,13 @@
                         ((SunFontManager) fm).addToPool(this);
                     }
                 }
-            } catch (NullPointerException e) {
+            } catch (PrivilegedActionException e) {
                 close();
-                throw new FontFormatException(e.toString());
+                Throwable reason = e.getCause();
+                if (reason == null) {
+                    reason = e;
+                }
+                throw new FontFormatException(reason.toString());
             } catch (ClosedChannelException e) {
                 /* NIO I/O is interruptible, recurse to retry operation.
                  * The call to channel.size() above can throw this exception.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/font/DefaultFontTest/DefaultFontTest.java	Sun Feb 02 17:41:33 2020 +0100
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2019, 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8221741
+ * @modules java.desktop/sun.font
+ * @summary Test font initialization
+ */
+
+import java.awt.Font;
+import java.awt.GraphicsEnvironment;
+import java.util.Arrays;
+
+import sun.font.Font2D;
+import sun.font.SunFontManager;
+
+public class DefaultFontTest {
+    public static void main(String[] args) throws Exception {
+        // this triggers font initialization
+        String[] fontFamilyNames = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
+        if (fontFamilyNames != null) {
+            System.out.println("FontFamilies:");
+            Arrays.asList(fontFamilyNames).stream().forEach((fontname)->System.out.println(fontname));
+        }
+        SunFontManager sfm = SunFontManager.getInstance();
+        Font[] createdFonts = sfm.getCreatedFonts();
+        if (createdFonts != null) {
+            System.out.println("\nCreated Fonts:");
+            Arrays.asList(createdFonts).stream().forEach((font)->System.out.println(font));
+        }
+        Font2D[] registeredFonts = sfm.getRegisteredFonts();
+        if (registeredFonts != null) {
+            System.out.println("\nRegistered Fonts:");
+            Arrays.asList(registeredFonts).stream().forEach((font)->System.out.println(font));
+        }
+        System.out.println("\nDefault physical font: " + sfm.getDefaultPhysicalFont());
+    }
+}