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