"Oracle" JDK ships with fonts. And it has a default fontconfig.properties (not the same thing as libfontconfig) file that maps all the logical fonts to those fonts. So it fully meets the spec and can function just fine on a system that has no other fonts installed. So on reflection we wouldn't want to fail at this point without checking to see if we actually
can continue.
This doesn't help "Open" JDK as it is, since it doesn't have fonts, but there's nothing to stop an OpenJDK port doing the exact same, except that its kind of pointless for a distro to do that as it would be easier to make libfontconfig and some core fonts a pre-requisite package.

I think I'll need to review everyone's "requirements" again to say
exactly what should be the path forward.

For your "headless" situation, I'm not completely clear about what you intend to run, but it occurs to me that if you are even tickling this code, its reasonable to suppose that the app is likely to need fonts. Whereas someone running a back-end server app would never initialise the AWT toolkit, so shouldn't care less whether fonts are installed.

-phil.


On 6/5/2013 9:38 AM, Jeremy Manson wrote:
I don't have enough of an understanding of the issues to say that this configuration should necessarily be supported. However, I am relatively sure that it shouldn't be supported just enough to make the error and the code confusing. If it doesn't find any fonts, FontConfigManager logs something to the platform logger and returns quietly.

      213         if (anyFont == null) {
      214             if (FontUtilities.isLogging()) {
215 PlatformLogger logger = FontUtilities.getLogger(); 216 logger.info <http://logger.info>("Fontconfig returned no fonts at all.");
      217             }
      218             fontConfigFailed = true;
      219             return;

and then when the X11FontManager "believes" it doesn't find a default font, it does a fallback:

787 /* Absolute last ditch attempt in the face of fontconfig problems. 788 * If we didn't match, pick the first, or just make something
      789          * up so we don't NPE.
      790          */
      791         if (info[0] == null) {
      792             if (fontConfigFonts.length > 0 &&
      793 fontConfigFonts[0].firstFont.fontFile != null) {
794 info[0] = fontConfigFonts[0].firstFont.familyName;
      795                 info[1] = fontConfigFonts[0].firstFont.fontFile;
      796             } else {
      797                 info[0] = "Dialog";
      798                 info[1] = "/dialog.ttf";
      799             }
      800         }

That would make the casual reader believe that "no fonts" is a supported configuration (or, at least, a configuration that isn't supposed to NPE). But the fallback doesn't get hit in this case, because the X11FontManager believes that getFontConfigFonts can't return null.

It seems reasonable to throw an exception, if that's what you want to do, but it seems to me that the exception should have a relatively clear message about what happened, and the fact that that configuration is unsupported. If you really want not to have code that deals with a lack of fonts, it would make a certain amount of sense to take out the code that is there and tries to do so. As it is, the code and its behavior occupy a very confusing middle ground, where the developer has to trace through the library to figure out what happened and why it happened.

(As for not linking with libfontconfig: we're trying to make a JDK that works regardless of whether fontconfig is there. It should be able to work in headless, stripped down mode, and for a developer who wants to use eclipse. I don't mind if devs need to catch exceptions on the headless machines, but they like to know why they are catching them.)

Jeremy



On Wed, Jun 5, 2013 at 1:56 AM, Jiri Vanek <jva...@redhat.com <mailto:jva...@redhat.com>> wrote:

    Hi!


    This is known issue - Openjdk fails when no fonts are installed.

    You can fix this by your own fontmanager (feel free to inspire at
    https://bugzilla.redhat.com/show_bug.cgi?id=862355#c5 where I'm
    creating an custom dummy fontmanager in case of failure)
    You can set up similar manager class by -Dsun.font.fontmanager
    property.

    Or you can support me and "force somebody" to review my patch
    where I have tried to smuggle inside Openjdk default fallback font[1]

    On the contrary, if [1] will go in, then it can mask deeper
    problems (as can be eg yours).



    [1]http://mail.openjdk.java.net/pipermail/2d-dev/2013-January/002999.html


    Best regards
     J.



    On 06/05/2013 01:32 AM, Jeremy Manson wrote:

        Hi Phil,

        Thanks for the response.  You've actually caught me out: this
        was a bug I found a while ago, and am
        only now just getting around to reporting.  I made this change
        locally (inside Google), and lost my
        repro instructions.  It was probably for a user issue, which
        means that I'm too chicken to back it
        out and see what happens.  This fix looked obvious enough that
        I thought I could get away with it,
        since it is clearly the case that X11FontManager expects a
        non-null fontConfigFonts regardless of
        the value of fontConfigFailed.

        IIRC, the cause was either that the fontconfig library wasn't
        installed or that the fontconfig file
        was obsolete / incorrect for the given system.  I almost
        certainly did not fix any ULEs (I would
        have a record of that).  We have some stripped down systems,
        and this may have been one of them.  It
        was a headless configuration.  I did preserve my stack trace:

        Exception in thread "main" java.lang.NullPointerException at
        sun.awt.X11FontManager.getDefaultPlatformFont(X11FontManager.java:779)
        at
        sun.font.SunFontManager$2.run(SunFontManager.java:428) at
        java.security.AccessController.doPrivileged(Native Method) at
        sun.font.SunFontManager.<init>(SunFontManager.java:371) at
        sun.awt.X11FontManager.<init>(X11FontManager.java:32) at
        sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native
        Method) at
        
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
        at
        
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at
        java.lang.reflect.Constructor.newInstance(Constructor.java:530) at
        java.lang.Class.newInstance0(Class.java:372) at
        java.lang.Class.newInstance(Class.java:325) at
        sun.font.FontManagerFactory$1.run(FontManagerFactory.java:80) at
        java.security.AccessController.doPrivileged(Native Method) at
        sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:71)
        at
        
sun.java2d.SunGraphicsEnvironment.getFontManagerForSGE(SunGraphicsEnvironment.java:185)
        at
        
sun.java2d.SunGraphicsEnvironment.getAllFonts(SunGraphicsEnvironment.java:192)
        at
        
sun.java2d.HeadlessGraphicsEnvironment.getAllFonts(HeadlessGraphicsEnvironment.java:91)

        I'm sure that the line numbers are obsolete, but you get the
        general idea. I don't seem to have what
        was beneath that in the stack, but I imagine it was something
        that was relatively comfortable with
        getAllFonts returning nothing (as appropriate).

        Having said all that, it seems to me that if fontConfigFailed
        is not allowed to be true unless you
        have a system configuration problem, then that should be made
        clear at runtime, and that you should
        not get rather mysterious NPEs at later points in the code.
         You do have a fallback in
        getDefaultPlatformFont that says "make something up so that we
        don't get NPE", which made me think
        that the original author intended to prefer avoiding NPEs.

        Jeremy


        On Tue, Jun 4, 2013 at 3:29 PM, Phil Race
        <philip.r...@oracle.com <mailto:philip.r...@oracle.com>
        <mailto:philip.r...@oracle.com <mailto:philip.r...@oracle.com>>>

        wrote:

            Jeremy,

            Why didn't it return any fonts ? Is this because the
        libfontconfig library isn't installed ?

            We've been runtime loading that lib but these days could
        potentially
            switch to linking against it at compile time, in which
        case you won't
            even get this far. So in other words this could be a
        system config issue.
            The most common thing I've seen is that 64 bit Linux
        doesn't have
            all the libs to run a 32 bit JRE. You probably found and
        fixed all of those
            because it was Unsatisfiedlinkerror or similar but the
        runtime linking
            is disguising that its really the same problem.

            If you really don't have any fonts installed, then that's also
            a missing package and we perhaps should have a better
        diagnostic,
            but there isn't really any point in continuing anyway
        without any fonts.
            Even headless applications may require fonts.

            -phil.


            On 6/4/2013 2:50 PM, Jeremy Manson wrote:

                Hi folks,

                I encountered a NullPointerException in the above
        method, when fontconfig doesn't return any
                fonts:

        
http://hg.openjdk.java.net/__jdk8/jdk8/jdk/file/__7eae7c89dab4/src/solaris/__classes/sun/awt/__X11FontManager.java


<http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/7eae7c89dab4/src/solaris/classes/sun/awt/X11FontManager.java>

                Line 779.  The issue is that FontConfigManager sets
        fontConfigFonts to null when Fontconfig
                doesn't return any fonts:

        
http://hg.openjdk.java.net/__jdk8/jdk8/jdk/file/__7eae7c89dab4/src/solaris/__classes/sun/font/__FontConfigManager.java


<http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/7eae7c89dab4/src/solaris/classes/sun/font/FontConfigManager.java>

                Line 218.

                The solution I came up with is to initialize
        fontConfigFonts with a zero-element array in
                this case:

                diff --git
        a/src/solaris/classes/sun/__font/FontConfigManager.java
                b/src/solaris/classes/sun/__font/FontConfigManager.java
                ---
        a/src/solaris/classes/sun/__font/FontConfigManager.java
                +++
        b/src/solaris/classes/sun/__font/FontConfigManager.java
                @@ -216,6 +216,7 @@
        logger.info <http://logger.info> <http://logger.info>
        <http://logger.info>("__Fontconfig returned no fonts at all.");


                              }
                              fontConfigFailed = true;
                +            fontConfigFonts = new FcCompFont[0];
                              return;
                          } else if (fontConfigFailed) {
                              for (int i = 0; i< fontArr.length; i++) {

                Thanks for your attention!

                Jeremy






Reply via email to