javap

How to disassemble and decompile Scala code (javap, scalac, jad)

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 14.6, “How to disassemble and decompile Scala code.”

Problem: In the process of learning Scala, or trying to understand a particular problem, you want to examine the source code and bytecode the Scala compiler generates from your original source code.

Solution: You can use several different approaches to see how your Scala source code is translated:

Java’s javap command doesn’t show private members (by default)

As I was just reminded, Java’s javap command doesn’t show private members by default. You have to use the -p option of javap to see private members.

I was just reminded of that when using the Scala REPL. Given this Person class with a private constructor field named name:

class Person(private var name: String)

javap without the -p option shows this:

You can run the `javap` command inside the Scala REPL

As shown in the image, I was just reminded that you can run javap inside the Scala REPL. The REPL help command shows some other things you can do:

scala> :help

All commands can be abbreviated, e.g., :he instead of :help.
:edit <id>|<line>        edit history
:help [command]          print this summary or command-specific help
:history [num]           show the history (optional num is commands to show)
:h? <string>             search the history
:imports [name name ...] show import history, identifying sources of names
:implicits [-v]          show the implicits in scope
:javap <path|class>      disassemble a file or class name
:line <id>|<line>        place line(s) at the end of history
:load <path>             interpret lines in a file
:paste [-raw] [path]     enter paste mode or paste a file
:power                   enable power user mode
:quit                    exit the interpreter
:replay [options]        reset the repl and replay all previous commands
:require <path>          add a jar to the classpath
:reset [options]         reset the repl to its initial state, forgetting all session entries
:save <path>             save replayable session to a file
:sh <command line>       run a shell command (result is implicitly => List[String])
:settings <options>      update compiler options, if possible; see reset
:silent                  disable/enable automatic printing of results
:type [-v] <expr>        display the type of an expression without evaluating it
:kind [-v] <type>        display the kind of a type. see also :help kind
:warnings                show the suppressed warnings from the most recent line which had any

A look at how the Scala `lazy val` syntax gets converted into Java code (bytecode)

Table of Contents1 - A little `lazy val` conversion example2 - A second `lazy val` conversion example3 - One more `lazy val` conversion example4 - The end

I don’t have any major conclusions to share in this blog post, but ... what I was curious about is how Scala implements “lazy val” fields. That is, when the Scala code I write is translated into a .class file and bytecode that a JVM can understand, what does that resulting code look like?

Converting a Scala class file to decompiled Java source code

As a Scala newbie, I'm curious about how the process of converting a Scala class back to Java source code works. What I really want to see is how my Scala source code is converted to Java source code. Besides plain old curiosity, I think that understanding more about how Scala works can also be very important to my understanding of Scala (such as the apply() method, and so on).