JD-Core es un decompilador de clases Java que destaca, entre otras cosas, porque, a diferencia del popular Jad, soporta algunas de las novedades más importantes introducidas en Java 5, como los generics o el tipo enum
. Este decompilador cuenta con dos interfaces, una aplicación standalone llamada JD-GUI y un plugin para Eclipse llamado JD-Eclipse.
Vamos a crear una pequeña clase de ejemplo para demostrar su funcionamiento.
import java.util.EnumSet; public class Ejemplo { enum Dia { LUNES, MARTES, MIERCOLES, JUEVES, VIERNES, SABADO, DOMINGO } public static void main(String[] args) { for (Dia dia : EnumSet.allOf(Dia.class)) System.out.println(dia); } }
Si abrimos la vista de navegador en Eclipse (Window -> Show View -> Navigator) y hacemos doble clic sobre el archivo que representa a nuestra clase compilada en la carpeta bin, se lanzará el visor de clases, mostrando el bytcode de la clase. También podemos utilizar la herramienta javap, incluída en el JDK:
javap -c Ejemplo
El bytecode de nuestra clase tiene el siguiente aspecto:
// Compiled from Ejemplo.java (version 1.6 : 50.0, super bit) public class Ejemplo { // Method descriptor #6 ()V // Stack: 1, Locals: 1 public Ejemplo(); 0 aload_0 [this] 1 invokespecial java.lang.Object() [8] 4 return Line numbers: [pc: 0, line: 3] Local variable table: [pc: 0, pc: 5] local: this index: 0 type: Ejemplo // Method descriptor #15 ([Ljava/lang/String;)V // Stack: 2, Locals: 3 public static void main(java.lang.String[] args); 0 ldc <Class Ejemplo$Dia> [16] 2 invokestatic java.util.EnumSet.allOf(java.lang.Class) : java.util.EnumSet [18] 5 invokevirtual java.util.EnumSet.iterator() : java.util.Iterator [24] 8 astore_2 9 goto 29 12 aload_2 13 invokeinterface java.util.Iterator.next() : java.lang.Object [28] [nargs: 1] 18 checkcast Ejemplo$Dia [16] 21 astore_1 [dia] 22 getstatic java.lang.System.out : java.io.PrintStream [34] 25 aload_1 [dia] 26 invokevirtual java.io.PrintStream.println(java.lang.Object) : void [40] 29 aload_2 30 invokeinterface java.util.Iterator.hasNext() : boolean [46] [nargs: 1] 35 ifne 12 38 return Line numbers: [pc: 0, line: 9] [pc: 22, line: 10] [pc: 29, line: 9] [pc: 38, line: 11] Local variable table: [pc: 0, pc: 39] local: args index: 0 type: java.lang.String[] [pc: 22, pc: 29] local: dia index: 1 type: Ejemplo.Dia Stack map table: number of frames 2 [pc: 12, full, stack: {}, locals: {java.lang.String[], _, java.util.Iterator}] [pc: 29, same] Inner classes: [inner class info: #16 Ejemplo$Dia, outer class info: #1 Ejemplo inner name: #59 Dia, accessflags: 16408 static final] }
Como vemos en realidad el bucle for each se convierte en un bucle que utiliza un iterador.
Si usamos el decompilador jad el resultado será:
import java.io.PrintStream; import java.util.EnumSet; import java.util.Iterator; public class Ejemplo { static final class Dia extends Enum { public static Dia[] values() { Dia adia[]; int i; Dia adia1[]; System.arraycopy(adia = ENUM$VALUES, 0, adia1 = new Dia[i = adia.length], 0, i); return adia1; } public static Dia valueOf(String s) { return (Dia) Enum.valueOf(Ejemplo$Dia, s); } public static final Dia LUNES; public static final Dia MARTES; public static final Dia MIERCOLES; public static final Dia JUEVES; public static final Dia VIERNES; public static final Dia SABADO; public static final Dia DOMINGO; private static final Dia ENUM$VALUES[]; static { LUNES = new Dia("LUNES", 0); MARTES = new Dia("MARTES", 1); MIERCOLES = new Dia("MIERCOLES", 2); JUEVES = new Dia("JUEVES", 3); VIERNES = new Dia("VIERNES", 4); SABADO = new Dia("SABADO", 5); DOMINGO = new Dia("DOMINGO", 6); ENUM$VALUES = (new Dia[] { LUNES, MARTES, MIERCOLES, JUEVES, VIERNES, SABADO, DOMINGO }); } private Dia(String s, int i) { super(s, i); } } public Ejemplo() { } public static void main(String args[]) { Dia dia; for (Iterator iterator = EnumSet.allOf(Ejemplo$Dia).iterator(); iterator .hasNext(); System.out.println(dia)) dia = (Dia) iterator.next(); } }
que como vemos no está demasiado mal, pero dista bastante del original.
Por último este es el resultado de JD-GUI:
import java.io.PrintStream; import java.util.EnumSet; import java.util.Iterator; public class Ejemplo { public static void main(String[] args) { for (Iterator localIterator = EnumSet.allOf(Ejemplo.Dia.class) .iterator(); localIterator.hasNext();) { Ejemplo.Dia dia = (Ejemplo.Dia) localIterator.next(); System.out.println(dia); } } static enum Dia { LUNES, MARTES, MIERCOLES, JUEVES, VIERNES, SABADO, DOMINGO; } }
La verdad es que es algo muy útil, que no sabes en que momento lo vas a necesitar.
Programa a tener en mente xD
yo lo he usado muchas veces para decompilar las clases que vienen en la EBS de Oracle! te salva la vida 😉
Pingback: JD-GUI, decompilar una clase Java « Ubuntu Life
Pingback: 100 programas gratis « Bichotoblog
estaa bueno
Qué tan ilegal o legal es usar esta aplicación??
Gracias, es una herramienta necesaria para decopilar clases realizadas en otros entornos y usarlos para eclipse, por citar un ejemplo.
Abrazox