Disassembly
Disassembly is a reconstruction of a Java class file into a human-readable representation or into Java source code (decompilation), this is the main view you’ll see in slicer.
The currently supported disassemblers/decompilers are:
- JASM (disassembler, https://github.com/jumanji144/Jasm)
- CFR (decompiler, https://github.com/leibnitz27/cfr)
- Vineflower (default; decompiler, https://github.com/Vineflower/vineflower)
- Procyon (decompiler, https://github.com/mstrobel/procyon)
- slicer (pseudocode disassembler, https://github.com/run-slicer/asm)
Custom ones can be added through the Disassembler API (popular ones are here).
Integrated disassembler
slicer includes a basic disassembler to power several bytecode analysis features, such as:
- the class view (prettifying class file constructs)
- the flow graph (prettifying instructions and computing the graph itself)
- the search (prettifying constant pool entries)
- the pseudocode disassembler
Constant pool
Constant pool entries are represented in a format consisting of the entry type identifier and the stringified value of the entry.
UTF8 <value>
- any string-like value defined in the class file (names, descriptors, strings, …)INTEGER/FLOAT/LONG/DOUBLE <value>
- primitives defined in the class fileCLASS <class name in internal format, UTF8 value>
- class referenceSTRING "<UTF8 value>"
- string literal defined in the class fileMETHOD_TYPE <method descriptor, UTF8 value>
- method descriptor referenceMODULE/PACKAGE <module/package name, UTF8 value>
- module-info/package-info name dataFIELDREF/METHODREF/INTERFACE_METHODREF <owner name, CLASS value> <member name and descriptor, NAME_AND_TYPE value>
- class member referenceNAME_AND_TYPE <name, UTF8 value> <descriptor, UTF8 value>
- member name and descriptor referenceDYNAMIC/INVOKE_DYNAMIC <bootstrap method index> <member name and descriptor, NAME_AND_TYPE value>
METHOD_HANDLE <handle kind> <METHODREF value>
- handle kinds:
GET_FIELD
,GET_STATIC
,PUT_FIELD
,PUT_STATIC
,INVOKE_VIRTUAL
,INVOKE_STATIC
,INVOKE_SPECIAL
,NEW_INVOKE_SPECIAL
,INVOKE_INTERFACE
- handle kinds:
Pseudocode
The disassembler produces pseudocode similar to Java, which allows you to view the rough structure of classes in a familiar way.
It does not resugar many code constructs, such as if statements and variable declarations, so knowledge of the JVM instruction set is highly necessary.
// Source file: StringsDuplicates.javapackage sample.string;
public super class StringsDuplicates extends java.lang.Object { private static final java.lang.String F = "Hello this is a duplicate string";
public StringsDuplicates() { // 0: aload this Lsample/string/StringsDuplicates; // 1: invokespecial java/lang/Object <init> ()V // 4: return } public static void main(java.lang.String[] args) { // 0: ldc "Hello this is a duplicate string" // 2: astore s Ljava/lang/String; // 3: ldc "Hello this is a duplicate string" // 5: invokestatic sample/string/StringsDuplicates p (Ljava/lang/String;)V // 8: aload s Ljava/lang/String; // 9: invokestatic sample/string/StringsDuplicates p (Ljava/lang/String;)V // 12: invokestatic sample/string/StringsDuplicates duplicate ()Ljava/lang/String; // 15: invokestatic sample/string/StringsDuplicates p (Ljava/lang/String;)V // 18: ldc "Hello this is a duplicate string" // 20: invokestatic sample/string/StringsDuplicates p (Ljava/lang/String;)V // 23: return } private static java.lang.String duplicate() { // 0: ldc "Hello this is a duplicate string" // 2: areturn } public static void p(java.lang.String s) { // 0: getstatic java/lang/System out Ljava/io/PrintStream; // 3: aload s Ljava/lang/String; // 4: invokevirtual java/io/PrintStream println (Ljava/lang/String;)V // 7: return }}
Header
Dissecting the class header, we can make out that we’re looking at a regular class named StringsDuplicates
with the modifiers ACC_PUBLIC
and ACC_SUPER
, and a super class of java.lang.Object
.
Furthermore, it’s located in the sample.string
package and was compiled from a StringsDuplicates.java
source file.
// Source file: StringsDuplicates.javapackage sample.string;
public super class StringsDuplicates extends java.lang.Object { // ...}
Members
Our class contains a couple of methods and one self-explanatory field, with one method resugared to its original constructor syntax.
The field has an assigned value, showing a value from its ConstantValue
attribute.
Code inside the methods is represented via string representations of individual instructions and their offsets.
Instructions may also be encased in a try-catch statement with a virtual goto in the handler, signifying an entry in the exception handler table.
// ...private static final java.lang.String F = "Hello this is a duplicate string";
public StringsDuplicates() { // 0: aload this Lsample/string/StringsDuplicates; // 1: invokespecial java/lang/Object <init> ()V // 4: return}public static void main(java.lang.String[] args) { // 0: ldc "Hello this is a duplicate string" // 2: astore s Ljava/lang/String; // 3: ldc "Hello this is a duplicate string" // 5: invokestatic sample/string/StringsDuplicates p (Ljava/lang/String;)V // 8: aload s Ljava/lang/String; // 9: invokestatic sample/string/StringsDuplicates p (Ljava/lang/String;)V // 12: invokestatic sample/string/StringsDuplicates duplicate ()Ljava/lang/String; // 15: invokestatic sample/string/StringsDuplicates p (Ljava/lang/String;)V // 18: ldc "Hello this is a duplicate string" // 20: invokestatic sample/string/StringsDuplicates p (Ljava/lang/String;)V // 23: return}
// ...