Chapter 3. Tools of the Trade

While you will almost certainly do the majority of your Java development in an IDE such as Eclipse, NetBeans, or (the author’s favorite, Intellij IDEA), all of the core tools you need to build Java applications are included in the Java Development Kit (JDK) that you have likely already downloaded from Oracle for version 7. In this chapter, we’ll discuss some of these command-line tools that you can use to compile, run, and package Java applications. There are many additional developer tools included in the JDK that we’ll discuss throughout this book.

For an introduction to the Eclipse IDE and instructions for loading all of the examples in this book as an Eclipse project, see Appendix A. In Chapter 22, we introduce the NetBeans IDE with our discussion of the JavaBeans component architecture, so you will get additional GUI development environment experience there.

JDK Environment

After you install Java 7, the core java runtime command may appear in your path (available to run) automatically. However, many of the other commands provided with the JDK may not be available unless you add the Java bin directory to your execution path. The following commands show how to do this on Mac OS X and Windows. You will, of course, have to change the path to match the version of Java you have installed.

# Mac OS X
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.7.0_09.jdk/Contents/Home
export PATH=$PATH:$JAVA_HOME/bin

# Windows
set JAVA_HOME=c:\Program Files\Java\jdk1.7.0_09

On Mac OS X, the situation may be more confusing because recent versions ship with “stubs” for the Java commands installed. If you attempt to run one of these commands, the OS will prompt you to download Java at that time. As of the time of this writing, Mac OS X still ships with Java version 6, so you will need to download version 7 and set up your environment as just shown.

When in doubt, your go-to test for determining which version of the tools you are using is to use the -version flag on the java and javac commands:

java -version

# java version "1.7.0_07"
# Java(TM) SE Runtime Environment (build 1.7.0_07-b10)
# Java HotSpot(TM) 64-Bit Server VM (build 23.3-b01, mixed mode)

javac -version

# javac 1.7.0_07

The Java VM

A Java virtual machine (VM) is software that implements the Java runtime system and executes Java applications. It can be a standalone application like the java command that comes with the JDK or built into a larger application like a web browser. Usually the interpreter itself is a native application, supplied for each platform, which then bootstraps other tools written in the Java language. Tools such as Java compilers and IDEs are often implemented directly in Java to maximize their portability and extensibility. NetBeans, for example, is a pure-Java application.

The Java VM performs all the runtime activities of Java. It loads Java class files, verifies classes from untrusted sources, and executes the compiled bytecode. It manages memory and system resources. Good implementations also perform dynamic optimization, compiling Java bytecode into native machine instructions.

Running Java Applications

A standalone Java application must have at least one class containing a method called main(), which is the first code to be executed upon startup. To run the application, start the VM, specifying that class as an argument. You can also specify options to the interpreter as well as arguments to be passed to the application:

    % java [interpreter options] class_name [program arguments]

The class should be specified as a fully qualified class name, including the package name, if any. Note, however, that you don’t include the .class file extension. Here are a couple of examples:

    %java animals.birds.BigBird
    %java MyTest

The interpreter searches for the class in the classpath, a list of directories and archive files where classes are stored. We’ll discuss the classpath in detail in the next section. The classpath can be specified either by an environment variable or with the command-line option -classpath. If both are present, the command-line option is used.

Alternately, the java command can be used to launch an “executable” Java archive (JAR) file:

    % java -jar spaceblaster.jar

In this case, the JAR file includes metadata with the name of the startup class containing the main() method, and the classpath becomes the JAR file itself.

After loading the first class and executing its main() method, the application can reference other classes, start additional threads, and create its user interface or other structures, as shown in Figure 3-1.

Starting a Java application
Figure 3-1. Starting a Java application

The main() method must have the right method signature. A method signature is the set of information that defines the method. It includes the method’s name, arguments, and return type, as well as type and visibility modifiers. The main() method must be a public, static method that takes an array of String objects as its argument and does not return any value (void):

    public static void main ( String [] myArgs )

The fact that main() is a public and static method simply means that it is globally accessible and that it can be called directly by name. We’ll discuss the implications of visibility modifiers such as public and the meaning of static in Chapters 4 through 6.

The main() method’s single argument, the array of String objects, holds the command-line arguments passed to the application. The name of the parameter doesn’t matter; only the type is important. In Java, the content of myArgs is an array. In Java, arrays know how many elements they contain and can happily provide that information:

    int numArgs = myArgs.length;

myArgs[0] is the first command-line argument, and so on.

The Java interpreter continues to run until the main() method of the initial class file returns and until any threads that it has started also exit. Special threads designated as daemon threads are automatically terminated when the rest of the application has completed.

System Properties

Although it is possible to read host environment variables from Java, it is discouraged for application configuration. Instead, Java allows any number of system property values to be passed to the application when the VM is started. System properties are simply name-value string pairs that are available to the application through the static System.getProperty() method. You can use these properties as a more structured and portable alternative to command-line arguments and environment variables for providing general configuration information to your application at startup. Each system property is passed to the interpreter on the command line using the -D option followed by name=value. For example:

    % java -Dstreet=sesame -Dscene=alley animals.birds.BigBird

The value of the street property is then accessible this way:

    String street = System.getProperty("street");

An application can get its configuration in myriad other ways, including via files or network configuration at runtime.

The Classpath

The concept of a path should be familiar to anyone who has worked on a DOS or Unix platform. It’s an environment variable that provides an application with a list of places to look for some resource. The most common example is a path for executable programs. In a Unix shell, the PATH environment variable is a colon-separated list of directories that are searched, in order, when the user types the name of a command. The Java CLASSPATH environment variable, similarly, is a list of locations that are searched for Java class files. Both the Java interpreter and the Java compiler use the CLASSPATH when searching for packages and Java classes.

An element of the classpath can be a directory or a JAR file. Java also supports archives in the conventional ZIP format, but JAR and ZIP are really the same format. JARs are simple archives that include extra files (metadata) that describe each archive’s contents. JAR files are created with the JDK’s jar utility; many tools for creating ZIP archives are publicly available and can be used to inspect or create JAR files as well. The archive format enables large groups of classes and their resources to be distributed in a single file; the Java runtime automatically extracts individual class files from the archive as needed.

The precise means and format for setting the classpath vary from system to system. On a Unix system (including Mac OS X), you set the CLASSPATH environment variable with a colon-separated list of directories and class archive files:

    %export CLASSPATH=/home/vicky/Java/classes:/home/josh/lib/foo.jar:.

This example specifies a classpath with three locations: a directory in the user’s home, a JAR file in another user’s directory, and the current directory, which is always specified with a dot (.). The last component of the classpath, the current directory, is useful when you are tinkering with classes.

On a Windows system, the CLASSPATH environment variable is set with a semicolon-separated list of directories and class archive files:

    C:\> set CLASSPATH=C:\home\vicky\Java\classes;C:\home\josh\lib\foo.jar;.

The Java launcher and the other command-line tools know how to find the core classes, which are the classes included in every Java installation. The classes in the java.lang,,, and javax.swing packages, for example, are all core classes so you do not need to include these classes in your classpath.

The classpath may also include “*” wildcards that match all JAR files within a directory. For example:

export CLASSPATH=/home/pat/libs/*

To find other classes, the Java interpreter searches the elements of the classpath in order. The search combines the path location and the components of the fully qualified class name. For example, consider a search for the class animals.birds.BigBird. Searching the classpath directory /usr/lib/java means the interpreter looks for an individual class file at /usr/lib/java/animals/birds/BigBird.class. Searching a ZIP or JAR archive on the classpath, say /home/vicky/myutils.jar, means that the interpreter looks for component file animals/birds/BigBird.class within that archive.

For the Java runtime, java, and the Java compiler, javac, the classpath can also be specified with the -classpath option:

    % javac -classpath /home/pat/classes:/utils/utils.jar:.

If you don’t specify the CLASSPATH environment variable or command-line option, the classpath defaults to the current directory (.); this means that the files in your current directory are normally available. If you change the classpath and don’t include the current directory, these files will no longer be accessible.

We suspect that about 80 percent of the problems that newcomers have when first learning Java are classpath-related. You may wish to pay particular attention to setting and checking the classpath when getting started. If you’re working inside an IDE, it may remove some or all of the burden of managing the classpath. Ultimately, however, understanding the classpath and knowing exactly what is in it when your application runs is very important to your long-term sanity. The javap command, discussed next, can be useful in debugging classpath issues.


A useful tool to know about is the javap command. With javap, you can print a description of a compiled class. You don’t need the source code, and you don’t even need to know exactly where it is, only that it is in your classpath. For example:

    % javap java.util.Stack

prints the information about the java.util.Stack class:

Compiled from ""
public class java.util.Stack<E> extends java.util.Vector<E> {
  public java.util.Stack();
  public E push(E);
  public synchronized E pop();
  public synchronized E peek();
  public boolean empty();
  public synchronized int search(java.lang.Object);

This is very useful if you don’t have other documentation handy and can also be helpful in debugging classpath problems. Using javap, you can determine whether a class is in the classpath and possibly even which version you are looking at (many classpath issues involve duplicate classes in the classpath). If you are really curious, you can try javap with the -c option, which causes it to also print the JVM instructions for each method in the class!

The Java Compiler

In this section, we’ll say a few words about javac, the Java compiler in the JDK. The javac compiler is written entirely in Java, so it’s available for any platform that supports the Java runtime system. javac turns Java source code into a compiled class that contains Java bytecode. By convention, source files are named with a .java extension; the resulting class files have a .class extension. Each source code file is considered a single compilation unit. As you’ll see in Chapter 6, classes in a given compilation unit share certain features, such as package and import statements.

javac allows one public class per file and insists that the file have the same name as the class. If the filename and class name don’t match, javac issues a compilation error. A single file can contain multiple classes, as long as only one of the classes is public and is named for the file. Avoid packing too many classes into a single source file. Packing classes together in a .java file only superficially associates them. In Chapter 6, we’ll talk about inner classes, classes that contain other classes and interfaces.

As an example, place the following source code in the file

    package animals.birds;

    public class BigBird extends Bird {

Next, compile it with:

    % javac

Unlike the Java interpreter, which takes just a class name as its argument, javac needs a filename (with the .java extension) to process. The previous command produces the class file BigBird.class in the same directory as the source file. While it’s nice to see the class file in the same directory as the source for this example, for most real applications, you need to store the class file in an appropriate place in the classpath.

You can use the -d option with javac to specify an alternative directory for storing the class files javac generates. The specified directory is used as the root of the class hierarchy, so .class files are placed in this directory or in a subdirectory below it, depending on whether the class is contained in a package. (The compiler creates intermediate subdirectories automatically, if necessary.) For example, we can use the following command to create the BigBird.class file at /home/vicky/Java/classes/animals/birds/BigBird.class:

    % javac -d /home/vicky/Java/classes

You can specify multiple .java files in a single javac command; the compiler creates a class file for each source file. But you don’t need to list the other classes your class references as long as they are in the classpath in either source or compiled form. During compilation, Java resolves all other class references using the classpath.

The Java compiler is more intelligent than your average compiler, replacing some of the functionality of a make utility. For example, javac compares the modification times of the source and class files for all classes and recompiles them as necessary. A compiled Java class remembers the source file from which it was compiled, and as long as the source file is available, javac can recompile it if necessary. If, in the previous example, class BigBird references another class, animals.furry.Grover, javac looks for the source file in an animals.furry package and recompiles it if necessary to bring the Grover.class class file up-to-date.

By default, however, javac checks only source files that are referenced directly from other source files. This means that if you have an out-of-date class file that is referenced only by an up-to-date class file, it may not be noticed and recompiled. For that and many other reasons, most projects use a real build utility such as Apache’s Ant to manage builds, packaging, and more. We discuss Ant in Chapter 15.

Finally, it’s important to note that javac can compile an application even if only the compiled (binary) versions of some of the classes are available. You don’t need source code for all your objects. Java class files contain all the data type and method signature information that source files contain, so compiling against binary class files is as typesafe (and exception safe) as compiling with Java source code.

JAR Files

Java Archive (JAR) files are Java’s suitcases. They are the standard and portable way to pack up all the parts of your Java application into a compact bundle for distribution or installation. You can put whatever you want into a JAR file: Java class files, serialized objects, data files, images, audio, etc. A JAR file can also carry one or more digital signatures that attest to its integrity and authenticity. A signature can be attached to the file as a whole or to individual items in the file.

The Java runtime system can load class files directly from an archive in your CLASSPATH, as described earlier. Nonclass files (data, images, etc.) contained in your JAR file can also be retrieved from the classpath by your application using the getResource() method (described in Chapter 12). Using this facility, your code doesn’t have to know whether any resource is in a plain file or a member of a JAR archive. Whether a given class or data file is an item in a JAR file or an individual file on the classpath, you can always refer to it in a standard way and let Java’s class loader resolve the location.

File Compression

Items stored in JAR files are compressed with the standard ZIP file compression. Compression makes downloading classes over a network much faster. A quick survey of the standard Java distribution shows that a typical class file shrinks by about 40 percent when it is compressed. Text files such as HTML or ASCII containing English words often compress to one-tenth their original size or less. (On the other hand, image files don’t normally get smaller when compressed as most common image formats are themselves a compression format.)

Java also has an archive format called Pack200, which is optimized specifically for Java class bytecode and can achieve over four times greater compression of Java classes than ZIP alone. We’ll talk about Pack200 later in this chapter.

The jar Utility

The jar utility provided with the JDK is a simple tool for creating and reading JAR files. Its user interface isn’t particularly friendly. It mimics the Unix tar (tape archive) command. If you’re familiar with tar, you’ll recognize the following incantations:

jar -cvf jarFile path [ path ] [ ... ]

Create jarFile containing path(s).

jar -tvf jarFile [ path ] [ ... ]

List the contents of jarFile, optionally showing just path(s).

jar -xvf jarFile [ path ] [ ... ]

Extract the contents of jarFile, optionally extracting just path(s).

In these commands, the flag letters c, t, and x tell jar whether it is creating an archive, listing an archive’s contents, or extracting files from an archive. The f means that the next argument is the name of the JAR file on which to operate. The optional v flag tells jar to be verbose when displaying information about files. In verbose mode, you get information about file sizes, modification times, and compression ratios.

Subsequent items on the command line (i.e., anything aside from the letters telling jar what to do and the file on which jar should operate) are taken as names of archive items. If you’re creating an archive, the files and directories you list are placed in it. If you’re extracting, only the filenames you list are extracted from the archive. (If you don’t list any files, jar extracts everything in the archive.)

For example, let’s say we have just completed our new game, spaceblaster. All the files associated with the game are in three directories. The Java classes themselves are in the spaceblaster/game directory, spaceblaster/images contains the game’s images, and spaceblaster/docs contains associated game data. We can pack all this in an archive with this command:

    % jar -cvf spaceblaster.jar spaceblaster

Because we requested verbose output, jar tells us what it is doing:

    adding:spaceblaster/ (in=0) (out=0) (stored 0%)
    adding:spaceblaster/game/ (in=0) (out=0) (stored 0%)
    adding:spaceblaster/game/Game.class (in=8035) (out=3936) (deflated 51%)
    adding:spaceblaster/game/Planetoid.class (in=6254) (out=3288) (deflated 47%)
    adding:spaceblaster/game/SpaceShip.class (in=2295) (out=1280) (deflated 44%)
    adding:spaceblaster/images/ (in=0) (out=0) (stored 0%)
    adding:spaceblaster/images/spaceship.gif (in=6174) (out=5936) (deflated 3%)
    adding:spaceblaster/images/planetoid.gif (in=23444) (out=23454) (deflated 0%)
    adding:spaceblaster/docs/ (in=0) (out=0) (stored 0%)
    adding:spaceblaster/docs/help1.html (in=3592) (out=1545) (deflated 56%)
    adding:spaceblaster/docs/help2.html (in=3148) (out=1535) (deflated 51%)

jar creates the file spaceblaster.jar and adds the directory spaceblaster, adding the directories and files within spaceblaster to the archive. In verbose mode, jar reports the savings gained by compressing the files in the archive.

We can unpack the archive with this command:

    % jar -xvf spaceblaster.jar

Likewise, we can extract an individual file or directory with:

    % jar -xvf spaceblaster.jar filename

But, of course, you normally don’t have to unpack a JAR file to use its contents; Java tools know how to extract files from archives automatically. We can list the contents of our JAR with the command:

    % jar -tvf spaceblaster.jar

Here’s the output; it lists all the files, their sizes, and their creation times:

    0 Thu May 15 12:18:54 PDT 2003 META-INF/
      1074 Thu May 15 12:18:54 PDT 2003 META-INF/MANIFEST.MF
         0 Thu May 15 12:09:24 PDT 2003 spaceblaster/
         0 Thu May 15 11:59:32 PDT 2003 spaceblaster/game/
      8035 Thu May 15 12:14:08 PDT 2003 spaceblaster/game/Game.class
      6254 Thu May 15 12:15:18 PDT 2003 spaceblaster/game/Planetoid.class
      2295 Thu May 15 12:15:26 PDT 2003 spaceblaster/game/SpaceShip.class
         0 Thu May 15 12:17:00 PDT 2003 spaceblaster/images/
      6174 Thu May 15 12:16:54 PDT 2003 spaceblaster/images/spaceship.gif
     23444 Thu May 15 12:16:58 PDT 2003 spaceblaster/images/planetoid.gif
         0 Thu May 15 12:10:02 PDT 2003 spaceblaster/docs/
      3592 Thu May 15 12:10:16 PDT 2003 spaceblaster/docs/help1.html
      3148 Thu May 15 12:10:02 PDT 2003 spaceblaster/docs/help2.html

JAR manifests

Note that the jar command automatically adds a directory called META-INF to our archive. The META-INF directory holds files describing the contents of the JAR file. It always contains at least one file: MANIFEST.MF. The MANIFEST.MF file can contain a “packing list” naming the files in the archive along with a user-definable set of attributes for each entry.

The manifest is a text file containing a set of lines in the form keyword: value. The manifest is, by default, empty and contains only JAR file version information:

Manifest-Version: 1.0
Created-By: 1.7.0_07 (Oracle Corporation)

It is also possible to sign JAR files with a digital signature. When you do this, digest (checksum) information is added to the manifest for each archived item (as shown next) and the META-INF directory holds digital signature files for items in the archive.

    Name: com/oreilly/Test.class
    SHA1-Digest: dF2GZt8G11dXY2p4olzzIc5RjP3=

You can add your own information to the manifest descriptions by specifying your own supplemental, manifest file when you create the archive. This is one possible place to store other simple kinds of attribute information about the files in the archive, perhaps version or authorship information.

For example, we can create a file with the following keyword: value lines:

    Name: spaceblaster/images/planetoid.gif
    RevisionNumber: 42.7
    Artist-Temperament: moody

To add this information to the manifest in our archive, place it in a file called and give the following jar command:

    % jar -cvmf spaceblaster.jar spaceblaster

We included an additional option, m, which specifies that jar should read additional manifest information from the file given on the command line. How does jar know which file is which? Because m is before f, it expects to find the manifest information before the name of the JAR file it will create. If you think that’s awkward, you’re right; get the names in the wrong order, and jar does the wrong thing.

An application can get this manifest information from a JAR file using the java.util.jar.Manifest class.

We’ll see more examples of adding information to the JAR manifest in Chapter 22. The JavaBeans APIs use manifest information to designate which classes are “beans” using a Java-Bean attribute. This information is used by IDEs that work with JavaBeans.

Making a JAR file runnable

Aside from attributes, you can put a few special values in the manifest file. One of these, Main-Class, allows you to specify the class containing the primary main() method for an application contained in the JAR:

    Main-Class: com.oreilly.Game

If you add this to your JAR file manifest (using the m option described earlier), you can run the application directly from the JAR:

    % java -jar spaceblaster.jar

More importantly, under Mac OS X, Windows, and other GUI environments, you can simply double-click on the JAR file to launch the application. The interpreter looks for the Main-Class value in the manifest, then loads the designated class as the application’s startup class.

The pack200 Utility

Pack200 is an archive format that is optimized for storing compiled Java class files. Pack200 is not a new form of compression, but rather a super-efficient layout for class information that eliminates many types of waste and redundancy across related classes. It is effectively a bulk class-file format that deconstructs many classes and reassembles their parts efficiently into one catalog. This then allows a standard compression format like ZIP to work at maximum efficiency on the archive, achieving four or more times greater compression. The Java runtime does not understand the Pack200 format, so you cannot place archives of this type into the classpath. Instead, it is mainly an intermediate format that is very useful for transferring application JARs over the network for applets or other kinds of web-based applications.

You can convert a JAR to and from Pack200 format with the pack200 and unpack200 commands supplied with the JDK.

For example, to convert foo.jar to foo.pack.gz, use the pack200 command:

    % pack200 foo.pack.gz foo.jar

To convert foo.pack.gz to foo.jar:

    % unpack200 foo.pack.gz foo.jar

Note that the Pack200 process completely tears down and reconstructs your classes at the class level, so the resulting foo.jar file will not be byte-for-byte the same as the original.

Policy Files

One of the truly novel things about Java is that security is built into the language. As described in Chapter 1, the Java VM can verify class files and Java’s security manager can impose limits on what classes do. In early versions of Java, it was necessary to implement security policies programmatically by writing a Java security manager class and using it in your application. Later, a declarative security system was added. This system allows you to write policy files—text-based descriptions of permissions—which are much simpler and don’t require code changes. These policy files tell the security manager what to allow and disallow and for whom.

In early versions of Java, much of the buzz had to do with the security of applets. Applets that were downloaded from untrusted locations could be run with security restrictions that prevented them from doing questionable things such as reading from or writing to the disk or contacting arbitrary computers on the network. With security policy files, it’s easy to apply applet-style security to any application without modifying it. Furthermore, it’s easy to fine-tune the access you grant. For example, you can allow an application to access only a specific directory on the disk, or you can allow network access to certain addresses.

Understanding security and security policies can be important, so we’ll cover it here. However, in practice, you probably won’t use this facility yourself, unless you are writing a framework for running applications from many unknown sources or need to restrict an application for some other reason.

The Default Security Manager

By default, no security manager is installed when you launch a Java application locally. You can turn on security using an option of the java interpreter to install a default security manager. The default security policy enforces many of the same rules as for applets. To see how this works, let’s write a little program that does something questionable: it makes a network connection to some computer on the Internet. (We cover the specifics of network programming in Chapters 13 and 14.)


    public class EvilEmpire {
      public static void main(String[] args) throws Exception{
        try {
          Socket s = new Socket("", 80);
        catch (SecurityException e) {
          System.out.println("SecurityException: could not connect.");

If you run this program with the Java interpreter, it makes the network connection:

    C:\> java EvilEmpire

But because this program is “evil,” let’s install the default security manager, like this:

    C:\> java EvilEmpire
    SecurityException: could not connect.

That’s better, but suppose that the application actually has a legitimate reason to make its network connection. We’d like to leave the default security manager in place, just to be safe, but we’d like to grant this application permission to make a network connection.

The policytool Utility

To permit our EvilEmpire example to make a network connection, we need to create a policy file that contains the appropriate permission. A handy utility called policytool, included with the JDK, helps make policy files. Fire it up from a command line like this:

    C:\> policytool

You may get an error message when policytool starts up about not finding a default policy file. Don’t worry about this; just click OK to make the message go away.

We now add a network permission for the EvilEmpire application. The application is identified by its origin, also called a codebase, described by a URL. In this case, it is a file: URL that points to the location of the EvilEmpire application on your disk.

If you started up policytool, you should see its main window, shown in Figure 3-2. Click on Add Policy Entry. Another window pops up, like the one shown in Figure 3-3 (but with the fields empty).

The Policy Tool window
Figure 3-2. The Policy Tool window
Adding a policy entry
Figure 3-3. Adding a policy entry

First, fill in the codebase with the URL of the directory containing EvilEmpire. Then click on Add Permission. Yet another window pops up as shown in Figure 3-4.

Choose SocketPermission from the first combo box. Then fill out the second text field on the right side with the network address that EvilEmpire will connect to. Finally, choose Connect from the third combo box. Click on OK; you should see the new permission in the policy entry window, as shown in Figure 3-3.

Creating a new permission
Figure 3-4. Creating a new permission

Click on Done to finish creating the policy. Then choose Save As from the File menu and save the policy file as something memorable, such as EvilEmpire.policy. You can quit policytool now; we’re all done with it.

The policy file you just created is not complicated. Take a look at it with a text editor, which shows the simple syntax of the policy we created:

    grant codeBase "file:/c:/Projects/Exploring/" {
      permission "", "connect";

You can eschew policytool entirely and just create policy files with a text editor if you’re more comfortable that way.

Using a Policy File with the Default Security Manager

Now that we’ve gone to the trouble of creating a policy file, let’s use it. You can tell the default security manager to use the policy file with another command-line option to the java interpreter:

    C:\> java 

EvilEmpire can now make its socket connection because we have explicitly granted it permission with a policy file. The default security manager still protects us in other ways, however. EvilEmpire cannot write or read files on the disk except in the directory it came from, and it cannot make connections to any other network addresses except the one we specified. Take a moment and bask in this warm fuzzy feeling.