Skip to content

Commit 2c7bb17

Browse files
committed
Micro optimizations for startup
- load deobfuscator jar in extra thread - load javafx for file chooser in extra thread - do not look for transformers in package-info, Config or inner classes - create method for fatal exception (like missing jfx) display
1 parent 5ce3766 commit 2c7bb17

File tree

6 files changed

+126
-47
lines changed

6 files changed

+126
-47
lines changed

src/java/com/javadeobfuscator/deobfuscator/ui/SwingWindow.java

Lines changed: 74 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import com.javadeobfuscator.deobfuscator.ui.component.SynchronousJFXCaller;
4343
import com.javadeobfuscator.deobfuscator.ui.component.SynchronousJFXFileChooser;
4444
import com.javadeobfuscator.deobfuscator.ui.component.WrapLayout;
45+
import com.javadeobfuscator.deobfuscator.ui.util.ExceptionUtil;
4546
import com.javadeobfuscator.deobfuscator.ui.util.FallbackException;
4647
import com.javadeobfuscator.deobfuscator.ui.util.InvalidJarException;
4748
import com.javadeobfuscator.deobfuscator.ui.util.TransformerConfigUtil;
@@ -64,41 +65,47 @@ public class SwingWindow
6465
private static final Map<Class<?>, String> TRANSFORMER_TO_NAME = new HashMap<>();
6566
private static final Map<String, Class<?>> NAME_TO_TRANSFORMER = new HashMap<>();
6667
private static DefaultListModel<TransformerWithConfig> transformerSelected;
68+
private static boolean swingLafLoaded = false;
69+
public static Thread mainThread;
70+
private static List<ConfigItem> configFieldsList;
6771

6872
public static void main(String[] args)
6973
{
70-
try
71-
{
72-
SynchronousJFXCaller.init();
73-
} catch (NoClassDefFoundError e)
74+
mainThread = Thread.currentThread();
75+
Thread loaderThread = new Thread("Deobfuscator Jar Loader Thread")
7476
{
75-
e.printStackTrace();
76-
try
77+
@Override
78+
public void run()
7779
{
78-
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
79-
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e2)
80+
loadWrappers();
81+
}
82+
};
83+
loaderThread.start();
84+
Thread jfxInitThread = new Thread("JavaFX Init Thread")
85+
{
86+
@Override
87+
public void run()
8088
{
81-
e2.printStackTrace();
89+
try
90+
{
91+
SynchronousJFXCaller.init();
92+
} catch (NoClassDefFoundError e)
93+
{
94+
e.printStackTrace();
95+
ensureSwingLafLoaded();
96+
ExceptionUtil.showFatalError("You need a JVM with JavaFX (an non-headless installation).\n\n" +
97+
"Could not find class " + e.getMessage());
98+
System.exit(1);
99+
}
82100
}
83-
JOptionPane.showMessageDialog(null, "You need a JVM with JavaFX (an non-headless installation).\n\n" +
84-
"Could not find class " + e.getMessage(), "Deobfuscator GUI", JOptionPane.ERROR_MESSAGE);
85-
System.exit(1);
86-
return;
87-
}
101+
};
88102
GuiConfig.read();
89-
try
90-
{
91-
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
92-
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e)
93-
{
94-
e.printStackTrace();
95-
}
103+
ensureSwingLafLoaded();
96104
if (GuiConfig.isDarkLaf())
97105
{
98106
installDarkLaf();
99107
}
100-
loadWrappers();
101-
List<ConfigItem> fields = new SwingConfiguration(config.get()).fieldsList;
108+
102109
//Initial frame
103110
JFrame frame = new JFrame();
104111
frame.setTitle("Deobfuscator GUI");
@@ -134,7 +141,7 @@ public void actionPerformed(ActionEvent e)
134141
return;
135142
}
136143
GuiConfig.setDarkLaf(false);
137-
writeAndSaveGuiConfig(fields);
144+
writeAndSaveGuiConfig(configFieldsList);
138145
System.exit(0);
139146
}
140147
}
@@ -183,7 +190,18 @@ public void actionPerformed(ActionEvent e)
183190
inputPnl.setLayout(new GridBagLayout());
184191

185192
int gridy = 0;
186-
for (ConfigItem i : fields)
193+
194+
try
195+
{
196+
loaderThread.join();
197+
} catch (InterruptedException e)
198+
{
199+
ExceptionUtil.showFatalError("", new RuntimeException("Couldn't wait for jar loader thread!", e));
200+
System.exit(1);
201+
}
202+
configFieldsList = new SwingConfiguration(config.get()).fieldsList;
203+
204+
for (ConfigItem i : configFieldsList)
187205
{
188206
if (i.type != SwingConfiguration.ItemType.FILE)
189207
continue;
@@ -245,7 +263,7 @@ public void actionPerformed(ActionEvent e)
245263
}
246264
if (!setDir && i.getDisplayName().equals("Output"))
247265
{
248-
Optional<ConfigItem> input = fields.stream().filter(ci -> ci.getDisplayName().equals("Input")).findAny();
266+
Optional<ConfigItem> input = configFieldsList.stream().filter(ci -> ci.getDisplayName().equals("Input")).findAny();
249267
if (input.isPresent())
250268
{
251269
Object value2 = input.get().getValue();
@@ -300,7 +318,7 @@ public void actionPerformed(ActionEvent e)
300318
inputPnl.add(boolWrapPanel, gbc);
301319
}
302320

303-
for (ConfigItem i : fields)
321+
for (ConfigItem i : configFieldsList)
304322
{
305323
if (i.type != ItemType.BOOLEAN)
306324
continue;
@@ -530,7 +548,7 @@ public void actionPerformed(ActionEvent e)
530548

531549
tabbedPane.addTab("Transformers", transformersPanel);
532550

533-
for (ConfigItem i : fields)
551+
for (ConfigItem i : configFieldsList)
534552
{
535553
if (i.type != ItemType.FILELIST)
536554
continue;
@@ -668,7 +686,7 @@ public void keyPressed(KeyEvent event)
668686
tabbedPane.addTab(i.getDisplayName(), libPanel);
669687
}
670688

671-
for (ConfigItem i : fields)
689+
for (ConfigItem i : configFieldsList)
672690
{
673691
if (i.type != ItemType.STRINGLIST)
674692
continue;
@@ -879,7 +897,7 @@ public void keyPressed(KeyEvent event)
879897
submitButton.addActionListener(e13 ->
880898
{
881899
String args1 = textPane.getText();
882-
readAndApplyConfig(fields, transformerSelected, args1);
900+
readAndApplyConfig(configFieldsList, transformerSelected, args1);
883901
loadConfigFrame.dispose();
884902
});
885903
loadConfigFrame.setVisible(true);
@@ -928,7 +946,7 @@ public void keyPressed(KeyEvent event)
928946
saveConfigFrame.getContentPane().add(scrollPane, gbc_scrollPane);
929947

930948
//Write args
931-
String t = createConfig(fields, transformerSelected);
949+
String t = createConfig(configFieldsList, transformerSelected);
932950
textPane.setText(t);
933951

934952
JButton copyButton = new JButton("Copy");
@@ -973,7 +991,7 @@ public void keyPressed(KeyEvent event)
973991
try
974992
{
975993
//Set fields
976-
for (ConfigItem item : fields)
994+
for (ConfigItem item : configFieldsList)
977995
{
978996
item.clearFieldValue();
979997
item.setFieldValue();
@@ -1090,20 +1108,42 @@ public void windowClosing(WindowEvent e)
10901108

10911109
if (GuiConfig.getStoreConfigOnClose())
10921110
{
1093-
readAndApplyConfig(fields, transformerSelected, GuiConfig.getConfig());
1111+
readAndApplyConfig(configFieldsList, transformerSelected, GuiConfig.getConfig());
10941112
}
10951113
frame.addWindowListener(new WindowAdapter()
10961114
{
10971115
@Override
10981116
public void windowClosing(WindowEvent e)
10991117
{
1100-
writeAndSaveGuiConfig(fields);
1118+
writeAndSaveGuiConfig(configFieldsList);
11011119
}
11021120
});
11031121

1122+
try
1123+
{
1124+
jfxInitThread.join();
1125+
} catch (InterruptedException e)
1126+
{
1127+
ExceptionUtil.showFatalError("", new RuntimeException("Couldn't wait for jfx init thread", e));
1128+
}
11041129
frame.setVisible(true);
11051130
}
11061131

1132+
public static synchronized void ensureSwingLafLoaded()
1133+
{
1134+
if (!swingLafLoaded)
1135+
{
1136+
swingLafLoaded = true;
1137+
try
1138+
{
1139+
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
1140+
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e)
1141+
{
1142+
e.printStackTrace();
1143+
}
1144+
}
1145+
}
1146+
11071147
private static void installDarkLaf()
11081148
{
11091149
ThemeSettings.getInstance().setConfiguration(GuiConfig.getDarklafSettings());

src/java/com/javadeobfuscator/deobfuscator/ui/util/ByteLoader.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import java.util.Map;
44
import java.util.Set;
55

6+
import com.javadeobfuscator.deobfuscator.ui.SwingWindow;
7+
68
/**
79
* ClassLoader that can find classes via their bytecode. Allows loading of external jar files to be instrumented before loading.
810
*/
@@ -21,7 +23,7 @@ public final class ByteLoader extends ClassLoader
2123
public ByteLoader(Map<String, byte[]> classes)
2224
{
2325
super(getSystemClassLoader());
24-
Thread.currentThread().setContextClassLoader(this);
26+
SwingWindow.mainThread.setContextClassLoader(this);
2527
this.classes = classes;
2628
}
2729

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.javadeobfuscator.deobfuscator.ui.util;
2+
3+
import java.io.PrintWriter;
4+
import java.io.StringWriter;
5+
6+
import javax.swing.JOptionPane;
7+
8+
import com.javadeobfuscator.deobfuscator.ui.SwingWindow;
9+
10+
public class ExceptionUtil
11+
{
12+
public static void showFatalError(String message) {
13+
showFatalError(message, null);
14+
}
15+
16+
public static void showFatalError(String message, Throwable t)
17+
{
18+
try
19+
{
20+
if (t != null)
21+
{
22+
t.printStackTrace();
23+
message = message + "\n" + getStackTrace(t);
24+
}
25+
SwingWindow.ensureSwingLafLoaded();
26+
JOptionPane.showMessageDialog(null, message, "Deobfuscator GUI - Error", JOptionPane.ERROR_MESSAGE);
27+
} catch (Throwable t2)
28+
{
29+
t2.printStackTrace();
30+
}
31+
System.exit(1);
32+
throw new Error("exit", t);
33+
}
34+
35+
public static String getStackTrace(Throwable t)
36+
{
37+
StringWriter sw = new StringWriter();
38+
t.printStackTrace(new PrintWriter(sw));
39+
return sw.toString();
40+
}
41+
}

src/java/com/javadeobfuscator/deobfuscator/ui/util/FallbackException.java

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
import java.awt.GridBagConstraints;
44
import java.awt.GridBagLayout;
55
import java.awt.Insets;
6-
import java.io.PrintWriter;
7-
import java.io.StringWriter;
86

97
import javax.swing.JButton;
108
import javax.swing.JFileChooser;
@@ -14,6 +12,8 @@
1412
import javax.swing.JTextArea;
1513
import javax.swing.JTextField;
1614

15+
import com.javadeobfuscator.deobfuscator.ui.SwingWindow;
16+
1717
public class FallbackException extends Exception
1818
{
1919
public String path;
@@ -22,6 +22,7 @@ public FallbackException(String title, String msg, Throwable cause)
2222
{
2323
super(msg, cause);
2424
this.printStackTrace();
25+
SwingWindow.ensureSwingLafLoaded();
2526
JPanel fallback = new JPanel();
2627
fallback.setLayout(new GridBagLayout());
2728
GridBagConstraints gbc = new GridBagConstraints();
@@ -32,7 +33,7 @@ public FallbackException(String title, String msg, Throwable cause)
3233
fallback.add(new JLabel(msg), gbc);
3334
if (cause != null) {
3435
gbc.gridy++;
35-
JTextArea area = new JTextArea(getStackTrace(cause));
36+
JTextArea area = new JTextArea(ExceptionUtil.getStackTrace(cause));
3637
area.setEditable(false);
3738
fallback.add(area, gbc);
3839
}
@@ -64,10 +65,4 @@ public FallbackException(String title, String msg, Throwable cause)
6465
System.exit(0);
6566
path = textField.getText();
6667
}
67-
68-
private static String getStackTrace(Throwable t) {
69-
StringWriter sw = new StringWriter();
70-
t.printStackTrace(new PrintWriter(sw));
71-
return sw.toString();
72-
}
7368
}

src/java/com/javadeobfuscator/deobfuscator/ui/wrap/Transformers.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ public List<Class<?>> getTransformers() throws FallbackException
4343
List<String> filtered = new ArrayList<>();
4444
for (String name : loader.getClassNames())
4545
{
46-
if (name.startsWith("com.javadeobfuscator.deobfuscator.transformers."))
46+
if (name.startsWith("com.javadeobfuscator.deobfuscator.transformers.") && !name.endsWith("package-info") && !name.endsWith("Config")
47+
&& !name.contains("$"))
4748
{
4849
filtered.add(name);
4950
}

src/java/com/javadeobfuscator/deobfuscator/ui/wrap/WrapperFactory.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public class WrapperFactory
1919
/**
2020
* Buffer size to use for reading classes from deobfuscator jar.
2121
*/
22-
private final static int BUFF_SIZE = (int) Math.pow(128, 2);
22+
private final static int BUFF_SIZE = (int) Math.pow(2, 13);
2323
/**
2424
* Loader to use.
2525
*/
@@ -195,7 +195,7 @@ private static Map<String, byte[]> readClasses(File jar) throws IOException, Inv
195195
}
196196
// We know this class is in the deobfuscator jar, so if the jar does
197197
// not contain it, it is not the correct file.
198-
if (className.contains("com/javadeobfuscator/deobfuscator/Deobfuscator"))
198+
if (!found && className.startsWith("com/javadeobfuscator/deobfuscator/Deobfuscator"))
199199
{
200200
found = true;
201201
}

0 commit comments

Comments
 (0)