the java class file lifestyle

Upload: mudit-khetan

Post on 10-Apr-2018

239 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/8/2019 The Java Class File Lifestyle

    1/32

    The Java class file lifestyle

    An introduction to the basic structure and lifestyle of the Java class file

    By Bill Venners, JavaWorld.com, 07/01/96

    Welcome to another installment of "Under the Hood." In last month's article I discussedthe Java Virtual Machine, or JVM, the abstract computer for which all Java programs are

    compiled. If you are unfamiliar with the JVM, you may want to read last month's article

    before this one. In this article I provide a glimpse into the basic structure and lifestyle of

    the Java class file.

    Born to travel

    The Java class file is a precisely defined format for compiled Java. Java source code is

    compiled into class files that can be loaded and executed by any JVM. The class files

    may travel across a network before being loaded by the JVM.

    In fact, if you are reading this article via a Java-capable browser, class files for the

    simulation applet at the end of the article are flying across the Internet to your computer

    right now. If you'd like to listen in on them (and your computer has audio capability),push the following button:

    Sounds like they're having fun, huh? That's in their nature. Java class files were designedto travel well. They are platform-independent, so they will be welcome in more places.

    They contain bytecodes, the compact instruction set for the JVM, so they can travel light.

    Java class files are constantly zipping through networks at breakneck speed to arrive at

    JVMs all over the world.

    What's in a class file?

    The Java class file contains everything a JVM needs to know about one Java class or

    interface. In their order of appearance in the class file, the major components are:

    http://www.javaworld.com/javaworld/jw-06-1996/jw-06-vm.htmlhttp://www.javaworld.com/javaworld/jw-06-1996/jw-06-vm.html
  • 8/8/2019 The Java Class File Lifestyle

    2/32

    magic, version, constant pool, access flags, this class, super class, interfaces, fields,

    methods, and attributes.

    Information stored in the class file often varies in length -- that is, the actual length of theinformation cannot be predicted before loading the class file. For instance, the number of

    methods listed in the methods component can differ among class files, because it dependson the number of methods defined in the source code. Such information is organized in

    the class file by prefacing the actual information by its size or length. This way, when theclass is being loaded by the JVM, the size of variable-length information is read first.

    Once the JVM knows the size, it can correctly read in the actual information.

    Information is generally written to the class file with no space or padding betweenconsecutive pieces of information; everything is aligned on byte boundaries. This helps

    keeps class files petite so they will be aerodynamic as they fly across networks.

    The order of class file components is strictly defined so JVMs can know what to expect,

    and where to expect it, when loading a class file. For example, every JVM knows that thefirst eight bytes of a class file contain the magic and version numbers, that the constant

    pool starts on the ninth byte, and that the access flags follow the constant pool. But

    because the constant pool is variable-length, it doesn't know the exact whereabouts of theaccess flags until it has finished reading in the constant pool. Once it has finished reading

    in the constant pool, it knows the next two bytes will be the access flags.

    Magic and version numbers

    The first four bytes of every class file are always 0xCAFEBABE. This magic number

    makes Java class files easier to identify, because the odds are slim that non-class fileswould start with the same initial four bytes. The number is called magic because it can be

    pulled out of a hat by the file format designers. The only requirement is that it is not

    already being used by another file format that may be encountered in the real world.According to Patrick Naughton, a key member of the original Java team, the magic

    number was chosen "long before the name Java was ever uttered in reference to this

    language. We were looking for something fun, unique, and easy to remember. It is only acoincidence that OxCAFEBABE, an oblique reference to the cute baristas at Peet's

    Coffee, was foreshadowing for the name Java."

    The second four bytes of the class file contain the major and minor version numbers.

    These numbers identify the version of the class file format to which a particular class file

  • 8/8/2019 The Java Class File Lifestyle

    3/32

    adheres and allow JVMs to verify that the class file is loadable. Every JVM has a

    maximum version it can load, and JVMs will reject class files with later versions.

    Constant pool

    The class file stores constants associated with its class or interface in the constant pool.Some constants that may be seen frolicking in the pool are literal strings, final variable

    values, class names, interface names, variable names and types, and method names and

    signatures. A methodsignature is its return type and set of argument types.

    The constant pool is organized as an array of variable-length elements. Each constantoccupies one element in the array. Throughout the class file, constants are referred to by

    the integer index that indicates their position in the array. The initial constant has anindex of one, the second constant has an index of two, etc. The constant pool array ispreceded by its array size, so JVMs will know how many constants to expect when

    loading the class file.

    Each element of the constant pool starts with a one-byte tag specifying the type of

    constant at that position in the array. Once a JVM grabs and interprets this tag, it knowswhat follows the tag. For example, if a tag indicates the constant is a string, the

    JVM expects the next two bytes to be the string length. Following this two-byte length,

    the JVM expects to find length number of bytes, which make up the characters of thestring.

    In the remainder of the article I'll sometimes refer to the nth element of the constant pool

    array as constant_pool[n]. This makes sense to the extent the constant pool is organizedlike an array, but bear in mind that these elements have different sizes and types and that

    the first element has an index of one.

    Access flags

    The first two bytes after the constant pool, the access flags, indicate whether or not this

    file defines a class or an interface, whether the class or interface is public or abstract, and

    (if it's a class and not an interface) whether the class is final.

  • 8/8/2019 The Java Class File Lifestyle

    4/32

    This class

    The next two bytes, the this class component, are an index into the constant pool array.

    The constant referred to by this class, constant_pool[this_class], has two parts, a one-byte

    tag and a two-byte name index. The tag will equal CONSTANT_Class, a value that

    indicates this element contains information about a class or interface.Constant_pool[name_index] is a string constant containing the name of the class or

    interface.

    The this class component provides a glimpse of how the constant pool is used. This classitself is just an index into the constant pool. When a JVM looks up

    constant_pool[this_class], it finds an element that identifies itself as a

    CONSTANT_Class with its tag. The JVM knows CONSTANT_Class elements alwayshave a two-byte index into the constant pool, called name index, following their one-byte

    tag. So it looks up constant_pool[name_index] to get the string containing the name ofthe class or interface.

    Super class

    Following the this class component is thesuper class component, another two-byte index

    into the constant pool. Constant_pool[super_class] is a CONSTANT_Class element thatpoints to the name of the super class from which this class descends.

    Interfaces

    The interfaces component starts with a two-byte count of the number of interfaces

    implemented by the class (or interface) defined in the file. Immediately following is an

    array that contains one index into the constant pool for each interface implemented by theclass. Each interface is represented by a CONSTANT_Class element in the constant pool

    that points to the name of the interface.

    Fields

    The fields component starts with a two-byte count of the number of fields in this class or

    interface. A field is an instance or class variable of the class or interface. Following thecount is an array of variable-length structures, one for each field. Each structure reveals

    information about one field such as the field's name, type, and, if it is a final variable, its

  • 8/8/2019 The Java Class File Lifestyle

    5/32

    constant value. Some information is contained in the structure itself, and some is

    contained in constant pool locations pointed to by the structure.

    The only fields that appear in the list are those that were declared by the class or interfacedefined in the file; no fields inherited from super classes or superinterfaces appear in the

    list.

    Methods

    The methods component starts with a two-byte count of the number of methods in the

    class or interface. This count includes only those methods that are explicitly defined bythis class, not any methods that may be inherited from superclasses. Following the

    method count are the methods themselves.

    The structure for each method contains several pieces of information about the method,including the method descriptor (its return type and argument list), the number of stack

    words required for the method's local variables, the maximum number of stack words

    required for the method's operand stack, a table of exceptions caught by the method, the

    bytecode sequence, and a line number table.

    Attributes

    Bringing up the rear are the attributes, which give general information about theparticular class or interface defined by the file. The attributes section has a two-byte

    count of the number of attributes, followed by the attributes themselves. For example,

    one attribute is the source code attribute; it reveals the name of the source file from whichthis class file was compiled. JVMs will silently ignore any attributes they don't recognize.

    Getting loaded: a simulation of a class file reaching its JVM destination

    The applet below simulates a JVM loading a class file. The class file being loaded in the

    simulation was generated by the javac compiler given the following Java source code:

    class Act {

  • 8/8/2019 The Java Class File Lifestyle

    6/32

    public static void doMathForever() {int i = 0;while (true) {

    i += 1;i *= 2;

    }}

    }

    The above snippet of code comes from last month's article about the JVM. It is the same

    doMathForever() method executed by the EternalMath applet from last month's article. I

    chose this code to provide a real example that wasn't too complex. Although the codemay not be very useful in the real world, it does compile to a real class file, which is

    loaded by the simulation below.

    The GettingLoaded applet allows you to drive the class load simulation one step at atime. For each step along the way you can read about the next chunk of bytes that is

    about to be consumed and interpreted by the JVM. Just press the "Step" button to cause

    the JVM to consume the next chunk. Pressing "Back" will undo the previous step, and

    pressing "Reset" will return the simulation to its original state, allowing you to start overfrom the beginning.

    The JVM is shown at the bottom left consuming the stream of bytes that makes up the

    class file Act.class. The bytes are shown in hex streaming out of a server on the bottom

    right. The bytes travel right to left, between the server and the JVM, one chunk at a time.The chunk of bytes to be consumed by the JVM on the next "Step" button press are

    shown in red. These highlighted bytes are described in the large text area above the JVM.Any remaining bytes beyond the next chunk are shown in black.

    I've tried to fully explain each chunk of bytes in the text area. There is a lot of detail,

    therefore, in the text area and you may wish to skim through all the steps first to get the

    general idea, then look back for more details.

    Source Code/********************************************************************

    Copyright (c) 1996 Artima Software Company. All Rights Reserved.

    PROJECT: JavaWorldMODULE: Under The HoodFILE: GettingLoaded.java

  • 8/8/2019 The Java Class File Lifestyle

    7/32

    AUTHOR: Bill Venners, June 1996

    DESCRIPTION:

    This file contains all the code for the Java class load simulator thataccompanies the Under The Hood article titled, "The Java Class FileLifestyle".I developed this under Symantec Cafe on Windows 95. As I developed it Ihadeach class in its own file, which made for very speedy compile and testcycles. I lumped all the files together into this file to make it easierto download.

    This applet retrieves two files from the server, the Act.class fileitself,from which it gets the bytes to display along the bottom, and a textfilewhich contains the text that accompanies each step. Each block of textisseparated by a line of stars which contains one star for each byte

    consumedby the step.

    *********************************************************************/

    import java.awt.*;import java.applet.*;import java.io.InputStream;import java.io.DataInputStream;import java.io.BufferedInputStream;import java.io.IOException;import java.io.EOFException;import java.net.URL;import java.net.URLConnection;import java.net.MalformedURLException;

    public class GettingLoaded extends Appletimplements Runnable {

    private URL theClassFileURL;private URL theActTextURL;private Thread runner;private TextArea ta = new TextArea();private StepNode firstNode;private StepNode lastNode;private StepNode currentNode;private boolean ready = false;

    private boolean jvmFinishedGobbling = false;private int currentGobblePosition = 0;private JVMPacman jvmPacman;private String titleString = "Getting Loaded\n\n";private boolean urlExceptionWasThrown = false;private String cantGoFurtherString = "Unfortunately this means the

    applet cannot go any further.\n";private String ioErrorMsg = "An IO Error occured while trying to

    read a file from the server.\n";

  • 8/8/2019 The Java Class File Lifestyle

    8/32

    private String securityErrorMsg = "An security exception occuredwhile trying to read a file from the server.\n";

    private String urlErrorMsg = "This HTML file contains a malformedURL of a file required by this applet.\n";

    public void init() {

    super.init();

    ta.setEditable(false);

    setBackground(Color.blue);

    String url = getParameter("classURL");try { this.theClassFileURL = new URL(url); }catch (MalformedURLException e) {

    urlExceptionWasThrown = true;ta.setText(titleString + "Bad URL: " + url + "\n\n" +

    urlErrorMsg + cantGoFurtherString);}

    url = getParameter("textURL");try { this.theActTextURL = new URL(url); }catch (MalformedURLException e) {

    urlExceptionWasThrown = true;ta.setText(titleString + "Bad URL: " + url + "\n\n" +

    urlErrorMsg + cantGoFurtherString);}ControlPanel controlPanel = new ControlPanel();jvmPacman = controlPanel.getJVMPacman();setLayout(new BorderLayout(5, 5));

    ta.setBackground(Color.white);

    add("North", new ColoredLabel("GETTING LOADED", Label.CENTER,Color.cyan));

    add("South", controlPanel);add("Center", ta);

    }

    public boolean handleEvent(Event event) {return super.handleEvent(event);

    }

    public boolean action(Event evt, Object arg) {if (evt.target instanceof Button) {

    String bname = (String) arg;if (bname.equals("Reset")) {

    if (ready) {if (!currentNode.first()) {

    currentNode = firstNode;currentGobblePosition = 0;jvmPacman.setGobblePosition(0,

    currentNode.getByteCount());ta.setText(currentNode.getString());

    }}

    }

  • 8/8/2019 The Java Class File Lifestyle

    9/32

    else if (bname.equals("Step")) {if (ready) {

    if (!currentNode.last()) {currentGobblePosition +=

    currentNode.getByteCount();currentNode = currentNode.getNext();jvmPacman.gobbleToPosition(currentGobblePositio

    n, currentNode.getByteCount());ta.setText(currentNode.getString());

    }else {

    if (!jvmFinishedGobbling) {currentGobblePosition +=

    currentNode.getByteCount();jvmPacman.gobbleToPosition(currentGobblePos

    ition, 0);jvmFinishedGobbling = true;ta.setText("(The End)");

    }}

    }}else if (bname.equals("Back")) {

    if (ready) {if (!currentNode.first()) {

    if (jvmFinishedGobbling) {jvmFinishedGobbling = false;currentGobblePosition -=

    currentNode.getByteCount();}else {

    currentNode = currentNode.getPrev();currentGobblePosition -=

    currentNode.getByteCount();}jvmPacman.setGobblePosition(currentGobblePositi

    on, currentNode.getByteCount());ta.setText(currentNode.getString());

    }}

    }}return true;

    }

    public Insets insets() {return new Insets(5, 5, 5, 5);

    }

    public void start() {if (runner == null && !ready && !urlExceptionWasThrown) {

    runner = new Thread (this);runner.start();

    }}

    public void stop() {

  • 8/8/2019 The Java Class File Lifestyle

    10/32

    if (runner != null) {runner.stop();runner = null;

    }}

    public void run() {InputStream conn = null;DataInputStream data = null;String line;StringBuffer buf = new StringBuffer();

    ta.setText(titleString + "Loading First Of Two Files...\n");

    try {conn = this.theClassFileURL.openStream();data = new DataInputStream(new BufferedInputStream(conn));

    try {while (true) {

    int unsignedByte = data.readUnsignedByte();HexString hexStr = new HexString(unsignedByte, 2);buf.append(hexStr.getString());

    }}catch (EOFException e) {

    jvmPacman.setText(buf.toString());}try {

    ta.setText(titleString + "Loading Second Of TwoFiles...\n");

    conn = this.theActTextURL.openStream();data = new DataInputStream(new

    BufferedInputStream(conn));buf.setLength(0);

    while ((line = data.readLine()) != null) {if (line.length() > 0 && line.charAt(0) == '*') {

    int starCount = line.length();StepNode nextNode = new

    StepNode(buf.toString(), starCount);if (firstNode == null) {

    firstNode = nextNode;lastNode = nextNode;

    }else {

    lastNode.setNext(nextNode);

    nextNode.setPrev(lastNode);lastNode = nextNode;

    }buf.setLength(0);

    }else {

    buf.append(line + "\n");}

    }ready = true;

  • 8/8/2019 The Java Class File Lifestyle

    11/32

    currentNode = firstNode;jvmPacman.setGobblePosition(0,

    firstNode.getByteCount());ta.setText(currentNode.getString());

    }catch (IOException e) {

    ta.setText(titleString + "IO Error: " + e.getMessage()+ "\n\n"

    + ioErrorMsg + cantGoFurtherString);}catch (SecurityException e) {

    ta.setText(titleString + "Security Exception: " +e.getMessage() + "\n\n"

    + securityErrorMsg + cantGoFurtherString);}

    }catch (IOException e) {

    ta.setText(titleString + "IO Error: " + e.getMessage() +"\n\n"

    + ioErrorMsg + cantGoFurtherString);

    }catch (SecurityException e) {

    ta.setText(titleString + "Security Exception: " +e.getMessage() + "\n\n"

    + securityErrorMsg + cantGoFurtherString);}

    }}

    class ButtonPanel extends Panel {

    ButtonPanel() {setLayout(new GridLayout(3, 1, 5, 5));setBackground(Color.blue);Button b = new Button("Step");b.setBackground(Color.lightGray);add(b);b = new Button("Back");b.setBackground(Color.lightGray);add(b);b = new Button("Reset");b.setBackground(Color.lightGray);add(b);

    }

    public Insets insets() {// top, left, bottom, right

    return new Insets(0, 0, 0, 0);}

    }

    // The string passed to the constructor and to addText must be one lineto// be printed out, excluding a closing return.class JVMPacman extends Canvas {

    private String theString;

  • 8/8/2019 The Java Class File Lifestyle

    12/32

    private boolean stringValid = false;private int currentGobblePosition;private int interestingCharsCount;private int charsThatFitBetweenRectanglesCount = 2;

    JVMPacman() {setBackground(Color.cyan);

    }

    void setText(String passedText) {

    theString = passedText;stringValid = true;

    }

    public Dimension minimumSize() {return new Dimension(110, 60);

    }public Dimension preferredSize() {

    return new Dimension(110, 60);

    }

    public void setGobblePosition(int pos, int interesting) {// Multiply the passed position by two because the passed

    position represents// a byte position whereas we want currentGobblePosition to

    represent a// character position, and there are two hex characters for

    each byte.currentGobblePosition = pos * 2;interestingCharsCount = interesting * 2;repaint();

    }

    public void gobbleToPosition(int pos, int interesting) {currentGobblePosition = pos * 2;interestingCharsCount = interesting * 2;repaint();

    }

    public void paint(Graphics g) {

    Font font = getFont();FontMetrics fm = getFontMetrics(font);int heightOfOneLine = fm.getHeight();

    // Calculate x starting point

    Dimension dim = new Dimension();

    dim = size();

    int xStartingPoint = 5;

    // Calculate y starting pointint totalHeight = heightOfOneLine * 2;int yStartingPoint = (dim.height - totalHeight) / 2;if (yStartingPoint < 5) {

  • 8/8/2019 The Java Class File Lifestyle

    13/32

    yStartingPoint = 5;}

    // Calculate width of JVM rectangle. This will beheightOfOneLine more than

    // the stringWidth of "JVM" which I'll write in the middle ofthe rectangle.

    // This will make the border around the "JVM" the same widthand height on

    // all sides and will equal heightOfOneLine / 2. I'll make theheight of the

    // rectangle heightOfOneLine *2.int jvmRectangleWidth = fm.stringWidth("JVM") + heightOfOneLine;

    // Draw the filled rectangleg.setColor(Color.green);g.fillRoundRect(xStartingPoint, yStartingPoint,

    jvmRectangleWidth, totalHeight,5, 5);

    // Give it a handsome black outlineg.setColor(Color.black);g.drawRoundRect(xStartingPoint, yStartingPoint,

    jvmRectangleWidth, totalHeight,5, 5);

    // Calculate width of Server rectangle. This will beheightOfOneLine more than

    // the stringWidth of "Server" which I'll write in the middleof the rectangle.

    // This will make the border around the "Server" the same widthand height on

    // all sides and will equal heightOfOneLine / 2. I'll make theheight of the

    // rectangle heightOfOneLine *2.int serverRectangleWidth = fm.stringWidth("Server") +

    heightOfOneLine;

    // Draw the filled rectangle. The x starting point is the widthof the

    // canvas minus the width of the server rectangle minus the 5pixel margin.

    int xStartingPointServerRect = dim.width - serverRectangleWidth- 5;

    g.setColor(Color.green);g.fillRoundRect(xStartingPointServerRect, yStartingPoint,

    serverRectangleWidth, totalHeight, 5, 5);

    // Give this rectangle a handsome black outlineg.setColor(Color.black);g.drawRoundRect(xStartingPointServerRect, yStartingPoint,

    serverRectangleWidth, totalHeight, 5, 5);

    int whiteRectangleWidth = xStartingPointServerRect -jvmRectangleWidth - 5;

    if (whiteRectangleWidth > 0) {

  • 8/8/2019 The Java Class File Lifestyle

    14/32

    g.setColor(Color.white);g.fillRect(jvmRectangleWidth + 5, yStartingPoint +

    (heightOfOneLine / 2),whiteRectangleWidth, heightOfOneLine);

    }

    // Draw "JVM" inside the rectangleg.setColor(Color.black);xStartingPoint += (heightOfOneLine / 2);int ascent = fm.getAscent();yStartingPoint += ascent + (heightOfOneLine / 2);g.drawString("JVM", xStartingPoint, yStartingPoint);

    // Draw "Server" inside the rectangleint xStartingPointServerText = xStartingPointServerRect +

    (heightOfOneLine / 2);g.drawString("Server", xStartingPointServerText,

    yStartingPoint);

    // The string should be written so that it fits between the JVM

    and Server// rectangles, leaving at least 5 pixels space between the

    rectangle and// the string.if (stringValid && currentGobblePosition < theString.length()) {

    // First need to figure out how many characters will fit in// the space between the two rectangles.int xTextStartingPoint = jvmRectangleWidth + 10;int xTextEndingPoint = xStartingPointServerRect - 5;int pixelsAvailableBetweenRectangles = xTextEndingPoint -

    xTextStartingPoint;if (pixelsAvailableBetweenRectangles < 0) {

    pixelsAvailableBetweenRectangles = 0;}

    // Initialize the number of characters to write as thenumber of

    // remaining characters. This will be reduced below if thisamount of

    // characters doesn't fit.int charsToWriteCount = theString.length() -

    currentGobblePosition;

    // Check to see if the string to be displayed already fitsbetween the

    // two rectangles. If so, we'll just use the total number

    of characters// remaining as the number of characters to write.int pixelWidthOfRemainingString =

    fm.stringWidth(theString.substring(currentGobblePosition));if (pixelWidthOfRemainingString >

    pixelsAvailableBetweenRectangles) {

    // The first while loop increments thecharsThatFitBetweenTwoRectanglesCount

  • 8/8/2019 The Java Class File Lifestyle

    15/32

    // until the width of the string in pixels just exceedsthe available space.

    String tryThisString =theString.substring(currentGobblePosition,

    currentGobblePosition +charsThatFitBetweenRectanglesCount);

    int pixelsEaten = fm.stringWidth(tryThisString);while (pixelsEaten pixelsAvailableBetweenRectangles) {

    --charsThatFitBetweenRectanglesCount;tryThisString =

    theString.substring(currentGobblePosition,currentGobblePosition +

    charsThatFitBetweenRectanglesCount);pixelsEaten = fm.stringWidth(tryThisString);

    }

    charsToWriteCount = charsThatFitBetweenRectanglesCount;}

    // Draw the interesting characters in red.g.setColor(Color.red);int redCharsCount = interestingCharsCount;if (redCharsCount > charsToWriteCount) {

    redCharsCount = charsToWriteCount;}String redString =

    theString.substring(currentGobblePosition,currentGobblePosition + redCharsCount);

    g.drawString(redString, xTextStartingPoint, yStartingPoint);

    // Draw the remaining characters in black.int blackStringStartingPosition = currentGobblePosition +

    redCharsCount;

    int blackCharsCount = charsToWriteCount - redCharsCount;if (blackStringStartingPosition < theString.length()

    && blackCharsCount > 0) {

    xTextStartingPoint += fm.stringWidth(redString);g.setColor(Color.black);g.drawString(theString.substring(blackStringStartingPos

    ition,blackStringStartingPosition + blackCharsCount),xTextStartingPoint, yStartingPoint);

  • 8/8/2019 The Java Class File Lifestyle

    16/32

    }}

    }}

    class ControlPanel extends Panel {

    JVMPacman jvmPacman = new JVMPacman();

    ControlPanel() {setLayout(new BorderLayout(5, 5));setBackground(Color.blue);add("West", new ButtonPanel());add("Center", jvmPacman);

    }

    public JVMPacman getJVMPacman() {return jvmPacman;

    }

    public Insets insets() {// top, left, bottom, rightreturn new Insets(0, 0, 0, 0);

    }}

    class StepNode {

    private String theString;private StepNode next;private StepNode prev;private boolean nextValid = false;private boolean prevValid = false;private int byteCount = 0;

    StepNode(String s, int bytes) {theString = s;byteCount = bytes;

    }

    String getString() {return theString;

    }

    int getByteCount() {return byteCount;

    }

    StepNode getNext() {// Should probably throw an exception here if !nextValidreturn next;

    }

    void setNext(StepNode n) {next = n;nextValid = true;

    }

  • 8/8/2019 The Java Class File Lifestyle

    17/32

    boolean last() {return !nextValid;

    }

    StepNode getPrev() {// Should probably throw an exception here if !prevValidreturn prev;

    }

    void setPrev(StepNode n) {prev = n;prevValid = true;

    }

    boolean first() {return !prevValid;

    }}

    // I used this class because I can't seem to set the background color of// a label. I only want a label, but I want the backgound to be gray.class ColoredLabel extends Panel {

    private Label theLabel;

    ColoredLabel(String label, int alignment, Color color) {

    setLayout(new GridLayout(1,1));

    setBackground(color);

    theLabel = new Label(label, alignment);

    add(theLabel);}

    public void setLabelText(String s) {

    theLabel.setText(s);}

    public Insets insets() {return new Insets(0, 0, 0, 0);

    }}

    class HexString {

    private final String hexChar = "0123456789ABCDEF";private StringBuffer buf = new StringBuffer();

    void Convert(int val, int maxNibblesToConvert) {

    buf.setLength(0);

    int v = val;

  • 8/8/2019 The Java Class File Lifestyle

    18/32

    for (int i = 0; i < maxNibblesToConvert; ++i) {

    if (v == 0) {

    if (i == 0) {buf.insert(0, '0');

    }break;

    }

    // Get lowest nibbleint remainder = v & 0xf;

    // Convert nibble to a character and insert it into thebeginning of the string

    buf.insert(0, hexChar.charAt(remainder));

    // Shift the int to the right four bitsv >>>= 4;

    }

    }

    HexString(int val, int minWidth) {

    Convert(val, minWidth);

    int charsNeeded = minWidth - buf.length();for (int i = 0; i < charsNeeded; ++i) {

    buf.insert(0, '0');}

    }

    public String getString() {

    return buf.toString();}

    }

    ASCII FILE for previous source code

    Step 1. Magic Number

    hex bytes name--------- ----CAFEBABE magic

    First the JVM must make sure that the class file starts with the propermagic number. In this case our JVM will be happy because it will findthe CafeBabe magic right where it's supposed to be.

    By the way, all numbers are stored in the class file in big-endianorder, which means the higher order bytes come first. The very firstbyte of every class file, therefore, will be 0xCA.****Step 2. Version Numbers

    hex dec name

  • 8/8/2019 The Java Class File Lifestyle

    19/32

    --- --- ----0003 3 minor_version002D 45 major_version

    Next, the JVM must make sure that it recognizes and fully understandstheformat of the class file being loaded. If either the major or minorversionnumber is higher than those version numbers for which this JVM wasimplemented,the JVM must reject the class file. In this case, our JVM is relievedto findthat the file has major version 45 and minor version 3, of which it hasintimateknowledge.****Step 3. Constant Pool Count

    0011 17 constant_pool_count

    The next two bytes make up an unsigned short integer which indicatesthe number of elements in the constant pool array. In this case theconstant pool will have 17 elements, but because the zeroeth elementdoesn't appear in the class file, the JVM will expect to find elements 1through 16 next in the stream.**Step 4. constant_pool[1]

    07 7 tag000C 12 name_index

    Each constant pool element contains a structure whose type is indicatedby the first byte of the element which is interpreted as a type tag.

    The first constant pool entry is a CONSTANT_Class_info structure. TheJVMknows this because it finds a 7, which means CONSTANT_Class, in the tagbyte position. Aside from the tag the CONSTANT_Class_info structure hasonly a name_index, which in this case is 12. This is an index into theconstantpool. The JVM doesn't know it yet, because it hasn't read in the 12thelementof the constant pool, but the 12th element will be the string"java/lang/Object",which is the name of the superclass of this class. Because class Actdoesn'texplicitly descend from any other class, it by default descends from

    classObject.

    Note that this is the first constant pool element and that it alreadyhasindex 1. constant_pool[0] doesn't appear in the class file.***Step 5. constant_pool[2]

    07 7 tag

  • 8/8/2019 The Java Class File Lifestyle

    20/32

    000D 13 name_index

    The 2nd constant pool entry is another CONSTANT_Class_info structure.The JVMknows this because it again finds a 7, which still meansCONSTANT_Class, in thetag byte position. The name_index here, however, is 13.constant_pool[13] will bethe string "Act", although once again the JVM doesn't know this yetbecause ithasn't read that far into the constant pool. At this point the JVM onlyknowsthat when it does get around to the 13th constant pool element, thatelementwill contain the name of the class which is represented by theCONSTANT_Class_info structure occupying constant_pool[2].

    constant_pool[2] therefore represents the "this" class, class Act,which thisclass file defines.

    ***Step 6. constant_pool[3]

    0A 10 tag0001 1 class_index0004 4 name_and_type_index

    constant_pool[3] contains a CONSTANT_Methodref_info structure,indicated by thetag of 10, which means CONSTANT_Methodref. A CONSTANT_Methodref_infostructurerepresents a method and records its name, type, and the class to whichitbelongs. The first two bytes after the tag, the class_index, form anindex intothe constant pool, in this case a 1. constant_pool[1] represents thesuperclass Object,so this method should be declared in Object.

    The next two bytes make up the name_and_type_index, which is an indexinto theconstant pool pointing to a CONSTANT_NameAndType structure. In this casename_and_type_index is 4 and constant_pool[4] defines "void ()".Becauseclass Act doesn't declare its own constructor, the javac compiler wroteoneof its own which calls () in superclass Object.

    *****Step 7. constant_pool[4]

    0C 12 tag000E 14 name_index0010 16 descriptor_index

    constant_pool[4] is a CONSTANT_NameAndType structure identified by itsinitial

  • 8/8/2019 The Java Class File Lifestyle

    21/32

    tag of 12, which stands for CONSTANT_NameAndType. Following the tagbyte isthe name_index, which is 14. constant_pool[14] will be the string"". Nextis the descriptor_index, which is 16. constant_pool[16] will be thestring "()V".

    "" is the name of the method being described. "()V" is the type.Inplain Java it would look like "void ()". "()V" is a methoddescriptor.The "()" indicates that there are no arguments to "". The "V"indicatesthe return type of "" is void.*****Step 8. constant_pool[5]

    01 1 tag000D 13 length436F6E7374616E7456616C7565 "ConstantValue"

    bytes[length]

    constant_pool[5] is a CONSTANT_Utf8_info structure as identified by itstag of 1, which means CONSTANT_Utf8. CONSTANT_Utf8 is how constantstringsare encoded in the constant pool. The UTF-8 format allows any 16 bitcharacterto be represented by either 1, 2, or 3 bytes. The characters '\u0001'to '\u007F'occupy only one byte. Other characters require 2 or 3 bytes, however,thesecharacters are expected to appear less frequently than the charactersthatrequire only 1 byte. By this means the full 16 bit Unicode characterset canbe supported by the class file without using as much space as wouldlikely beused by just making each character 16 bits long.

    The tag byte of a CONSTANT_Utf8_info structure is followed by a length,in thiscase 13, which indicates the length in bytes of the UTF-8 format stringthat follows. Inthis case the string spells out "ConstantValue". This string is usedinternallyby the class file in a manner that will be described later in the fileloading

    simulation.

    There is no trailing null character in a CONSTANT_Utf8_info.bytes asthatwould unnecessarily waste bandwidth.****************Step 9. constant_pool[6]

    01 1 tag000D 13 length

  • 8/8/2019 The Java Class File Lifestyle

    22/32

    646F4D617468466F7265766572 "doMathForever"bytes[length]

    constant_pool[6] is a CONSTANT_Utf8_info structure which contains thestring"doMathForever". This is the name of the lone method defined in classAct.****************Step 10. constant_pool[7]

    01 1 tag000A 10 length457863657074696F6E73 "Exceptions" bytes[length]

    constant_pool[7] is a CONSTANT_Utf8_info structure which contains thestring"Exceptions".*************Step 11. constant_pool[8]

    01 1 tag000F 15 length4C696E654E756D6265725461626C65 "LineNumberTable"

    bytes[length]

    constant_pool[8] is a CONSTANT_Utf8_info structure which contains thestring"LineNumberTable".******************Step 12. constant_pool[9]

    01 1 tag000A 10 length536F7572636546696C65 "SourceFile" bytes[length]

    constant_pool[9] is a CONSTANT_Utf8_info structure which contains thestring"SourceFile".*************Step 13. constant_pool[10]

    01 1 tag000E 14 length4C6F63616C5661726961626C6573 "LocalVariable" bytes[length]

    constant_pool[10] is a CONSTANT_Utf8_info structure which contains thestring

    "LocalVariable".*****************Step 14. constant_pool[11]

    01 1 tag0004 4 length436F6465 "Code" bytes[length]

    constant_pool[11] is a CONSTANT_Utf8_info structure which contains thestring

  • 8/8/2019 The Java Class File Lifestyle

    23/32

    "Code".*******Step 15. constant_pool[12]

    01 1 tag0010 16 length6A6176612F6C616E672F4F626A656374 "java/lang/Object"

    bytes[length]

    constant_pool[12] is a CONSTANT_Utf8_info structure which contains thestring"java/lang/Object". This is the fully qualified class name of"java.lang.Object"with the dots changed to slashes. (The slashes are there in place ofthe dotsbecause of historical reasons.)*******************Step 16. constant_pool[13]

    01 1 tag

    0003 3 length416374 "Act" bytes[length]

    constant_pool[13] is a CONSTANT_Utf8_info structure which contains thestring"Act". This is the name of the class which is being defined by thisfile.******Step 17. constant_pool[14]

    01 1 tag0006 6 length3C696E69743E "" bytes[length]

    constant_pool[14] is a CONSTANT_Utf8_info structure which contains thestring"", the name of a method in the superclass, Object.*********Step 18. constant_pool[15]

    01 1 tag000B 11 length736E697065742E6A617661 "snipet.java" bytes[length]

    constant_pool[15] is a CONSTANT_Utf8_info structure which contains thestring"snipet.java", the name of the source file in which class Act was

    defined.**************Step 19. constant_pool[16]

    01 1 tag0003 3 length282956 "()V" bytes[length]

    constant_pool[15] is a CONSTANT_Utf8_info structure which contains thestring

  • 8/8/2019 The Java Class File Lifestyle

    24/32

    "()V", a method descriptor which translates to a method that takes noargumentsand returns void.******Step 20. Access Flags

    0000 access_flags

    The access flags are a two byte unsigned integer that is composed bybitwiseoring bitmasks for individual flags that represent modifiers of theclass orinterface defined by this file. For example, ACC_PUBLIC is 0x0001 andACC_FINAL is 0x0010. A class declared to be both public and final wouldhaveits access flags set to 0x0011, or (ACC_PUBLIC | ACC_FINAL).

    In this case no access_flags are set because the class being defined,class Act,was not declared to be public, final, or abstract.

    Classes which are declared with these modifiers would have theappropriate bitmasksfrom ACC_PUBLIC, ACC_FINAL, and ACC_ABSTRACT ored together to make theresultantaccess_flags. Also, if a class file defines an interface and not class,then anACC_INTERFACE bit is set in access_flags. This is how the JVM knowswhether a classor an interface is being defined by the file.**Step 21. This Class and Super Class

    0002 2 this_class0001 1 super_class

    this_class is a two byte unsigned integer index into the constant pool,whereconstant_pool[this_class] is a CONSTANT_Class_info structurerepresenting theclass defined by this file. In our case it is the CONSTANT_Class_infostructurefor class Act.

    super_class is a two byte unsigned integer index into the constantpool, whereconstant_pool[super_class] is a CONSTANT_Class_info structure

    representing thesuperclass from which the class defined by this file decends. In ourcase itis the CONSTANT_Class_info structure for class Object.****Step 22. Interfaces Count and Fields Count

    0000 0 interfaces_count0000 0 fields_count

  • 8/8/2019 The Java Class File Lifestyle

    25/32

    interfaces_count is a two byte unsigned integer which indicates thenumber ofinterfaces implemented by this class. Because class Act implements nointerfaces,interfaces_count is zero in this case.

    fields_count is a two byte unsigned integer which indicates the numberoffields (class or instance variables) implemented by this class. Becauseclass Acthas no class or instance variables, fields_count is zero in our case.****Step 23. Methods Count

    0002 2 methods_count

    methods_count is a two byte unsigned integer indicating the number ofmethodsdefined by this class. The count does not include any methods inheritedfrom

    superclasses, only those methods explicitly defined in this class.

    In this case methods_count is 2 because doMathForever() is defined inthesource file and the constructor Act() is defined by the compiler.

    The JVM will expect an array of 2 method_info structures to immediatelyfollowthis methods_count.**Step 24. doMathForever()'s Access Flags, Name Index, and DescriptorIndex

    0009 access_flags0006 6 name_index0010 16 descriptor_index

    This is the beginning of the array of method_info structures thatimmediately followsthe methods_count. The first method_info structure, methods[0], givesinformationabout the doMathForever() method. The second method_info structure,methods[1], givesinformation about the Act() constructor.

    The first three parts of methods[0] are shown here. access_flags givesthe modifiers

    with which the method was declared. In this case access_flags is a0x0009 whichequates to (ACC_PUBLIC | ACC_STATIC). If you look back at the sourcecode, thedoMathForever() method is indeed declared public and static.

    The name_index indicates the constant pool entry where the name of themethod isstored. In this case name_index is 6 and constant_pool[6] is indeed theUTF-8

  • 8/8/2019 The Java Class File Lifestyle

    26/32

    string "doMathForever".

    The descriptor_index indicates the constant pool entry where thedescriptor ofthis method is stored. In this case descriptor_index is 16 andconstant_pool[16] isthe string "()V". This descriptor string indicates that doMathForever()is a methodwhich takes no arguments and returns void.******Step 25. doMathForever() Attributes

    0001 1 attributes_count

    methods[0].attributes[0]000B 11 attribute_name_index00000030 48 length

    Following the descriptor_index of a method is its attributes_count. Inthis case there

    is only 1 attribute for the doMathForever() method.

    The list of attributes follows the attributes_count. Here there is onlyone attribute,attributes[0]. The first two bytes of the attribute are theattribute_name_index. Theattribute_name_index is the index of the constant pool entry whichcontains the name ofthe attribute. In this case attribute_name_index is 11 andconstant_pool[11] is "Code".Therefore this is the Code attribute of doMathForever() which willcontain, among a fewother items, the actual bytecode sequence for the method.

    The length word indicates the number of bytes in the attribute, in thiscase 48 bytes.This means 48 bytes will follow this length word.********Step 26. doMathForever() Max Stack and Max Locals

    0002 2 max_stack0001 1 max_locals

    Max stack is a two byte unsigned integer that indicates the maximumnumber of entrieson the JVM's operand stack at any point in the method. Max locals is atwo byte

    unsigned integer that indicates the number of local variables slotsused by the method.Each local variable slot is a four byte word.

    In this case, max_stack is 2. If you look back at the Eternal Mathapplet from lastmonth's article and watch the operand stack as the JVM executes thedoMathForever()bytecodes, you will see that the operand stack never has more than twowords in it.

  • 8/8/2019 The Java Class File Lifestyle

    27/32

    The max_locals is 1 in this case, because doMathForever() takes noarguments and hasonly one variable, i. If you look back at the Eternal Math applet youcan see thatthere is only one word in the local variables section ofdoMathForever()'s stackframe, the integer i.****Step 27. doMathForever() Bytecodes and Exception Table

    0000000C 12 code_length033B8400011A05683BA7FFF9 code[code_length]0000 0 exception_table_length

    code_length indicates the number of bytes in the bytecode sequence forthis method.The actual bytecodes follow the code_length. In this case thedoMathForever()method bytecode sequence fills 12 bytes. If you look back to the

    Eternal Math appletfrom last month's article you will see that these are the bytecodesbeingexecuted in that simulation.

    pc instruction mnemonic-- ----------- --------0 03 iconst_01 3B istore_02 840001 iinc 0 15 1A iload_06 05 iconst_27 68 imul8 3B istore_09 A7FFF9 goto 2

    exception_table_length indicates the number of exceptions that arecaught in themethod. In the case of doMathForever(), exception_table_length is zerobecause noexceptions are explicitly caught in this method. For methods that docatchexceptions, an array of exception handler structures immediatelyfollows theexception_table_length.

    One other thing you may notice at this point is that these bytecodes

    haven'tbeen assigned a place in memory yet. This is done by the JVM when itloads theclass file. Therefore, the value I called pc is really the offset fromtheactual program counter address at which this bytecode sequence is loadedby a JVM.******************Step 28. Attributes of the doMathForever() Code Attribute

  • 8/8/2019 The Java Class File Lifestyle

    28/32

    0001 1 attributes_count0008 8 attribute_name_index00000012 18 attribute_length0004 4 line_number_table_length

    The doMathForever() "Code" attribute itself has a "sub-attribute"section. I.e.,the attributes listed here belong to the "Code" attribute ofdoMathForever().

    attributes_count is 1, which indicates there is only one attributebelonging tothe "Code" attribute of doMathForever(). attribute_name_index is an 8,andconstant_pool[8] is the string "LineNumberTable". This is the name oftheattribute. attribute_length gives the length of attribute"LineNumberTable" as18. The line_number_table_length is 4, meaning that there will be 4line_number_table entries immediately following.

    If you look back at the snipet of Java code which definesdoMathForever() you'llsee that there are only 4 lines of code which get translated tobytecodes:

    line 4: i = 0;line 5: while (true) {line 6: i += 1;line 7: i *= 2;

    These four lines will be matched up with the corresponding bytecodes intheline_number_table that follows.**********Step 29. Line Number Table for doMathForever()

    hex dec name what it refers to--- --- ---- -------------------line_number_table[0]0000 0 start_pc iconst_0, istore_00004 4 line_number int i = 0;

    line_number_table[1]0002 2 start_pc iinc 0 10006 6 line_number i += 1

    line_number_table[2]0005 5 start_pc iload_0, iconst_2, imul,istore_00007 7 line_number i *= 2

    line_number_table[3]0009 9 start_pc goto 20005 5 line_number while (true) {

  • 8/8/2019 The Java Class File Lifestyle

    29/32

    The above table associates each line in the doMathForever() code withitscorresponding bytecode instruction. The start_pc value of each tableentryindicates the zero based byte position inside the doMathForever()bytecodesequence. The line_number value of each table entry is the line numberofthe source file that corresponds to the start_pc position in thebytecodesequence.

    The line number information is of general utility. It is useful todebuggers,for example. It also allows the line number at which an exception isthrownto be written to the Java console.

    This is the last of the information in the class file about thedoMathForever()

    method. Next will come the information about the other method of thisclass,the constructor Act().****************Step 30. Act()'s Access Flags, Name Index, and Descriptor Index

    methods[1]0000 access_flags000E 14 name_index0010 16 descriptor_index

    This is the beginning of the second method_info structure, methods[1],whichgives information about the Act() constructor.

    The first three parts of methods[1] are shown here. access_flags givesthe modifierswith which the method was declared. In this case access_flags is a0x0000 whichmeans it's neither public, private, protected, static, final,synchronized, native,or abstract. It's just a plain old method.

    The name_index indicates the constant pool entry where the name of themethod isstored. In this case name_index is 14 and constant_pool[14] is indeedthe UTF-8

    string "". "" is a special internal method name used torepresentconstructors.

    The descriptor_index indicates the constant pool entry where thedescriptor ofthis method is stored. In this case descriptor_index is 16 andconstant_pool[16] isthe string "()V". This descriptor string indicates that () orAct() is a

  • 8/8/2019 The Java Class File Lifestyle

    30/32

    method which takes no arguments and returns void.******Step 31. Act() Attributes

    0001 1 attributes_count

    000B 11 attribute_name_index0000001D 29 attribute_length

    Following the descriptor_index of a method is its attributes_count. Inthis case thereis only 1 attribute for the Act() method.

    The list of attributes follows the attributes_count. Here there is onlyone attribute,attributes[0]. The first two bytes of the attribute are theattribute_name_index. Theattribute_name_index is the index of the constant pool entry whichcontains the name ofthe attribute. In this case attribute_name_index is 11 and

    constant_pool[11] is "Code".Therefore this is the Code attribute of doMathForever() which willcontain, among a fewother items, the actual bytecode sequence for the method.

    The length word indicates the number of bytes in the attribute, in thiscase 29 bytes.This means 29 bytes will follow this length word.********Step 32. Act() Max Stack and Max Locals

    0001 1 max_stack0001 1 max_locals

    Max stack is a two byte unsigned integer that indicates the maximumnumber of entrieson the JVM's operand stack at any point in the method, in this case 1.Max locals is atwo byte unsigned integer that indicates the number of local variablesslots used bythe method, in this case 1. Each local variable slot is a four byteword.****Step 33. Act() Bytecodes and Exception Table

    00000005 5 code_length2AB70003B1 code[code_length]

    0000 0 exception_table_length

    code_length indicates the number of bytes in the bytecode sequence forthis method.The actual bytecodes follow the code_length. In this case the Act()method bytecode sequence fills 5 bytes. This method was generated bythe compilerand doesn't appear in the Java source file for class Act.

    pc instruction mnemonic

  • 8/8/2019 The Java Class File Lifestyle

    31/32

    -- ----------- --------0 2A aload_01 B70003 invokenonvirtual #3 4 B1 return

    If you look at the operand for the second instruction, invokenonvirtual(bytecode B7),you will see a 0003. If you go look at constant_pool[3] you'll find aname and typeconstant that describes the method of java.lang.Object.

    exception_table_length indicates the number of exceptions that arecaught in themethod. In the case of Act(), exception_table_length is zero because noexceptions are explicitly caught in this method. For methods that docatchexceptions, an array of exception handler structures immediatelyfollows theexception_table_length.

    ***********Step 34. Line Number Table Attribute of the Act() Code Attribute

    hex dec name--- --- ----0001 1 attributes_count0008 8 attribute_name_index00000006 6 attribute_length0001 1 line_number_table_length

    The Act() "Code" attribute itself has a "sub-attribute" section. I.e.,the attributes listed here belong to the "Code" attribute of Act().

    attributes_count is 1, which indicates there is only one attributebelonging tothe "Code" attribute of Act(). attribute_name_index is an 8, andconstant_pool[8] is the string "LineNumberTable". This is the name oftheattribute. attribute_length gives the length of attribute"LineNumberTable" as6. The line_number_table_length is 1, meaning that there will be only 1line_number_table entry immediately following.**********Step 35. Line Number Table for Act()

    hex dec name what it refers to--- --- ---- -----------------

    0000 0 start_pc aload_0, invokenonvirtual#3, return0002 2 line_number class Act {

    The above table associates a line in the Java source file with thestartinginstruction of the Act() method. The start_pc value of the table entryindicates the zero based byte position inside the Act() bytecodesequence. The line_number value of the table entry is the line number of

  • 8/8/2019 The Java Class File Lifestyle

    32/32

    the source file that corresponds to the start_pc position in thebytecodesequence.

    This is the last of the information in the class file about the Act()method, which was the last method to be described by this file. The lastsection of the class file follows, the general class file attributes.****Step 36. General Attributes

    0001 1 attributes_count

    0009 9 attribute_name_index00000002 2 attribute_length000F 15 sourcefile_index

    A class file can have any number of attributes at the end. In this caseattributes_count is a 1, so there is only 1 attribute here. Theattribute_name_indexis 9, and constant_pool[9] is the string "SourceFile". Therefore, this

    is the"SourceFile" attribute. attribute_length gives the length of theattribute as 2,which means that two bytes will follow the attribute_length field. Thelast twobytes are the sourcefile_index, which in this case is 15.constant_pool[15] isthe string "snipet.java", which as it happens, is the name of thesource fileI compiled with javac to generate this file, Act.class.**********