Archive

Posts Tagged ‘disassamble’

Quick decompile of Java code

April 29, 2013 2 comments

If you need to quickly decompile a java .class file and you only have access to a machine with the JDK installed on it (like production servers) – you can use a tool which is built-in with the JDK.

It is called javap and it can disassemble any .class file. All you need to do is run it from the directory where all of your the .class files exist (the “root”).
It will also work if the class can be found within the CLASSPATH (i.e. the environment variable CLASSPATH) and it can be given a specific classpath via a CLI argument. It can also find the .class file within a JAR.

javap <FQCN> Usage Gets the list of all the public members (variables + methods).
Only gives you method declerations.
Example javap java.lang.String
javap -private <FQCN> Usage Gets the list of all the members (variables + methods).
Only gives you method declerations.
Example javap -private java.lang.String
javap -c <FQCN> Usage Same as javap <FQCN>, but also disassembles the method body.
This does not “decompile” – but you can understand what will happen in simple methods.
Example javap -c java.lang.String
javap -c -private <FQCN> Usage Same as above but does it for all private members as well.
Example javap -c -private java.lang.String

FQCN: Fully Qualified Class Name.

How does it look? Take for example this piece of code:

package com.ron;

import java.lang.*;

public class JavapSample
{
        private String someMember;

        public JavapSample(int someArgument)
        {
                someMember = String.valueOf(someArgument);
        }

        public void doSomething()
        {
                System.out.println(someMember);
        }

        private void doSomethingSecret()
        {
                System.out.println("Secret ...");
        }
}

Here is the output:

public class com.ron.JavapSample extends java.lang.Object{
    public com.ron.JavapSample(int);
    public void doSomething();
}
public class com.ron.JavapSample extends java.lang.Object{
    private java.lang.String someMember;
    public com.ron.JavapSample(int);
    public void doSomething();
    private void doSomethingSecret();
}
public class com.ron.JavapSample extends java.lang.Object{
private java.lang.String someMember;

public com.ron.JavapSample(int);
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   aload_0
   5:   iload_1
   6:   invokestatic    #2; //Method java/lang/String.valueOf:(I)Ljava/lang/String;
   9:   putfield        #3; //Field someMember:Ljava/lang/String;
   12:  return

public void doSomething();
  Code:
   0:   getstatic       #4; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   aload_0
   4:   getfield        #3; //Field someMember:Ljava/lang/String;
   7:   invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   10:  return

private void doSomethingSecret();
  Code:
   0:   getstatic       #4; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc     #6; //String Secret ...
   5:   invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   8:   return
}

Where/When to use it – I use it when I need to ensure a certain fix is available within a JAR on a QA/Prod environment. It is not intrusive – and it is rather easy to understand if the fix is there or not.

Note for Java7 users: In java 7 it looks like javap can receive a .class file as an argument instead of the FQCN.

Categories: Java, Tools Tags: , ,
%d bloggers like this: