diff --git a/src/main/java/me/konloch/kontainer/io/DiskWriter.java b/src/main/java/me/konloch/kontainer/io/DiskWriter.java
index e3180ff0..eda3442b 100644
--- a/src/main/java/me/konloch/kontainer/io/DiskWriter.java
+++ b/src/main/java/me/konloch/kontainer/io/DiskWriter.java
@@ -1,9 +1,6 @@
package me.konloch.kontainer.io;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.PrintWriter;
+import java.io.*;
import java.util.Arrays;
/**
@@ -132,13 +129,13 @@ public class DiskWriter {
* @param fileContents
* @param debug
*/
- public static synchronized void replaceFile(String filename,
- byte[] fileContents, boolean debug) {
+ public static synchronized void replaceFileBytes(String filename,
+ byte[] fileContents, boolean debug) {
new File(filename).getParentFile().mkdirs();
File f = new File(filename);
if (f.exists())
f.delete();
- PrintWriter writer = null;
+
String original = filename;
int counter = 0;
@@ -146,10 +143,10 @@ public class DiskWriter {
int failSafe = 0;
while (!saved && failSafe++ <= 42069)
{
- try {
- writer = new PrintWriter(new BufferedWriter(new FileWriter(
- filename, true)));
- writer.println(Arrays.toString(fileContents));
+ try(FileOutputStream stream = new FileOutputStream(new File(filename)))
+ {
+ stream.write(fileContents);
+ stream.flush();
if (debug)
System.out.println("Saved " + filename + " to disk");
saved = true;
@@ -164,7 +161,6 @@ public class DiskWriter {
counter++;
}
}
- writer.close();
}
/**
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/Configuration.java b/src/main/java/the/bytecode/club/bytecodeviewer/Configuration.java
index 84641403..586d5949 100644
--- a/src/main/java/the/bytecode/club/bytecodeviewer/Configuration.java
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/Configuration.java
@@ -15,11 +15,14 @@ import java.io.File;
public class Configuration
{
public static String python2 = "";
+ public static String python2Extra = "";
public static String python3 = "";
+ public static String python3Extra = "";
public static String rt = "";
public static String library = "";
public static String javac = "";
public static String java = "";
+ public static String javaTools = "";
public static File krakatauTempDir;
public static File krakatauTempJar;
public static boolean displayParentInTab = false; //also change in the main GUI
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/SettingsSerializer.java b/src/main/java/the/bytecode/club/bytecodeviewer/SettingsSerializer.java
index 05287657..8147c65b 100644
--- a/src/main/java/the/bytecode/club/bytecodeviewer/SettingsSerializer.java
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/SettingsSerializer.java
@@ -191,6 +191,8 @@ public class SettingsSerializer
save(BytecodeViewer.viewer.viewPane1.isPaneEditable());
save(BytecodeViewer.viewer.viewPane2.isPaneEditable());
save(BytecodeViewer.viewer.viewPane3.isPaneEditable());
+
+ save(Configuration.javaTools);
} catch (Exception e) {
BytecodeViewer.handleException(e);
}
@@ -348,6 +350,8 @@ public class SettingsSerializer
BytecodeViewer.viewer.viewPane1.setPaneEditable(asBoolean(131));
BytecodeViewer.viewer.viewPane2.setPaneEditable(asBoolean(132));
BytecodeViewer.viewer.viewPane3.setPaneEditable(asBoolean(133));
+
+ Configuration.javaTools = asString(134);
} catch (Exception e) {
//ignore because errors are expected, first start up and outdated settings.
e.printStackTrace();
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/compilers/impl/KrakatauAssembler.java b/src/main/java/the/bytecode/club/bytecodeviewer/compilers/impl/KrakatauAssembler.java
index 84f4bba1..8b6fc3d5 100644
--- a/src/main/java/the/bytecode/club/bytecodeviewer/compilers/impl/KrakatauAssembler.java
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/compilers/impl/KrakatauAssembler.java
@@ -46,15 +46,8 @@ public class KrakatauAssembler extends InternalCompiler
@Override
public byte[] compile(String contents, String name) {
- if (Configuration.python2.isEmpty()) {
- BytecodeViewer.showMessage("You need to set your Python (or PyPy for speed) 2.7 executable path.");
- ExternalResources.getSingleton().selectPython2();
- }
-
- if (Configuration.python2.isEmpty()) {
- BytecodeViewer.showMessage("You need to set Python!");
+ if(!ExternalResources.getSingleton().hasSetPythonCommand())
return null;
- }
String origName = MiscUtils.randomString(20);
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/decompilers/impl/ASMTextifierDecompiler.java b/src/main/java/the/bytecode/club/bytecodeviewer/decompilers/impl/ASMTextifierDisassembler.java
similarity index 96%
rename from src/main/java/the/bytecode/club/bytecodeviewer/decompilers/impl/ASMTextifierDecompiler.java
rename to src/main/java/the/bytecode/club/bytecodeviewer/decompilers/impl/ASMTextifierDisassembler.java
index b8c5a400..e6ddf033 100644
--- a/src/main/java/the/bytecode/club/bytecodeviewer/decompilers/impl/ASMTextifierDecompiler.java
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/decompilers/impl/ASMTextifierDisassembler.java
@@ -30,7 +30,7 @@ import the.bytecode.club.bytecodeviewer.decompilers.InternalDecompiler;
*
* @author Thiakil
*/
-public class ASMTextifierDecompiler extends InternalDecompiler
+public class ASMTextifierDisassembler extends InternalDecompiler
{
@Override
public String decompileClassNode(ClassNode cn, byte[] b) {
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/decompilers/impl/JavapDisassembler.java b/src/main/java/the/bytecode/club/bytecodeviewer/decompilers/impl/JavapDisassembler.java
new file mode 100644
index 00000000..b8721088
--- /dev/null
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/decompilers/impl/JavapDisassembler.java
@@ -0,0 +1,106 @@
+package the.bytecode.club.bytecodeviewer.decompilers.impl;
+
+import me.konloch.kontainer.io.DiskReader;
+import me.konloch.kontainer.io.DiskWriter;
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.util.Textifier;
+import org.objectweb.asm.util.TraceClassVisitor;
+import the.bytecode.club.bytecodeviewer.Configuration;
+import the.bytecode.club.bytecodeviewer.Constants;
+import the.bytecode.club.bytecodeviewer.decompilers.InternalDecompiler;
+import the.bytecode.club.bytecodeviewer.gui.components.SystemConsole;
+import the.bytecode.club.bytecodeviewer.resources.ExternalResources;
+import the.bytecode.club.bytecodeviewer.util.MiscUtils;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+import static the.bytecode.club.bytecodeviewer.Constants.fs;
+import static the.bytecode.club.bytecodeviewer.api.ExceptionUI.KONLOCH;
+
+/***************************************************************************
+ * Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
+ * Copyright (C) 2014 Kalen 'Konloch' Kinloch - http://bytecodeviewer.com *
+ * *
+ * This program is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program. If not, see . *
+ ***************************************************************************/
+
+/**
+ * Javap disassembler
+ *
+ * https://github.com/Konloch/bytecode-viewer/issues/93
+ *
+ * @author Konloch
+ * @since 07/11/2021
+ */
+
+public class JavapDisassembler extends InternalDecompiler
+{
+ @Override
+ public String decompileClassNode(ClassNode cn, byte[] b)
+ {
+ if(!ExternalResources.getSingleton().hasJavaToolsSet())
+ return "Set Java Tools Path!";
+
+ final File tempDirectory = new File(Constants.tempDirectory + fs + MiscUtils.randomString(32) + fs);
+ tempDirectory.mkdir();
+ final File tempClass = new File(Constants.tempDirectory + fs + "temp" + MiscUtils.randomString(32) + ".class");
+
+ DiskWriter.replaceFileBytes(tempClass.getAbsolutePath(), b, false);
+
+ SystemConsole sysOut = null;
+ try
+ {
+ URLClassLoader child = new URLClassLoader(
+ new URL[] {new File(Configuration.javaTools).toURI().toURL()},
+ this.getClass().getClassLoader()
+ );
+ //Class> javap = child.loadClass("com.sun.tools.javap.Main");
+ Class> javap = Class.forName("com.sun.tools.javap.Main", true, child);
+ Method main = javap.getMethod("main", String[].class);
+ Object cl = javap.newInstance();
+
+ //pipe sys out
+ sysOut = new SystemConsole("");
+
+ //invoke Javap
+ main.invoke(cl, (Object) new String[]{"-c", "-l", "-constants", tempClass.getAbsolutePath()});
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ finally
+ {
+ tempClass.delete();
+ }
+
+ if(sysOut != null)
+ {
+ sysOut.finished();
+ return sysOut.getTextAreaOutputStreamOut().getBuffer().toString();
+ }
+
+ return KONLOCH;
+ }
+
+ @Override
+ public void decompileToZip(String sourceJar, String zipName) {
+
+ }
+}
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/decompilers/impl/KrakatauDecompiler.java b/src/main/java/the/bytecode/club/bytecodeviewer/decompilers/impl/KrakatauDecompiler.java
index 9c291717..269ae7ef 100644
--- a/src/main/java/the/bytecode/club/bytecodeviewer/decompilers/impl/KrakatauDecompiler.java
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/decompilers/impl/KrakatauDecompiler.java
@@ -149,21 +149,15 @@ public class KrakatauDecompiler extends InternalDecompiler
@Override
public String decompileClassNode(ClassNode cn, byte[] b) {
- if (Configuration.python2.isEmpty()) {
- BytecodeViewer.showMessage("You need to set your Python (or PyPy for speed) 2.7 executable path.");
- ExternalResources.getSingleton().selectPython2();
- }
+ if(!ExternalResources.getSingleton().hasSetPythonCommand())
+ return "You need to set your Python 2.7 path!";
+
if (Configuration.rt.isEmpty()) {
BytecodeViewer.showMessage("You need to set your JRE RT Library." +
"\r\n(C:\\Program Files (x86)\\Java\\jre7\\lib\\rt.jar)");
ExternalResources.getSingleton().selectJRERTLibrary();
}
- if (Configuration.python2.isEmpty()) {
- BytecodeViewer.showMessage("You need to set Python!");
- return "Set your paths";
- }
-
if (Configuration.rt.isEmpty()) {
BytecodeViewer.showMessage("You need to set RT.jar!");
return "Set your paths";
@@ -240,10 +234,8 @@ public class KrakatauDecompiler extends InternalDecompiler
@Override
public void decompileToZip(String sourceJar, String zipName) {
- if (Configuration.python2.isEmpty()) {
- BytecodeViewer.showMessage("You need to set your Python (or PyPy for speed) 2.7 executable path.");
- ExternalResources.getSingleton().selectPython2();
- }
+ if(!ExternalResources.getSingleton().hasSetPythonCommand())
+ return;
ExternalResources.getSingleton().rtCheck();
if (Configuration.rt.isEmpty()) {
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/decompilers/impl/KrakatauDisassembler.java b/src/main/java/the/bytecode/club/bytecodeviewer/decompilers/impl/KrakatauDisassembler.java
index a9419468..7fc67bc5 100644
--- a/src/main/java/the/bytecode/club/bytecodeviewer/decompilers/impl/KrakatauDisassembler.java
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/decompilers/impl/KrakatauDisassembler.java
@@ -47,15 +47,8 @@ public class KrakatauDisassembler extends InternalDecompiler
{
@Override
public String decompileClassNode(ClassNode cn, byte[] b) {
- if (Configuration.python2.isEmpty()) {
- BytecodeViewer.showMessage("You need to set your Python (or PyPy for speed) 2.7 executable path.");
- ExternalResources.getSingleton().selectPython2();
- }
-
- if (Configuration.python2.isEmpty()) {
- BytecodeViewer.showMessage("You need to set Python!");
- return "Set your paths";
- }
+ if(!ExternalResources.getSingleton().hasSetPythonCommand())
+ return "You need to set your Python 2.7 path!";
String s = "Bytecode Viewer Version: " + VERSION + nl + nl +
"Please send this to konloch@gmail.com. " + nl + nl;
@@ -120,10 +113,8 @@ public class KrakatauDisassembler extends InternalDecompiler
@Override
public void decompileToZip(String sourceJar, String zipName) {
- if (Configuration.python2.isEmpty()) {
- BytecodeViewer.showMessage("You need to set your Python (or PyPy for speed) 2.7 executable path.");
- ExternalResources.getSingleton().selectPython2();
- }
+ if(!ExternalResources.getSingleton().hasSetPythonCommand())
+ return;
String ran = MiscUtils.randomString(32);
final File tempDirectory = new File(Constants.tempDirectory + fs + ran + fs);
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/components/JFrameConsolePrintStream.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/components/JFrameConsolePrintStream.java
index 37cadc35..99c67189 100644
--- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/components/JFrameConsolePrintStream.java
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/components/JFrameConsolePrintStream.java
@@ -83,6 +83,16 @@ public class JFrameConsolePrintStream extends JFrameConsole
System.setOut(Constants.OUT);
}
+ public JTextAreaOutputStream getTextAreaOutputStreamErr()
+ {
+ return textAreaOutputStreamErr;
+ }
+
+ public JTextAreaOutputStream getTextAreaOutputStreamOut()
+ {
+ return textAreaOutputStreamOut;
+ }
+
private void update()
{
if(System.currentTimeMillis()-lastUpdate <= 50)
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/components/JTextAreaOutputStream.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/components/JTextAreaOutputStream.java
index 02ed534d..4897b261 100644
--- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/components/JTextAreaOutputStream.java
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/components/JTextAreaOutputStream.java
@@ -55,4 +55,9 @@ public class JTextAreaOutputStream extends OutputStream
sb.append((char) b);
og.write(b);
}
+
+ public StringBuilder getBuffer()
+ {
+ return sb;
+ }
}
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/DecompilerSelectionPane.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/DecompilerSelectionPane.java
index 9d32aee1..d06b3501 100644
--- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/DecompilerSelectionPane.java
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/DecompilerSelectionPane.java
@@ -37,11 +37,12 @@ public class DecompilerSelectionPane
private final DecompilerViewComponent smali = new DecompilerViewComponent("Smali", BYTECODE, Decompiler.SMALI_DISASSEMBLER);
private final DecompilerViewComponent bytecode = new DecompilerViewComponent("Bytecode", BYTECODE_NON_EDITABLE, Decompiler.BYTECODE_DISASSEMBLER);
private final DecompilerViewComponent asmTextify = new DecompilerViewComponent("ASM Textify", BYTECODE_NON_EDITABLE, Decompiler.ASM_TEXTIFY_DISASSEMBLER);
+ private final DecompilerViewComponent javap = new DecompilerViewComponent("JavaP", BYTECODE_NON_EDITABLE, Decompiler.JAVAP_DISASSEMBLER);
//TODO when adding new decompilers insert the DecompilerViewComponent object into here
// also in the group, then finally the build menu
public List components = new ArrayList<>(Arrays.asList(
- procyon, CFR, JADX, JD, fern, krakatau, smali, bytecode, asmTextify));
+ procyon, CFR, JADX, JD, fern, krakatau, smali, bytecode, asmTextify, javap));
public DecompilerSelectionPane(int paneID)
{
@@ -82,16 +83,8 @@ public class DecompilerSelectionPane
{
//build the radiobutton group
group.add(none);
- procyon.addToGroup(group);
- CFR.addToGroup(group);
- JADX.addToGroup(group);
- JD.addToGroup(group);
- fern.addToGroup(group);
- krakatau.addToGroup(group);
- smali.addToGroup(group);
- bytecode.addToGroup(group);
- asmTextify.addToGroup(group);
group.add(hexcode);
+ components.forEach(decompilerViewComponent -> decompilerViewComponent.addToGroup(group));
//build the action commands
none.setActionCommand(Decompiler.NONE.name());
@@ -137,6 +130,7 @@ public class DecompilerSelectionPane
menu.add(smali.getMenu());
menu.add(new JSeparator());
menu.add(bytecode.getMenu());
+ menu.add(javap.getMenu());
menu.add(asmTextify.getMenu());
menu.add(new JSeparator());
menu.add(hexcode);
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/resources/ExternalResources.java b/src/main/java/the/bytecode/club/bytecodeviewer/resources/ExternalResources.java
index e95853d6..2f9bdde0 100644
--- a/src/main/java/the/bytecode/club/bytecodeviewer/resources/ExternalResources.java
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/resources/ExternalResources.java
@@ -6,7 +6,10 @@ import the.bytecode.club.bytecodeviewer.SettingsSerializer;
import the.bytecode.club.bytecodeviewer.util.DialogueUtils;
import the.bytecode.club.bytecodeviewer.util.JRTExtractor;
+import java.io.BufferedReader;
import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
import java.util.Objects;
import static the.bytecode.club.bytecodeviewer.Constants.*;
@@ -83,6 +86,37 @@ public class ExternalResources
return Configuration.java;
}
+ /**
+ * Check if the python command has been set
+ */
+ public boolean hasJavaToolsSet()
+ {
+ return !getJavaTools(false).isEmpty();
+ }
+
+ /**
+ * Auto-detect the Java command
+ */
+ public String getJavaTools(boolean blockTillSelected)
+ {
+ boolean empty = Configuration.javaTools.isEmpty();
+
+ if(!empty)
+ return Configuration.javaTools;
+
+ //TODO auto-detect the Java path
+ boolean block = true;
+ while (Configuration.javaTools.isEmpty() && block)
+ {
+ BytecodeViewer.showMessage("You need to set your Java Tools path, this requires the JDK to be downloaded." +
+ nl + "(C:/Program Files/Java/JDK_xx/lib/tools.jar)");
+ ExternalResources.getSingleton().selectJavaTools();
+ block = !blockTillSelected; //signal block flag off
+ }
+
+ return Configuration.javaTools;
+ }
+
/**
* Check if the python command has been set
*/
@@ -106,12 +140,18 @@ public class ExternalResources
//check using python CLI flag
try
{
- //TODO read the version output to verify python 2
+ //read the version output to verify python 2
ProcessBuilder pb = new ProcessBuilder("python", "-2", "--version");
- pb.start();
+ Process p = pb.start();
+ p.waitFor();
- Configuration.python2 = "python -2"; //python is set
- return Configuration.python2;
+ //set python path
+ if(readProcess(p).toLowerCase().contains("python 2"))
+ {
+ Configuration.python2 = "python";
+ Configuration.python2Extra = "-2";
+ return Configuration.python2;
+ }
}
catch (Exception e) { } //ignore
finally
@@ -122,12 +162,17 @@ public class ExternalResources
//check if 'python' command is bound as python 2.X
try
{
- //TODO read the version output to verify python 2
+ //read the version output to verify python 2
ProcessBuilder pb = new ProcessBuilder("python", "--version");
- pb.start();
+ Process p = pb.start();
+ p.waitFor();
- Configuration.python2 = "python"; //python is set
- return Configuration.python2;
+ //set python path
+ if(readProcess(p).toLowerCase().contains("python 2"))
+ {
+ Configuration.python2 = "python";
+ return Configuration.python2;
+ }
}
catch (Exception e) { } //ignore
finally
@@ -217,6 +262,19 @@ public class ExternalResources
SettingsSerializer.saveSettingsAsync();
}
+ public void selectJavaTools()
+ {
+ final File file = DialogueUtils.fileChooser("Select Java Tools Jar",
+ "Java Tools Jar (Inside Of JDK 'C:/Program Files/Java/JDK_xx/lib/tools.jar')",
+ "everything");
+
+ if(file == null)
+ return;
+
+ Configuration.javaTools = file.getAbsolutePath();
+ SettingsSerializer.saveSettingsAsync();
+ }
+
public void selectOptionalLibraryFolder()
{
final File file = DialogueUtils.fileChooser("Select Library Folder",
@@ -278,4 +336,21 @@ public class ExternalResources
return null;
}
+
+ /**
+ * @author https://stackoverflow.com/a/16714180
+ */
+ public String readProcess(Process process) throws IOException
+ {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
+ StringBuilder builder = new StringBuilder();
+ String line;
+ while ((line = reader.readLine()) != null)
+ {
+ builder.append(line);
+ builder.append(System.getProperty("line.separator"));
+ }
+
+ return builder.toString();
+ }
}
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/resources/importing/impl/XAPKResourceImporter.java b/src/main/java/the/bytecode/club/bytecodeviewer/resources/importing/impl/XAPKResourceImporter.java
index f0c4bfc6..61d02f79 100644
--- a/src/main/java/the/bytecode/club/bytecodeviewer/resources/importing/impl/XAPKResourceImporter.java
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/resources/importing/impl/XAPKResourceImporter.java
@@ -78,7 +78,7 @@ public class XAPKResourceImporter implements Importer
public File exportTo(File original, String extension, byte[] bytes)
{
File file = new File(original.getAbsolutePath() + extension);
- DiskWriter.replaceFile(file.getAbsolutePath(), bytes, false);
+ DiskWriter.replaceFileBytes(file.getAbsolutePath(), bytes, false);
return file;
}
}
diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/util/JarUtils.java b/src/main/java/the/bytecode/club/bytecodeviewer/util/JarUtils.java
index 922f6f34..e1f97114 100644
--- a/src/main/java/the/bytecode/club/bytecodeviewer/util/JarUtils.java
+++ b/src/main/java/the/bytecode/club/bytecodeviewer/util/JarUtils.java
@@ -335,7 +335,7 @@ public class JarUtils
File f = new File(name);
f.mkdirs();
- DiskWriter.replaceFile(name, cw.toByteArray(), false);
+ DiskWriter.replaceFileBytes(name, cw.toByteArray(), false);
}
} catch (Exception e) {
BytecodeViewer.handleException(e);