Skip to content

Commit 133526c

Browse files
committed
Partial Fix For Slow jFileChooser
Start of fixing #272 This is a Swing / JDK bug - Using a different JDK is the recommended fix, but this work around helps cut the time waited by a lot.
1 parent d78ab84 commit 133526c

File tree

12 files changed

+275
-204
lines changed

12 files changed

+275
-204
lines changed

src/main/java/the/bytecode/club/bytecodeviewer/BytecodeViewer.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@
5353
import java.io.IOException;
5454
import java.util.List;
5555
import java.util.*;
56+
import java.util.concurrent.ExecutorService;
57+
import java.util.concurrent.Executors;
5658

5759
import static javax.swing.JOptionPane.QUESTION_MESSAGE;
5860
import static the.bytecode.club.bytecodeviewer.Constants.*;
@@ -263,7 +265,8 @@ public static void boot(boolean cli)
263265
TASK_MANAGER.start();
264266

265267
//setup the viewer
266-
viewer.calledAfterLoad();
268+
if(!cli)
269+
viewer.calledAfterLoad();
267270

268271
//setup the recent files
269272
Settings.resetRecentFilesMenu();

src/main/java/the/bytecode/club/bytecodeviewer/GlobalHotKeys.java

+22-15
Original file line numberDiff line numberDiff line change
@@ -103,26 +103,33 @@ else if ((e.getKeyCode() == KeyEvent.VK_S) && ((e.getModifiersEx() & KeyEvent.CT
103103
if (!BytecodeViewer.autoCompileSuccessful())
104104
return;
105105

106-
JFileChooser fc = new FileChooser(Configuration.getLastSaveDirectory(), "Select Zip Export", "Zip Archives", "zip");
106+
try
107+
{
108+
JFileChooser fc = FileChooser.create(Configuration.getLastSaveDirectory(), "Select Zip Export", "Zip Archives", "zip");
107109

108-
int returnVal = fc.showSaveDialog(BytecodeViewer.viewer);
110+
int returnVal = fc.showSaveDialog(BytecodeViewer.viewer);
109111

110-
if (returnVal == JFileChooser.APPROVE_OPTION)
111-
{
112-
Configuration.setLastSaveDirectory(fc.getSelectedFile());
112+
if (returnVal == JFileChooser.APPROVE_OPTION)
113+
{
114+
Configuration.setLastSaveDirectory(fc.getSelectedFile());
113115

114-
File file = MiscUtils.autoAppendFileExtension(".zip", fc.getSelectedFile());
116+
File file = MiscUtils.autoAppendFileExtension(".zip", fc.getSelectedFile());
115117

116-
if (!DialogUtils.canOverwriteFile(file))
117-
return;
118+
if (!DialogUtils.canOverwriteFile(file))
119+
return;
118120

119-
BytecodeViewer.updateBusyStatus(true);
120-
Thread jarExport = new Thread(() ->
121-
{
122-
JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(), file.getAbsolutePath());
123-
BytecodeViewer.updateBusyStatus(false);
124-
}, "Jar Export");
125-
jarExport.start();
121+
BytecodeViewer.updateBusyStatus(true);
122+
Thread jarExport = new Thread(() ->
123+
{
124+
JarUtils.saveAsJar(BytecodeViewer.getLoadedClasses(), file.getAbsolutePath());
125+
BytecodeViewer.updateBusyStatus(false);
126+
}, "Jar Export");
127+
jarExport.start();
128+
}
129+
}
130+
catch (Exception ex)
131+
{
132+
ex.printStackTrace();
126133
}
127134
}, "Resource Export");
128135

src/main/java/the/bytecode/club/bytecodeviewer/bootloader/UpdateCheck.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import java.io.*;
3333
import java.net.URI;
3434
import java.net.URL;
35+
import java.util.concurrent.ExecutionException;
3536

3637
import static the.bytecode.club.bytecodeviewer.Constants.VERSION;
3738
import static the.bytecode.club.bytecodeviewer.Constants.NL;
@@ -145,9 +146,9 @@ else if (result == 2)
145146
}
146147
}
147148

148-
public static File promptFileSave(String description, String extension) throws IOException
149+
public static File promptFileSave(String description, String extension) throws IOException, ExecutionException, InterruptedException
149150
{
150-
JFileChooser fc = new FileChooser(new File("./").getCanonicalFile(), "Select Save File", description, extension);
151+
JFileChooser fc = FileChooser.create(new File("./").getCanonicalFile(), "Select Save File", description, extension);
151152

152153
int returnVal = fc.showSaveDialog(BytecodeViewer.viewer);
153154
File file = null;

src/main/java/the/bytecode/club/bytecodeviewer/gui/MainViewerGUI.java

+6
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@
6161
import java.util.HashMap;
6262
import java.util.List;
6363
import java.util.Map;
64+
import java.util.concurrent.ExecutorService;
65+
import java.util.concurrent.Executors;
6466

6567
import static the.bytecode.club.bytecodeviewer.Configuration.useNewSettingsDialog;
6668
import static the.bytecode.club.bytecodeviewer.Constants.VERSION;
@@ -835,6 +837,10 @@ public void defaultSettings()
835837
public void calledAfterLoad()
836838
{
837839
deleteForeignOutdatedLibs.setSelected(Configuration.deleteForeignLibraries);
840+
841+
//preload the jFileChooser to fix https://stackoverflow.com/a/59165208
842+
ExecutorService executor = Executors.newSingleThreadExecutor();
843+
executor.execute(FileChooser.SINGLETON);
838844
}
839845

840846
public int getFontSize()

src/main/java/the/bytecode/club/bytecodeviewer/gui/components/FileChooser.java

+20-10
Original file line numberDiff line numberDiff line change
@@ -26,40 +26,48 @@
2626
import java.util.Arrays;
2727
import java.util.HashSet;
2828
import java.util.Set;
29+
import java.util.concurrent.ExecutionException;
30+
import java.util.concurrent.FutureTask;
2931

3032
/**
3133
* @author Konloch
3234
* @since 6/25/2021
3335
*/
34-
public class FileChooser extends JFileChooser
36+
public class FileChooser
3537
{
38+
public static final FutureTask<JFileChooser> SINGLETON = new FutureTask<>(JFileChooser::new);
3639
public static final String EVERYTHING = "everything";
3740

38-
public FileChooser(File file, String title, String description, String... extensions)
41+
public static JFileChooser create(File file, String title, String description, String... extensions) throws ExecutionException, InterruptedException
3942
{
40-
this(false, file, title, description, extensions);
43+
return create(false, file, title, description, extensions);
4144
}
4245

43-
public FileChooser(boolean skipFileFilter, File file, String title, String description, String... extensions)
46+
public static JFileChooser create(boolean skipFileFilter, File file, String title, String description, String... extensions) throws ExecutionException, InterruptedException
4447
{
48+
JFileChooser chooser = SINGLETON.get();
49+
4550
Set<String> extensionSet = new HashSet<>(Arrays.asList(extensions));
4651

47-
setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
52+
chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
4853

4954
try
5055
{
51-
setSelectedFile(file);
56+
chooser.setSelectedFile(file);
5257
}
5358
catch (Exception ignored)
5459
{
5560
}
5661

57-
setDialogTitle(title);
58-
setFileHidingEnabled(false);
59-
setAcceptAllFileFilterUsed(false);
62+
chooser.setDialogTitle(title);
63+
chooser.setFileHidingEnabled(false);
64+
chooser.setAcceptAllFileFilterUsed(false);
65+
66+
chooser.resetChoosableFileFilters();
67+
6068
if (!skipFileFilter)
6169
{
62-
addChoosableFileFilter(new FileFilter()
70+
chooser.addChoosableFileFilter(new FileFilter()
6371
{
6472
@Override
6573
public boolean accept(File f)
@@ -80,5 +88,7 @@ public String getDescription()
8088
}
8189
});
8290
}
91+
92+
return chooser;
8393
}
8494
}

src/main/java/the/bytecode/club/bytecodeviewer/plugin/PluginWriter.java

+24-17
Original file line numberDiff line numberDiff line change
@@ -235,30 +235,37 @@ public void save()
235235

236236
if (savePath == null)
237237
{
238-
final String ext = FileNameUtils.getExtension(pluginName);
239-
JFileChooser fc = new FileChooser(Configuration.getLastPluginDirectory(), "Save Plugin", "BCV Plugin", ext);
240-
241-
int returnVal = fc.showSaveDialog(BytecodeViewer.viewer);
242-
if (returnVal == JFileChooser.APPROVE_OPTION)
238+
try
243239
{
244-
Configuration.setLastPluginDirectory(fc.getSelectedFile());
240+
final String ext = FileNameUtils.getExtension(pluginName);
241+
JFileChooser fc = FileChooser.create(Configuration.getLastPluginDirectory(), "Save Plugin", "BCV Plugin", ext);
245242

246-
File file = fc.getSelectedFile();
247-
String path = file.getAbsolutePath();
243+
int returnVal = fc.showSaveDialog(BytecodeViewer.viewer);
244+
if (returnVal == JFileChooser.APPROVE_OPTION)
245+
{
246+
Configuration.setLastPluginDirectory(fc.getSelectedFile());
248247

249-
//auto append extension
250-
if (!path.endsWith("." + ext))
251-
path += "." + ext;
248+
File file = fc.getSelectedFile();
249+
String path = file.getAbsolutePath();
252250

253-
if (!DialogUtils.canOverwriteFile(path))
254-
return;
251+
//auto append extension
252+
if (!path.endsWith("." + ext))
253+
path += "." + ext;
255254

256-
//swap from save-as to having a defined path each save
257-
setSourceFile(new File(path));
255+
if (!DialogUtils.canOverwriteFile(path))
256+
return;
257+
258+
//swap from save-as to having a defined path each save
259+
setSourceFile(new File(path));
260+
}
261+
else
262+
{
263+
return;
264+
}
258265
}
259-
else
266+
catch (Exception e)
260267
{
261-
return;
268+
e.printStackTrace();
262269
}
263270
}
264271

src/main/java/the/bytecode/club/bytecodeviewer/resources/ResourceDecompiling.java

+47-46
Original file line numberDiff line numberDiff line change
@@ -63,42 +63,42 @@ public static void decompileSaveAll()
6363

6464
MiscUtils.createNewThread("Decompile Save-All Thread", () ->
6565
{
66-
//signal to the user that BCV is performing an action in the background
67-
BytecodeViewer.updateBusyStatus(true);
66+
try
67+
{
68+
//signal to the user that BCV is performing an action in the background
69+
BytecodeViewer.updateBusyStatus(true);
6870

69-
//auto compile before decompilation
70-
if (!BytecodeViewer.autoCompileSuccessful())
71-
return;
71+
//auto compile before decompilation
72+
if (!BytecodeViewer.autoCompileSuccessful())
73+
return;
7274

73-
final JFileChooser fc = new FileChooser(Configuration.getLastSaveDirectory(),
74-
"Select Zip Export", "Zip Archives", "zip");
75+
final JFileChooser fc = FileChooser.create(Configuration.getLastSaveDirectory(),
76+
"Select Zip Export", "Zip Archives", "zip");
7577

76-
//if the user doesn't select a file then we should stop while we're ahead
77-
if (fc.showSaveDialog(BytecodeViewer.viewer) != JFileChooser.APPROVE_OPTION)
78-
return;
78+
//if the user doesn't select a file then we should stop while we're ahead
79+
if (fc.showSaveDialog(BytecodeViewer.viewer) != JFileChooser.APPROVE_OPTION)
80+
return;
7981

80-
//set the last touched save directory for BCV
81-
Configuration.setLastSaveDirectory(fc.getSelectedFile());
82+
//set the last touched save directory for BCV
83+
Configuration.setLastSaveDirectory(fc.getSelectedFile());
8284

83-
//get the save file and auto append zip extension
84-
final File outputZip = MiscUtils.autoAppendFileExtension(".zip", fc.getSelectedFile());
85+
//get the save file and auto append zip extension
86+
final File outputZip = MiscUtils.autoAppendFileExtension(".zip", fc.getSelectedFile());
8587

86-
//prompt the user for a dialogue override-this-file option if the file already exists
87-
if (!DialogUtils.canOverwriteFile(outputZip))
88-
return;
88+
//prompt the user for a dialogue override-this-file option if the file already exists
89+
if (!DialogUtils.canOverwriteFile(outputZip))
90+
return;
8991

90-
//this temporary jar file will be used to store the classes while BCV performs decompilation
91-
File temporaryTargetJar = MiscUtils.deleteExistingFile(new File(TEMP_DIRECTORY + FS
92-
+ "temp_" + MiscUtils.getRandomizedName() + ".jar"));
92+
//this temporary jar file will be used to store the classes while BCV performs decompilation
93+
File temporaryTargetJar = MiscUtils.deleteExistingFile(new File(TEMP_DIRECTORY + FS
94+
+ "temp_" + MiscUtils.getRandomizedName() + ".jar"));
9395

94-
//extract all the loaded classes imported into BCV to the temporary target jar
95-
JarUtils.saveAsJarClassesOnly(BytecodeViewer.getLoadedClasses(), temporaryTargetJar.getAbsolutePath());
96+
//extract all the loaded classes imported into BCV to the temporary target jar
97+
JarUtils.saveAsJarClassesOnly(BytecodeViewer.getLoadedClasses(), temporaryTargetJar.getAbsolutePath());
9698

97-
//signal to the user that BCV is finished performing that action
98-
BytecodeViewer.updateBusyStatus(false);
99+
//signal to the user that BCV is finished performing that action
100+
BytecodeViewer.updateBusyStatus(false);
99101

100-
try
101-
{
102102
//handle the result of the user selection
103103
switch (promptDecompilerUserSelect() + DECOMPILE_SAVE_ALL)
104104
{
@@ -159,34 +159,35 @@ public static void decompileSaveOpenedResource()
159159

160160
MiscUtils.createNewThread("Decompile Save Opened Resource", () ->
161161
{
162-
//signal to the user that BCV is performing an action in the background
163-
BytecodeViewer.updateBusyStatus(true);
162+
try
163+
{
164+
//signal to the user that BCV is performing an action in the background
165+
BytecodeViewer.updateBusyStatus(true);
164166

165-
//auto compile before decompilation
166-
if (!BytecodeViewer.autoCompileSuccessful())
167-
return;
167+
//auto compile before decompilation
168+
if (!BytecodeViewer.autoCompileSuccessful())
169+
return;
168170

169-
JFileChooser fc = new FileChooser(Configuration.getLastSaveDirectory(), "Select Java Files", "Java Source Files", "java");
171+
JFileChooser fc = FileChooser.create(Configuration.getLastSaveDirectory(),
172+
"Select Java Files", "Java Source Files", "java");
170173

171-
//if the user doesn't select a file then we should stop while we're ahead
172-
if (fc.showSaveDialog(BytecodeViewer.viewer) != JFileChooser.APPROVE_OPTION)
173-
return;
174+
//if the user doesn't select a file then we should stop while we're ahead
175+
if (fc.showSaveDialog(BytecodeViewer.viewer) != JFileChooser.APPROVE_OPTION)
176+
return;
174177

175-
//set the last touched save directory for BCV
176-
Configuration.setLastSaveDirectory(fc.getSelectedFile());
178+
//set the last touched save directory for BCV
179+
Configuration.setLastSaveDirectory(fc.getSelectedFile());
177180

178-
//get the save file and auto append java extension
179-
File file = MiscUtils.autoAppendFileExtension(".java", fc.getSelectedFile());
181+
//get the save file and auto append java extension
182+
File file = MiscUtils.autoAppendFileExtension(".java", fc.getSelectedFile());
180183

181-
//prompt the user for a dialogue override-this-file option if the file already exists
182-
if (!DialogUtils.canOverwriteFile(file))
183-
return;
184+
//prompt the user for a dialogue override-this-file option if the file already exists
185+
if (!DialogUtils.canOverwriteFile(file))
186+
return;
184187

185-
//signal to the user that BCV is finished performing that action
186-
BytecodeViewer.updateBusyStatus(false);
188+
//signal to the user that BCV is finished performing that action
189+
BytecodeViewer.updateBusyStatus(false);
187190

188-
try
189-
{
190191
//handle the result of the user selection
191192
switch (promptDecompilerUserSelect() + DECOMPILE_OPENED_ONLY_ALL)
192193
{

0 commit comments

Comments
 (0)