Developer

Examine class files with the javap command

Javap is useful when you want to see what your compiler is doing for (or to) you, or when you want to see what effect a code change will have on the compiled class file. Get more details on using the javap command.

Java developers are familiar with the performance best practice of using a StringBuffer in a loop instead of concatenating String objects. However, most developers have never seen the difference in terms of bytecode for one approach vs. the other. There is a tool included with the Java Development Kit (JDK) called javap that can show you why you would want to adopt this best practice.

Javap takes a class and dumps information about its methods to standard out. It doesn't decompile the code into Java source code, but it will disassemble the bytecode into the bytecode instructions defined by the Java Virtual Machine specification.

Javap is useful when you want to see what your compiler is doing for (or to) you, or when you want to see what effect a code change will have on the compiled class file.

Let's use the StringBuffer vs. String scenario mentioned above as an example. Below is a contrived class that has two methods that return a String consisting of the numbers 0 to n, where n is supplied by the caller. The only difference between the two methods is that one uses a String to build the result, and the other uses a StringBuffer.

public class JavapTip {
    public static void main(String []args) {
    }

    private static String withStrings(int count) {
        String s = "";
        for (int i = 0; i < count; i++) {
            s += i;
        }

        return s;
    }

    private static String withStringBuffer(int count) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < count; i++) {
            sb.append(i);
        }

        return sb.toString();
    }
}

Now let's take a look at what javap outputs when it's run against the class with the -c option. The -c option tells javap to disassemble the bytecode found in the class.

Running it looks like this:

>javap -c JavapTip

The output of the command relative to this tip is:

Method java.lang.String withStrings(int)
   0 ldc #2 <String "">
   2 astore_1
   3 iconst_0
   4 istore_2
   5 goto 30
   8 new #3 <Class java.lang.StringBuffer>
  11 dup
  12 invokespecial #4 <Method java.lang.StringBuffer()>
  15 aload_1
  16 invokevirtual #5 <Method java.lang.StringBuffer append(java.lang.String)>
  19 iload_2
  20 invokevirtual #6 <Method java.lang.StringBuffer append(int)>
  23 invokevirtual #7 <Method java.lang.String toString()>
  26 astore_1
  27 iinc 2 1
  30 iload_2
  31 iload_0
  32 if_icmplt 8
  35 aload_1
  36 areturn

Method java.lang.String withStringBuffer(int)
   0 new #3 <Class java.lang.StringBuffer>
   3 dup
   4 invokespecial #4 <Method java.lang.StringBuffer()>
   7 astore_1
   8 iconst_0
   9 istore_2
  10 goto 22
  13 aload_1
  14 iload_2
  15 invokevirtual #6 <Method java.lang.StringBuffer append(int)>
  18 pop
  19 iinc 2 1
  22 iload_2
  23 iload_0
  24 if_icmplt 13
  27 aload_1
  28 invokevirtual #7 <Method java.lang.String toString()>
  31 areturn

The output is a little cryptic if you've never seen Java assembler before, but hopefully you can see that the withString method creates a new StringBuffer instance each time through the loop. Then, it appends the current value of the existing String to the StringBuffer and appends the current value of the loop. Finally, it calls toString on the buffer and assigns the results to the existing String reference.

This is in contrast to the withStringBuffer method, which only calls the existing StringBuffer's append method each time through the loop. There's no object creation and no new String references.

In this case, we already knew that using StringBuffer instead of String was a good idea; if we didn't, then javap would have helped us find the answer.

You won't often find yourself in circumstances that require a Java disassembler, but when you do, it's nice to know that you already have one on your machine and that it's simple to use. If you're interested, take a look at javap's other options—you might find features that will come in handy in your environment.

Delivered each Thursday, our free Java newsletter provides insight and hands-on tips you need to unlock the full potential of this programming language. Automatically sign up today!

Editor's Picks

Free Newsletters, In your Inbox