- Richard Feynman -
- 1 Our books on Java
- 2 About Java
- 3 Install Java
- 4 Java Virtual Machine
- 5 Java source code
- 6 Java bytecode
- 7 Java tools
- 7.1 JAR files
- 7.2 java
- 7.3 javac (the compiler)
- 7.4 javadoc
- 7.5 jar
- 7.6 javah
- 7.7 jdb
- 7.8 javap
- 8 Generics
Our books on Java
We have two books on Java on this wiki. Programming with Java which is an introductory book on programming with the Java programming language and technology. We also have a book (which is work in progress!), More programming with Java which addresses some more advanced topics on programming with Java such as design patterns. Another book on this wiki related to Java technology is Android (also work in progress).
Java is both a programming language and a software platform. When we're writing (or developing) Java programs we usually do that in the Java programming language and use Java tools. When we run our programs written in the Java programming language we use the Java software platform.
With the Java platform comes a whole suite of programs used for developing (and running) software written using the Java programming language. The basic programs used with the Java platform, is the JVM (the Java Virtual Machine), which actually runs the programs, and the compiler
javac. The JVM is usually invoked using the
java command. Included in the platform is a rather huge library of "classes" (pre-compiled Java libraries).
Wikipedia has more information about the Java Software Platform.
Read the page Install Java for instructions on how to install Java, verify the installation and how to get started using Java.
Java Virtual Machine
The Java platform is based around the concept of a "virtual machine", which execute "Java bytecode" (compiled Java source code units like classes, interfaces and enums). The idea behind a virtual machine is that you can define the bytecode format once, and make virtual machines to run on virtually (pun intended) any operating platform. The benefit of this, is that you can now develop Java programs on any platform, as long as your compiler compiles the programs to valid bytecode. The compiled bytecode can then run on any computer with a Java virtual machine.
This is not possible with normal compiled languages like C or C++ for instance. Normal (non bytecode-based) languages are compiled to machine code for a specific operating platform. If you intend to port a non-bytecode program to a new platform, you must recompile it for the target platform.
Languages based on the bytecode-virtual machine concept are sometimes said to be "platform independent", since the compiled programs can be moved to a new platform, as long as it has a virtual machine which can execute the bytecode.
Of course, this "extra step" by runnign a virtual machine which executes the compiled program imposes some overhead. In order to speed things up, a JIT (Just In Time) compiler is often used. The JIT actually translates the bytecode to native machine code and uses various techniques to cache (temporarily store in memory) the compiled code for quick re-use.
You can read more about the JVM and JIT technology over at Wikipedia:
Java source code
Java bytecode is the code with the instructions for the Java virtual machine. The instructions in the bytecode are interpreted by the JVM during execution. The byte code is stored in the
.class files created by the
javac compiler. See above for more information on the Java virtual machine.
Wikipedia has more information about Java_bytecode.
java is a program that can execute (run) programs written in Java. java actually executes classes as found in so called class files (see bytecode above). The argument to
java can be the qualified name of a compiled class which contains the special "main method". The
java command starts the virtual machine (JVM) which will read the corresponding class file and execute the instructions of the bytecode in the file.
If you want to execute the class Hello, as found in the file
Hello.java, in the package
$ java org.exampleproject.Hello
Note, that the Hello class must define a special "main" method in order to be possible for the JVM to execute.
javac (the compiler)
javac is a compiler that reads Java source code and transforms that into Java byte code (which it stores in a binary file with the
Simple case of compiling one file
If you want to compile the file
Hello.java in the package
$ javac org/exampleproject/Hello.java
If you want to compile the file
Hello.java in the package
org.exampleproject and put the class files in a separate directory called
$ javac -d bin org/exampleproject/Hello.java
Compiling a class which imports other classes
Sometimes you need to give
javac a classpath.
Let's say we have this directory structure:
. |-- bin `-- src `-- org `-- exampleproject |-- domain | `-- DomainOjbect.java |-- main | `-- Hello.java `-- util `-- HelperClass.java
The packages are called
If we want to remain in the
. directory, above both
bin, and compile
Hello.java and get the class files in a structure under the
bin directory, we'd do this:
javac -d bin src/org/exampleproject/main/Hello.java
The argument to
javac is a flag for where to put the class file(s)
-d bin and the most important argument
src/org/exampleproject/main/Hello.java which is the text file we want to compile.
Hello.java imports for instance
org.exampleproject.util.HelperClass, how can javac find the corresponding source code file for that class?
Remember, we are standing in a directory above
src. The compiler
javac will look for the class
org.exampleproject.util.HelperClass in the current directory, beginning with looking for the
org directory. But the only directories here are
So the compiler will complain about not finding the package
org.exampleproject.util when we try to compile the file
src/org/exampleproject/main/Hello.java (because the Hello class imports
At first, you might think this is strange. But think about it! How could the compiler find
src/org/exampleproject/main/Hello.java? That was simple! We gave the compiler the full relative path to the source code file, from our current directory. It didn't matter that
src is not part of the package name for the package of
Hello. The compiler
javac wants as argument the relative (or absolute) path to the file we want to compile.
So that it could find the
Hello.java, wasn't so strange, since we gave the full path to the file (relative to our current directory). But the compiler discovered that the
Hello class imported
org.exampleproject.util.HelperClass. So the compiler must check if it needs to compile also that class. But the only clue as to where to find the source code file for
HelperClass comes from the package name
org.exampleproject.util. Now, the compiler knows that a package corresponds to a path. So it starts looking for the
org directory. But our current directory only contains the directories
bin. That's why it complains that it can't find the package!
So if we are in a directory which is not immediately above the top package directory (in our case
org), and the class we're trying to compile imports classes from another package, we must help the compiler to find the top-level package directory (again, in our case
This can be accomplished using another flag to
javac, namely the
-cp (for "class path") flag:
$ javac -d bin -cp src src/org/exampleproject/main/Hello.java
Think about that command as meaning the following: Dear
javac, put the class files under the bin/ directory (
-d bin), and look for packages in the src/ directory (
-cp src) when you compile the textfile with source code in
Note that when compiling a class in a package and directing the class files to e.g. bin/ then
javac will create the directories corresponding to the packages of the compiled classes. So if we compile Hello.java which is a class which imports
org.exampleproject.util.HelperClass, we'll get the following directory structure as a result (note the new directories under bin/):
. |-- bin | `-- org | `-- exampleproject | |-- main | | `-- Hello.class | `-- util | `-- HelperClass.class `-- src `-- org `-- exampleproject |-- domain | `-- DomainOjbect.java |-- main | `-- Hello.java `-- util `-- HelperClass.java
DomainObject.java source code wasn't compiled, since neither
HelperClass imported it.
External Links on compiling Java source code
- Compiling Java from the Java Programming wikibook. Good source if you want to learn more about how to use javac
- Oracle tutorial on Compiling and running Java
- Oracle tutorial - Common problems and solutions (when compiling and running)
Javadoc is a tool that parses the declarations and documentation comments in a set of source files and produces a set of HTML pages describing the classes, interfaces, constructors, methods, and fields.
A program that combines files into one file in the Wikipedia: JAR file. This program can be used to combine class files (with Java byte code) into one single file.
If you want to pack class files in the bin directory:
$ jar cf exampleproject.jar org/exampleproject
- Wikipedia on JAR
- Oracle - Tutorial on JAR
- Oracle - JAR files
javah produces C header files from a Java class. These files provide the connecting glue that allow your Java and C code to interact.
The Java Debugger,
jdb, is a simple command-line debugger for Java classes. It is a demonstration of the Java Platform Debugger Architecture that provides inspection and debugging of a local or remote Java Virtual Machine.
javap command disassembles one or more class files. Its output depends on the options used. If no options are used,
javap prints out the package, protected, and public fields and methods of the classes passed to it.
javap prints its output to stdout.
Generics was introduced to the Java programming language with the J2SE 5.0 version of the language. It is an extension of the Java type system with the aim of shifting the type safety of certain operations to compile-time, rather than runtime. A typical use of Generics, is found in the collections framework. A generic collection like
List<T>, allows the programmer to create a list permitting only a certain type of elements. The adding and retrieval of the elements are now type-checked at compile-time.
Prior to Java 5 and Generics, collections could only store objects of type Object. This meant that you could add any reference type to the collection, since all reference types "extend Object" (count as types of Object). This, in turn, of course meant that the compiler couldn't do so much if the programmer by mistake added "the wrong type" of reference to the collection. When retrieving an element of "wrong type", you would get the element as of type "reference to Object". When using type-cast to convert the element to the expected type, you would typically get a runtime exception (ClassCastException) if the element wasn't what you hoped for.
Generics aimed to solve this, and it works quite well, even though some flaws have been discovered. Read more about Generics over at Wikipedia: Generics in Java .