我在Oracle JDK 7/8和OpenSUSE 13.1下开发swing应用程序时遇到了麻烦:他们花了太多时间与JDK 6下运行的同一个应用程序进行比较。
这是我的主要测试代码:
final long start = System.currentTimeMillis();
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
} catch (Exception e1) {
e1.printStackTrace();
}
System.out.println("Set LAF. Milliseconds from start app: " + (System.currentTimeMillis() - start));
EventQueue.invokeLater(new Runnable() {
public void run() {
TestSwingJFrame frame = new TestSwingJFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Backup Utilities");
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setResizable(false);
System.out.println("Render app. Milliseconds from start app: " + (System.currentTimeMillis() - start));
}
});
TestSwingJFrame.java :( 4个JLabel,2个JTextField,4个JButton,1个JTextArea,根本没有进程,只是UI元素)
public TestSwingJFrame() {
setBounds(100, 100, 360, 575);
getContentPane().setLayout(null);
JLabel labelBackup = new JLabel(Constants.UI.TEXT_BACKUPS);
labelBackup.setBounds(12, 12, 63, 25);
getContentPane().add(labelBackup);
JComboBox comboBoxBackups = new JComboBox();
comboBoxBackups.setBounds(70, 12, 265, 25);
getContentPane().add(comboBoxBackups);
JLabel labelDate = new JLabel(Constants.UI.TEXT_DATE);
labelDate.setBounds(12, 46, 63, 25);
getContentPane().add(labelDate);
JTextField textDate = new JTextField();
textDate.setBounds(70, 46, 120, 25);
getContentPane().add(textDate);
textDate.setColumns(10);
textDate.setEditable(false);
JLabel labelVer = new JLabel(Constants.UI.TEXT_VERSION);
labelVer.setBounds(202, 46, 65, 25);
getContentPane().add(labelVer);
JTextField textVer = new JTextField();
textVer.setBounds(266, 46, 70, 25);
getContentPane().add(textVer);
textVer.setColumns(10);
textVer.setEditable(false);
JButton buttonRequestBK = new JButton(Constants.UI.TEXT_REQUEST_ONLINE);
buttonRequestBK.setBounds(12, 80, Constants.UI.BUTTON_WIDTH, Constants.UI.BUTTON_HEIGHT);
getContentPane().add(buttonRequestBK);
JButton buttonRestoreOnline = new JButton(Constants.UI.TEXT_RESTORE_ONLINE);
buttonRestoreOnline.setBounds(189, 80, Constants.UI.BUTTON_WIDTH, Constants.UI.BUTTON_HEIGHT);
buttonRestoreOnline.setEnabled(false);
getContentPane().add(buttonRestoreOnline);
JButton buttonBackupLocal = new JButton(Constants.UI.TEXT_BACKUP_LOCAL);
buttonBackupLocal.setBounds(12, 111, Constants.UI.BUTTON_WIDTH, Constants.UI.BUTTON_HEIGHT);
getContentPane().add(buttonBackupLocal);
JButton buttonRestoreLocal = new JButton(Constants.UI.TEXT_RESTORE_LOCAL);
buttonRestoreLocal.setBounds(189, 112, Constants.UI.BUTTON_WIDTH, Constants.UI.BUTTON_HEIGHT);
getContentPane().add(buttonRestoreLocal);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(12, 151, 330, 387);
getContentPane().add(scrollPane);
JTextArea textLog = new JTextArea();
textLog.setLineWrap(true);
textLog.setWrapStyleWord(true);
scrollPane.setViewportView(textLog);
}
瞧,这些代码在JDK 7/8下大约需要17秒才能渲染。这是使用每个JDK编译和运行应用程序的结果:
// JDK 8u20
Set LAF. Milliseconds from start app: 17250
Render app. Milliseconds from start app: 17367
// JDK 7u51
Set LAF. Milliseconds from start app: 17271
Render app. Milliseconds from start app: 17375
// JDK 6u45
Set LAF. Milliseconds from start app: 668
Render app. Milliseconds from start app: 931
首先,我认为Nimbus LAF有问题,所以我删除了设置LAF的代码,但没有任何改变:
// JDK 8u20
Set LAF. Milliseconds from start app: 0
Render app. Milliseconds from start app: 17295
//JDK 7u51
Set LAF. Milliseconds from start app: 0
Render app. Milliseconds from start app: 17263
// JDK 6u45
Set LAF. Milliseconds from start app: 0
Render app. Milliseconds from start app: 245
经过一些调试后,我发现应用程序的大部分开始时间(没有设置LAF)都在这一行:
frame.setVisible(true);
我尝试过其他Oracle JDK(7u60,7u65)和默认的Open JDK(7u51),但没有运气。挖掘谷歌没有带来任何结果。 17秒开始一个简单的挥杆应用真是难以忍受。请有人帮我解开这个谜!
编辑1:我在Lubuntu,Windows XP和Windows 7上进行了其他测试:
// Lubuntu - JDK 7u10
Set LAF. Milliseconds from start app: 265
Render app. Milliseconds from start app: 392
// Windows XP SP2 - JDK 7u67
Set LAF. Milliseconds from start app: 100
Render app. Milliseconds from start app: 280
//Windows XP SP2 - JDK 7u65
Set LAF. Milliseconds from start app: 562
Render app. Milliseconds from start app: 1061
因此问题可能在于与JDK 7/8兼容的OpenSUSE 13.1。
编辑2:作为AlexR的建议,使用Eclipse,我在Java代码中进一步调试,发现这个类的方法占用了大部分时间:
Container.validateTree()
但是没有记录,就不可能进一步挖掘,因为这是一种递归方法。