diff --git a/trunk/src/com/jpexs/decompiler/flash/SWF.java b/trunk/src/com/jpexs/decompiler/flash/SWF.java index 0cc431ab4..645a660c0 100644 --- a/trunk/src/com/jpexs/decompiler/flash/SWF.java +++ b/trunk/src/com/jpexs/decompiler/flash/SWF.java @@ -127,6 +127,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; import java.util.logging.Logger; @@ -650,37 +651,61 @@ public class SWF { return ret; } - public List exportActionScript3(AbortRetryIgnoreHandler handler, String outdir, ExportMode exportMode, boolean parallel) { - ExecutorService executor = Executors.newFixedThreadPool(parallel ? 20 : 1); - List> futureResults = new ArrayList<>(); - AtomicInteger cnt = new AtomicInteger(1); - List abcTags = new ArrayList<>(); + public List exportActionScript3(final AbortRetryIgnoreHandler handler, final String outdir, final ExportMode exportMode, final boolean parallel) { + final AtomicInteger cnt = new AtomicInteger(1); + final List abcTags = new ArrayList<>(); for (Tag t : tags) { if (t instanceof ABCContainerTag) { abcTags.add((ABCContainerTag) t); } } - List> packs = getAS3Packs(); - for (MyEntry item : packs) { - Future future = executor.submit(new ExportPackTask(handler, cnt, packs.size(), item.key, item.value, outdir, abcTags, exportMode, parallel)); - futureResults.add(future); - } - List ret = new ArrayList<>(); - for (int f = 0; f < futureResults.size(); f++) { + final List ret = new ArrayList<>(); + final List> packs = getAS3Packs(); + + if (!parallel || packs.size() < 2) { try { - ret.add(futureResults.get(f).get()); - } catch (InterruptedException | ExecutionException ex) { - Logger.getLogger(SWF.class.getName()).log(Level.SEVERE, "Error during ABC export", ex); + Helper.timedCall(new Callable() { + @Override + public Void call() throws Exception { + for (MyEntry item : packs) { + ExportPackTask task = new ExportPackTask(handler, cnt, packs.size(), item.key, item.value, outdir, abcTags, exportMode, parallel); + try { + ret.add(task.call()); + } catch (Exception ex) { + Logger.getLogger(SWF.class.getName()).log(Level.SEVERE, "Error during ABC export", ex); + } + } + return null; + } + }, Configuration.DECOMPILATION_TIMEOUT, TimeUnit.SECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException ex) { + Logger.getLogger(ABC.class.getName()).log(Level.SEVERE, Helper.formatTimeToText(Configuration.DECOMPILATION_TIMEOUT) + " ActionScript export limit reached", ex); + } + } else { + ExecutorService executor = Executors.newFixedThreadPool(20); + List> futureResults = new ArrayList<>(); + for (MyEntry item : packs) { + Future future = executor.submit(new ExportPackTask(handler, cnt, packs.size(), item.key, item.value, outdir, abcTags, exportMode, parallel)); + futureResults.add(future); + } + + for (int f = 0; f < futureResults.size(); f++) { + try { + ret.add(futureResults.get(f).get()); + } catch (InterruptedException | ExecutionException ex) { + Logger.getLogger(SWF.class.getName()).log(Level.SEVERE, "Error during ABC export", ex); + } + } + + try { + executor.shutdown(); + executor.awaitTermination(Configuration.DECOMPILATION_TIMEOUT, TimeUnit.SECONDS); + } catch (InterruptedException ex) { + Logger.getLogger(ABC.class.getName()).log(Level.SEVERE, Helper.formatTimeToText(Configuration.DECOMPILATION_TIMEOUT) + " ActionScript export limit reached", ex); } } - - try { - executor.shutdown(); - executor.awaitTermination(Configuration.DECOMPILATION_TIMEOUT, TimeUnit.SECONDS); - } catch (InterruptedException ex) { - Logger.getLogger(ABC.class.getName()).log(Level.SEVERE, Helper.formatTimeToText(Configuration.DECOMPILATION_TIMEOUT) + " ActionScript export limit reached", ex); - } + return ret; } diff --git a/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java b/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java index c4f28f6c6..2248b350b 100644 --- a/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java +++ b/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java @@ -64,6 +64,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Stack; import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; @@ -606,7 +607,7 @@ public class SWFInputStream extends InputStream { /** * Reads list of tags from the stream. Reading ends with End tag(=0) or end - * of the stream. Optinally can skip AS1/2 tags when file is AS3 + * of the stream. Optionally can skip AS1/2 tags when file is AS3 * * @param swf * @param level @@ -633,10 +634,11 @@ public class SWFInputStream extends InputStream { */ public List readTagList(SWF swf, int level, boolean parallel, boolean skipUnusualTags, boolean parseTags) throws IOException { ExecutorService executor = null; + List> futureResults = new ArrayList<>(); if (parallel) { executor = Executors.newFixedThreadPool(20); + futureResults = new ArrayList<>(); } - List> futureResults = new ArrayList<>(); List tags = new ArrayList<>(); Tag tag; Tag previousTag = null; @@ -659,7 +661,7 @@ public class SWFInputStream extends InputStream { } tag.previousTag = previousTag; previousTag = tag; - boolean doParse = false; + boolean doParse; if (!skipUnusualTags) { doParse = true; } else { @@ -718,7 +720,7 @@ public class SWFInputStream extends InputStream { for (Future future : futureResults) { try { tags.add(future.get()); - } catch (Exception e) { + } catch (InterruptedException | ExecutionException e) { Logger.getLogger(SWFInputStream.class.getName()).log(Level.SEVERE, "Error during tag reading", e); } } @@ -1005,21 +1007,6 @@ public class SWFInputStream extends InputStream { return ret; } - /** - * Reads one Tag from the stream - * - * @param swf - * @param level - * @param pos - * @param parallel - * @param skipUnusualTags - * @return Tag or null when End tag - * @throws IOException - */ - public Tag readTag(SWF swf, int level, long pos, boolean parallel, boolean skipUnusualTags) throws IOException { - return readTag(swf, level, pos, true, parallel, skipUnusualTags); - } - /** * Reads one Tag from the stream with optional resolving (= reading tag * content) diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java index 858fa6145..c0d1fbe89 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java @@ -135,40 +135,38 @@ public class Traits implements Serializable { } public HilightedTextWriter convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, boolean makePackages, int scriptIndex, int classIndex, HilightedTextWriter writer, List fullyQualifiedNames, boolean parallel) { - ExecutorService executor = null; - List> futureResults = null; - List traitConvertTasks = null; - - if (parallel) { - executor = Executors.newFixedThreadPool(20); - futureResults = new ArrayList<>(); - } else { - traitConvertTasks = new ArrayList<>(); - } - for (int t = 0; t < traits.length; t++) { - HilightedTextWriter writer2 = new HilightedTextWriter(writer.getIsHighlighted(), writer.getIndent()); - TraitConvertTask task = new TraitConvertTask(traits[t], parent, makePackages, path, abcTags, abc, isStatic, exportMode, scriptIndex, classIndex, writer2, fullyQualifiedNames, t, parallel); - if (parallel) { - Future future = executor.submit(task); - futureResults.add(future); - } else { - traitConvertTasks.add(task); - } - } - - int taskCount = parallel ? futureResults.size() : traitConvertTasks.size(); - for (int f = 0; f < taskCount; f++) { - if (f > 0) { + if (!parallel || traits.length < 2) { + for (int t = 0; t < traits.length; t++) { + if (t > 0) { + writer.newLine(); + } + TraitConvertTask task = new TraitConvertTask(traits[t], parent, makePackages, path, abcTags, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, t, parallel); + task.call(); writer.newLine(); } - try { - String taskResult = parallel ? futureResults.get(f).get() : traitConvertTasks.get(f).call(); - writer.appendWithoutIndent(taskResult); - } catch (InterruptedException | ExecutionException ex) { - Logger.getLogger(Traits.class.getName()).log(Level.SEVERE, "Error during traits converting", ex); + } else { + ExecutorService executor = Executors.newFixedThreadPool(20); + List> futureResults = null; + + futureResults = new ArrayList<>(); + for (int t = 0; t < traits.length; t++) { + HilightedTextWriter writer2 = new HilightedTextWriter(writer.getIsHighlighted(), writer.getIndent()); + TraitConvertTask task = new TraitConvertTask(traits[t], parent, makePackages, path, abcTags, abc, isStatic, exportMode, scriptIndex, classIndex, writer2, fullyQualifiedNames, t, parallel); + Future future = executor.submit(task); + futureResults.add(future); + } + + for (int f = 0; f < futureResults.size(); f++) { + if (f > 0) { + writer.newLine(); + } + try { + String taskResult = futureResults.get(f).get(); + writer.appendWithoutIndent(taskResult); + } catch (InterruptedException | ExecutionException ex) { + Logger.getLogger(Traits.class.getName()).log(Level.SEVERE, "Error during traits converting", ex); + } } - } - if (parallel) { executor.shutdown(); } return writer; diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/Main.java b/trunk/src/com/jpexs/decompiler/flash/gui/Main.java index 967478882..131cbad25 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/Main.java @@ -281,12 +281,16 @@ public class Main { if (Main.inputStream instanceof FileInputStream) { Main.inputStream.close(); } + } catch (OutOfMemoryError ex) { + Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); + View.showMessageDialog(null, "Cannot load SWF file. Out of memory."); + loadingDialog.setVisible(false); + swf = null; } catch (Exception ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); View.showMessageDialog(null, "Cannot load SWF file."); loadingDialog.setVisible(false); swf = null; - //return false; } try { @@ -966,6 +970,65 @@ public class Main { } pos++; + } else if (args[pos].equals("-affinity")) { + parameterProcessed = true; + pos++; + if (Platform.isWindows()) { + if (args.length <= pos) { + System.err.println("affinity parameter expected"); + badArguments(); + } + try { + int affinityMask = Integer.parseInt(args[pos]); + Kernel32.INSTANCE.SetProcessAffinityMask(Kernel32.INSTANCE.GetCurrentProcess(), affinityMask); + } catch (NumberFormatException nex) { + System.err.println("Bad affinityMask value"); + } + + pos++; + } else { + System.err.println("Process affinity setting is only available on Windows platform."); + } + } else if (args[pos].equals("-priority")) { + parameterProcessed = true; + pos++; + if (Platform.isWindows()) { + if (args.length <= pos) { + System.err.println("priority parameter expected"); + badArguments(); + } + String priority = args[pos]; + int priorityClass = 0; + switch (priority) { + case "low": + priorityClass = Kernel32.IDLE_PRIORITY_CLASS; + break; + case "belownormal": + priorityClass = Kernel32.BELOW_NORMAL_PRIORITY_CLASS; + break; + case "normal": + priorityClass = Kernel32.NORMAL_PRIORITY_CLASS; + break; + case "abovenormal": + priorityClass = Kernel32.ABOVE_NORMAL_PRIORITY_CLASS; + break; + case "high": + priorityClass = Kernel32.HIGH_PRIORITY_CLASS; + break; + case "realtime": + priorityClass = Kernel32.REALTIME_PRIORITY_CLASS; + break; + default: + System.err.println("Bad affinityMask value"); + } + if (priorityClass != 0) { + Kernel32.INSTANCE.SetPriorityClass(Kernel32.INSTANCE.GetCurrentProcess(), priorityClass); + } + + pos++; + } else { + System.err.println("Process priority setting is only available on Windows platform."); + } } } if (args[pos].equals("-removefromcontextmenu")) { @@ -1119,7 +1182,7 @@ public class Main { default: exportOK = false; } - } catch (Exception ex) { + } catch (OutOfMemoryError | Exception ex) { exportOK = false; System.err.print("FAIL: Exporting Failed on Exception - "); Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); diff --git a/trunk/src/com/sun/jna/platform/win32/Kernel32.java b/trunk/src/com/sun/jna/platform/win32/Kernel32.java index cbcbbcd68..ee4337229 100644 --- a/trunk/src/com/sun/jna/platform/win32/Kernel32.java +++ b/trunk/src/com/sun/jna/platform/win32/Kernel32.java @@ -109,7 +109,18 @@ public interface Kernel32 extends WinNT { // Define the well known values for CreateNamedPipe nMaxInstances // public static final int PIPE_UNLIMITED_INSTANCES = 255; - + // + // Define the values for process priority + // + public static final int ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000; + public static final int BELOW_NORMAL_PRIORITY_CLASS = 0x00004000; + public static final int HIGH_PRIORITY_CLASS = 0x00000080; + public static final int IDLE_PRIORITY_CLASS = 0x00000040; + public static final int NORMAL_PRIORITY_CLASS = 0x00000020; + public static final int PROCESS_MODE_BACKGROUND_BEGIN = 0x00100000; + public static final int PROCESS_MODE_BACKGROUND_END = 0x00200000; + public static final int REALTIME_PRIORITY_CLASS = 0x00000100; + // __out // HANDLE // WINAPI @@ -172,6 +183,10 @@ public interface Kernel32 extends WinNT { */ HANDLE GetCurrentProcess(); + int SetProcessAffinityMask(HANDLE hProcess, int mask); + + int SetPriorityClass(HANDLE hProcess, int dwPriorityClass); + /** * This function returns a handle to an existing process object. *