Page 2 of 6
public interface Application {
public void main(String args[]);
}
If the above interface was defined, and classes implemented it, then at least you could use the instanceof operator in Java to determine if you had an application or not and thus determine whether or not it was suitable for invoking
from the command line. The bottom line is that you can't (define the interface), it wasn't (built into the Java interpreter),
and so you can't (determine if a class file is an application easily). So what can you do?
Actually, you can do quite a bit if you know what to look for and how to use it.
The Java class file is architecture-neutral, which means it is the same set of bits whether it is loaded from a Windows 95 machine or a Sun Solaris machine. It is also very well documented in the book The Java Virtual Machine Specification by Lindholm and Yellin. The class file structure was designed, in part, to be easily loaded into the SPARC address space. Basically, the class file could be mapped into the virtual address space, then the relative pointers inside the class fixed up, and presto! You had instant class structure. This was less useful on the Intel architecture machines, but the heritage left the class file format easy to comprehend, and even easier to break down.
In the summer of 1994, I was working in the Java group and building what is known as a "least privilege" security model for Java. I had just finished figuring out that what I really wanted to do was to look inside a Java class, excise those pieces that were not allowed by the current privilege level, and then load the result through a custom class loader. It was then that I discovered there weren't any classes in the main run time that knew about the construction of class files. There were versions in the compiler class tree (which had to generate class files from the compiled code), but I was more interested in building something for manipulating pre-existing class files.
I started by building a Java class that could decompose a Java class file that was presented to it on an input stream. I gave
it the less-than-original name ClassFile. The beginning of this class is shown below.
public class ClassFile {
int magic;
short majorVersion;
short minorVersion;
ConstantPoolInfo constantPool[];
short accessFlags;
ConstantPoolInfo thisClass;
ConstantPoolInfo superClass;
ConstantPoolInfo interfaces[];
FieldInfo fields[];
MethodInfo methods[];
AttributeInfo attributes[];
boolean isValidClass = false;
public static final int ACC_PUBLIC = 0x1;
public static final int ACC_PRIVATE = 0x2;
public static final int ACC_PROTECTED = 0x4;
public static final int ACC_STATIC = 0x8;
public static final int ACC_FINAL = 0x10;
public static final int ACC_SYNCHRONIZED = 0x20;
public static final int ACC_THREADSAFE = 0x40;
public static final int ACC_TRANSIENT = 0x80;
public static final int ACC_NATIVE = 0x100;
public static final int ACC_INTERFACE = 0x200;
public static final int ACC_ABSTRACT = 0x400;
As you can see, the instance variables for class ClassFile define the major components of a Java class file. In particular, the central data structure for a Java class file is known
as the constant pool. Other interesting chunks of class file get classes of their own: MethodInfo for methods, FieldInfo for fields (which are the variable declarations in the class), AttributeInfo to hold class file attributes, and a set of constants that was taken directly from the specification on class files to decode
the various modifiers that apply to field, method, and class declarations.