JDK-7131153 : GetDC called way too many times - causes bad performance.
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 8
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_7
  • CPU: x86
  • Submitted: 2012-01-18
  • Updated: 2019-07-25
  • Resolved: 2012-02-07
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7 JDK 8
6u81Fixed 7u55Fixed 8 b25Fixed
Description
FULL PRODUCT VERSION :
java version "1.7.0_02"
Java(TM) SE Runtime Environment (build 1.7.0_02-b13)
Java HotSpot(TM) 64-Bit Server VM (build 22.0-b10, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]

EXTRA RELEVANT SYSTEM CONFIGURATION :
Any PC with at least 8 CPU cores.

A DESCRIPTION OF THE PROBLEM :
After some investigation of why multiple instances of certain java apps won't startup in a timely manor, we tracked down the fact that \jdk\src\windows\native\sun\font\fontpath.c make calls the Windows API GetDC(NULL) hundreds of times in service of the Java_sun_awt_Win32FontManager_populateFontFileNameMap0(...) function. We isolated and reproduced the same performance issue in a standalone program based on  \jdk\src\windows\native\sun\font\fontpath.c and believe that a) the calls to GetDC(NULL) leak handles, and b) calling GetDC once, saving the handle and passing the saved handle into all EnumFontFamiliesExW() calls restores performance.

REGRESSION.  Last worked in version 1.4.2

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Take code given below and create a file named TrueTypeJokerman.java
2. compiler (using javac.exe) into TrueTypeJokerman.class
3. from a dos command prompt, run the following command:

for /l %i in (1,1,16) do start /B cmd /C "C:\Program Files\Java\jdk1.7.0_02\jre\bin\java.exe" TrueTypeJokerman

and notice how long it takes for the apps windows to appear _and_ that until they do, the system seems frozen.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
expect application windows to appear quickly...within just a second or two.
ACTUAL -
It takes about 45 seconds for all 16 app windows to appear. During this time, the system is frozen and you can't even click to bring task manager up.

If I try to start 32 process instances, it takes a whopping 195 seconds before the app windows appears.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.Font;
import java.awt.GraphicsEnvironment;

import javax.swing.JFrame;
import javax.swing.JLabel;

public class TrueTypeJokerman extends JFrame {

  private String textMessage = "Java Internationalization";

  public TrueTypeJokerman() {
    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    ge.getAllFonts();

    Font font = new Font("Jokerman", Font.PLAIN, 35);
    JLabel textLabel = new JLabel(textMessage);
    textLabel.setFont(font);

    getContentPane().add(textLabel);
    setVisible(true);
  }

  public static void main(String[] args) {
    JFrame frame = new TrueTypeJokerman();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);
  }
}
---------- END SOURCE ----------

Comments
SQE has functional test for this bug fix. The results are ok for jdk8 and jdk8u5. So, SQE OK to take the fix into CPU14_02
27-01-2014

CAP member had reported the same issue and would like back port the fix to 7 update release - Have a number of users running a GUI application on Windows 7 and been reported fairly slow performance. After working with Microsoft it turns out that Java 7 creates excessive number of GDI DeviceContext objects within FontManager. Further investigation has conclude that the issue has been addressed in Java 8 with this bug. Have tested the problem with the testcase provided there and it definitely trigger the issue, and trying Java 7 Update 51 this issue still occurs. Would like backport this fix back into Java 7 stream.
20-12-2013

2D_Font/SetFontPerformanceTest
28-06-2013

EVALUATION I don't know how much of a regression this can be since the code that introduced this was actually a massive performance *improvement* for startup. Previously requesting a font triggered opening all the windows font files. Now it doesn't. However we clearly want to fix a leak and take any improvements we can get. On my PC this shaves about 33ms off the JNI call time. Down from 40ms to 7ms. The overall overhead of the lookup including java code we execute around it means its probably down from about 250ms to 210ms. I'm not sure if it can therefore account for everything the bug reporter sees but its a nice saving and should fix the leakage.
19-01-2012

EVALUATION I think someone internal noticed this but I forgot to file a bug about it. We've looked for DC leaks before and I can only suppose that because this code path is executed only once that it didn't show up as being a leak due to already having happened and being in a steady state once we are up and running.
18-01-2012