Java/Development Class/JVM Tool Interface

Материал из Java эксперт
Перейти к: навигация, поиск

Byte Code Instrumentation (BCI)

Check the version of the interface being used

Do some very basic bytecode insertion (BCI) of class files

Floating Point Arithmetic

   <source lang="java">
  

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

* Permission to use, copy, modify, and distribute this software
* and its documentation for EVALUATION purposes only
* is hereby granted provided that this copyright notice
* appears in all copies. "Evaluation purposes" are any uses which
* do not constitute the sale, sharing, or redistribution of this
* software with or to any other persons in any medium.
*
* ARTIMA SOFTWARE COMPANY MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT
* THE SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. ARTIMA SOFTWARE COMPANY
* SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
* USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.

PROJECT: JavaWorld MODULE: Under The Hood FILE: ExposedFloat.java AUTHOR: Bill Venners, August 1996 DESCRIPTION: This file contains all the code for the Floating Point Viewer applet, named Exposed Float, that accompanies the Under The Hood article titled, "Floating Point Arithmetic". As I developed this applet I had every class in a separate file. I combined them in one file here to make it easier to download.

                                                                                                                                          • /

import java.awt.*; import java.applet.*; public class ExposedFloat extends Applet {

   private Label binaryField;
   private Label signField;
   private Label exponentField;
   private Label mantissaField;
   private Label hexField;
   private Label base2Field;
   private Label base10Field;
   private float value;
   private final String titleString = "EXPOSED FLOAT";
   private final String binaryString = "binary";
   private final String signString = "sign";
   private final String exponentString = "exponent";
   private final String mantissaString = "mantissa";
   private final String hexString = "hex";
   private final String base10String = "radix 10";
   private final String base2String = "radix 2";
   private final String incrementButtonString = "++";
   private final String decrementButtonString = "--";
   private final String multByZeroButtonString = "*=(0)";
   private final String piButtonString = "Pi";
   private final String positiveInfinityButtonString = "+Inf";
   private final String negativeInfinityButtonString = "-Inf";
   private final String maximumButtonString = "Max";
   private final String minimumButtonString = "Min";
   private final String notANumberButtonString = "NaN";
   private final String changeSignButtonString = "*=(-1)";
   private final String doubleButtonString = "*=(2)";
   private final String halveButtonString = "/=(2)";
   private final String notANumberString = "Not A Number";
   private final String positiveInfinityString = "+Infinity";
   private final String negativeInfinityString = "-Infinity";
   Button maximumButton = new Button(maximumButtonString);
   Button minimumButton = new Button(minimumButtonString);
   Button positiveInfinityButton = new Button(positiveInfinityButtonString);
   Button negativeInfinityButton = new Button(negativeInfinityButtonString);
   Button piButton = new Button(piButtonString);
   Button notANumberButton = new Button(notANumberButtonString);
   public void init() {
       Panel buttonPanel = new PanelWithInsets(0, 0, 0, 0);
       buttonPanel.setLayout(new GridLayout(6, 2, 5, 5));
       buttonPanel.add(maximumButton);
       buttonPanel.add(minimumButton);
       buttonPanel.add(positiveInfinityButton);
       buttonPanel.add(negativeInfinityButton);
       buttonPanel.add(piButton);
       buttonPanel.add(notANumberButton);
       buttonPanel.add(new Button(multByZeroButtonString));
       buttonPanel.add(new Button(changeSignButtonString));
       buttonPanel.add(new Button(doubleButtonString));
       buttonPanel.add(new Button(halveButtonString));
       buttonPanel.add(new RepeaterButton(incrementButtonString));
       buttonPanel.add(new RepeaterButton(decrementButtonString));
       binaryField = new Label("00000000000000000000000000000000");
       signField = new Label("0");
       exponentField = new Label("00000000");
       mantissaField = new Label("000000000000000000000000");
       hexField = new Label("00000000");
       base2Field = new Label("0");
       base10Field = new Label("0");
       Font fieldFont = new Font("TimesRoman", Font.PLAIN, 12);
       binaryField.setFont(fieldFont);
       signField.setFont(fieldFont);
       exponentField.setFont(fieldFont);
       mantissaField.setFont(fieldFont);
       hexField.setFont(fieldFont);
       base2Field.setFont(fieldFont);
       base10Field.setFont(fieldFont);
       Panel numberPanel = new Panel();
       numberPanel.setBackground(Color.white);
       numberPanel.setLayout(new GridLayout(7, 1));
       numberPanel.add(signField);
       numberPanel.add(exponentField);
       numberPanel.add(mantissaField);
       Panel binaryPanel = new Panel();
       binaryPanel.setLayout(new BorderLayout());
       binaryPanel.add("Center", binaryField);
       numberPanel.add(binaryPanel);
       Panel hexPanel = new Panel();
       hexPanel.setLayout(new BorderLayout());
       hexPanel.add("Center", hexField);
       numberPanel.add(hexPanel);
       numberPanel.add(base2Field);
       numberPanel.add(base10Field);
       Panel labelPanel = new Panel();
       labelPanel.setBackground(Color.white);
       labelPanel.setLayout(new GridLayout(7, 1));
       Font labelFont = new Font("Helvetica", Font.ITALIC, 11);
       Label label = new Label(signString, Label.CENTER);
       label.setFont(labelFont);
       labelPanel.add(label);
       label = new Label(exponentString, Label.CENTER);
       label.setFont(labelFont);
       labelPanel.add(label);
       label = new Label(mantissaString, Label.CENTER);
       label.setFont(labelFont);
       labelPanel.add(label);
       label = new Label(binaryString, Label.CENTER);
       label.setFont(labelFont);
       labelPanel.add(label);
       label = new Label(hexString, Label.CENTER);
       label.setFont(labelFont);
       labelPanel.add(label);
       label = new Label(base2String, Label.CENTER);
       label.setFont(labelFont);
       labelPanel.add(label);
       label = new Label(base10String, Label.CENTER);
       label.setFont(labelFont);
       labelPanel.add(label);
       Panel dataPanel = new Panel();
       dataPanel.setLayout(new BorderLayout());
       dataPanel.add("West", labelPanel);
       dataPanel.add("Center", numberPanel);
       ColoredLabel title = new ColoredLabel(titleString, Label.CENTER, Color.cyan);
       title.setFont(new Font("Helvetica", Font.BOLD, 12));
       setBackground(Color.green);
       setLayout(new BorderLayout(5, 5));
       add("North", title);
       add("West", buttonPanel);
       add("Center", dataPanel);
   }
   public boolean action(Event evt, Object arg) {
       if (evt.target instanceof Button) {
           String bname = (String) arg;
           if (bname.equals(incrementButtonString)) {
               ++value;
           }
           else if (bname.equals(decrementButtonString)) {
               --value;
           }
           else if (bname.equals(multByZeroButtonString)) {
               value *= (float) 0.0;
           }
           else if (bname.equals(piButtonString)) {
               value = (float) Math.PI;
           }
           else if (bname.equals(positiveInfinityButtonString)) {
               value = Float.POSITIVE_INFINITY;
           }
           else if (bname.equals(negativeInfinityButtonString)) {
               value = Float.NEGATIVE_INFINITY;
           }
           else if (bname.equals(maximumButtonString)) {
               value = Float.MAX_VALUE;
           }
           else if (bname.equals(minimumButtonString)) {
               value = Float.MIN_VALUE;
           }
           else if (bname.equals(notANumberButtonString)) {
               value = Float.NaN;
           }
           else if (bname.equals(changeSignButtonString)) {
               value *= -1.0;
           }
           else if (bname.equals(doubleButtonString)) {
               value *= 2.0;
           }
           else if (bname.equals(halveButtonString)) {
               value /= 2.0;
           }
           updateNumberFields();
           enableDisableButton(maximumButton, Float.MAX_VALUE);
           enableDisableButton(minimumButton, Float.MIN_VALUE);
           enableDisableButton(positiveInfinityButton, Float.POSITIVE_INFINITY);
           enableDisableButton(negativeInfinityButton, Float.NEGATIVE_INFINITY);
           enableDisableButton(piButton, (float) Math.PI);
           enableDisableButton(notANumberButton, Float.NaN);
           if (!notANumberButton.isEnabled()) {
               if (!Float.isNaN(value)) {
                   notANumberButton.enable();
               }
           } else if (Float.isNaN(value)) {
               notANumberButton.disable();
           }
       }
       return true;
   }
   void enableDisableButton(Button b, float val) {
       if (!b.isEnabled()) {
           if (value != val) {
               b.enable();
           }
       } else if (value == val) {
           b.disable();
       }
   }
   void updateNumberFields() {
       int intBits = Float.floatToIntBits(value);
       if (Float.isNaN(value)) {
           base10Field.setText(notANumberString);
       }
       else if (Float.isInfinite(value)) {
           if ((intBits >>> 31) == 1) {
               // This is a negative infinity
               base10Field.setText(negativeInfinityString);
           }
           else {
               // This is a positive infinity
               base10Field.setText(positiveInfinityString);
           }
       }
       else if (intBits == (int) 0x80000000) {
           base10Field.setText("-0");
       }
       else {
           base10Field.setText(Float.toString(value));
       }
       int v = intBits;
       StringBuffer buf = new StringBuffer();
       for (int i = 0; i < 8; ++i) {
           // Get lowest bit
           int remainder = v & 0xf;
           // Convert bit to a character and insert it into the beginning of the string
           switch (remainder) {
           case 0:
               buf.insert(0, "0");
               break;
           case 1:
               buf.insert(0, "1");
               break;
           case 2:
               buf.insert(0, "2");
               break;
           case 3:
               buf.insert(0, "3");
               break;
           case 4:
               buf.insert(0, "4");
               break;
           case 5:
               buf.insert(0, "5");
               break;
           case 6:
               buf.insert(0, "6");
               break;
           case 7:
               buf.insert(0, "7");
               break;
           case 8:
               buf.insert(0, "8");
               break;
           case 9:
               buf.insert(0, "9");
               break;
           case 10:
               buf.insert(0, "a");
               break;
           case 11:
               buf.insert(0, "b");
               break;
           case 12:
               buf.insert(0, "c");
               break;
           case 13:
               buf.insert(0, "d");
               break;
           case 14:
               buf.insert(0, "e");
               break;
           case 15:
               buf.insert(0, "f");
               break;
           }
           // Shift the int to the right one bit
           v >>>= 4;
       }
       hexField.setText(buf.toString());
       v = intBits;
       buf.setLength(0);
       for (int i = 0; i < 32; ++i) {
           // Get lowest bit
           int remainder = v & 0x1;
           // Convert bit to a character and insert it into the beginning of the string
           if (remainder == 0) {
               buf.insert(0, "0");
           }
           else {
               buf.insert(0, "1");
           }
           // Shift the int to the right one bit
           v >>>= 1;
       }
       binaryField.setText(buf.toString());
       if (intBits < 0) {
           signField.setText("1");
       }
       else {
           signField.setText("0");
       }
       v = intBits >> 23;
       buf.setLength(0);
       for (int i = 0; i < 8; ++i) {
           // Get lowest bit
           int remainder = v & 0x1;
           // Convert bit to a character and insert it into the beginning of the string
           if (remainder == 0) {
               buf.insert(0, "0");
           }
           else {
               buf.insert(0, "1");
           }
           // Shift the int to the right one bit
           v >>>= 1;
       }
       exponentField.setText(buf.toString());
       // Do the mantissa
       v = intBits;
       buf.setLength(0);
       for (int i = 0; i < 23; ++i) {
           // Get lowest bit
           int remainder = v & 0x1;
           // Convert bit to a character and insert it into the beginning of the string
           if (remainder == 0) {
               buf.insert(0, "0");
           }
           else {
               buf.insert(0, "1");
           }
           // Shift the int to the right one bit
           v >>>= 1;
       }
       if (((intBits >> 23) & 0xff) == 0) {
           // This is a denormalized number, first bit is 0
           buf.insert(0, "0");
       }
       else {
           // This is a normalized number, first bit is 1
           buf.insert(0, "1");
       }
       mantissaField.setText(buf.toString());
       // Print out a denormalized base 2 version.
       buf.setLength(0);
       if (Float.isNaN(value)) {
           buf.append(notANumberString);
       }
       else if (Float.isInfinite(value)) {
           if ((intBits >>> 31) == 1) {
               // This is a negative infinity
               buf.append(negativeInfinityString);
           }
           else {
               // This is a positive infinity
               buf.append(positiveInfinityString);
           }
       }
       else {
           if ((intBits >>> 31) == 1) {
               // This is a negative number
               buf.append("-");
           }
           // Convert mantissa to int.
           v = (intBits & 0x007fffff);
           if (((intBits >> 23) & 0xff) != 0) {
               // Set bit 23 if the number is normalized
               v |= 0x00800000;
           }
           buf.append(v);
           // print out the exponent
           v = (intBits >> 23) & 0xff;
           if (v != 150 && intBits != 0 && intBits != (int) 0x80000000) {
               if (v != 0) {
                   // regular normalized number
                   buf.append("e" + (v - 150));
               }
               else {
                   // denormalized number
                   buf.append("e-149");
               }
           }
       }
       base2Field.setText(buf.toString());
   }
   public Insets insets() {
       return new Insets(5, 5, 5, 5);
   }

} // 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 GrayButton extends Button {

   GrayButton(String label) {
       super(label);
       setBackground(Color.lightGray);
   }

} class PanelWithInsets extends Panel {

   private int top;
   private int left;
   private int bottom;
   private int right;
   PanelWithInsets(int t, int l, int b, int r) {
       top = t;
       left = l;
       bottom = b;
       right = r;
   }
   PanelWithInsets() {
       top = 5;
       left = 5;
       bottom = 5;
       right = 5;
   }
   public Insets insets() {
       return new Insets(top, left, bottom, right);
   }

} class RepeaterButton extends GrayButton {

   RepeaterButton(String label) {
       super(label);
   }

}


 </source>
   
  
 
  



How to get an easy view of the heap in terms of total object count and space used

Inject code at method calls

Java Platform Debugger Architecture

jconsole plugin

JVM Simulator

   <source lang="java">
  

/*

* Copyright (c) 1996 Artima Software Company. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for EVALUATION purposes only
* is hereby granted provided that this copyright notice
* appears in all copies. "Evaluation purposes" are any uses which
* do not constitute the sale, sharing, or redistribution of this
* software with or to any other persons in any medium.
*
* ARTIMA SOFTWARE COMPANY MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT
* THE SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. ARTIMA SOFTWARE COMPANY
* SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
* USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*
*/

/*

* LogicalResults.java
*
* This file contains all the code for the java virtual machine simulation
* applet, named Three Dimensional Array, that accompanies the JavaWorld Under The Hood
* article titled,"Objecs and Arrays".
*
* Bill Venners, October 1996
*
*/

import java.awt.BorderLayout; import java.awt.Button; import java.awt.Color; import java.awt.ruponent; import java.awt.Container; import java.awt.Dimension; import java.awt.Event; import java.awt.Font; import java.awt.GridLayout; import java.awt.Insets; import java.awt.Label; import java.awt.LayoutManager; import java.awt.Panel;

/**

* An applet that simulates the Java virtual machine executing a
* sequence of bytecodes.
*
* @author      Bill Venners
*/

public class JVMSimulator extends java.applet.Applet implements Runnable {

   // Vars for the three outer panels that are contained inside the Applet"s panel.
   // twoParts contains the stack and the method area. simulationController
   // contains the Step and Reset buttons and the hint label.
   private ThreeParts threeParts;
   private RegisterPanel registers;
   private ControlPanel simulationController;
   // Local reference to buttons on control panel allows for easy enabling and
   // disabling of buttons.
   private Button stepButton;
   private Button resetButton;
   private Button runButton;
   private Button stopButton;
   // If the "run" button is pushed, a separate thread will be invoked that
   // will cause the JVM to execute until the "stop" button is pressed.
   private Thread runner;
   private final int millisecondDelayBetweenSteps = 250;
   // Vars that implement the Java stack
   private final int stackBase = 0x33330000;
   private StackMemorySection stackMemorySection = new StackMemorySection(stackBase, SimData.stackMemorySectionSize);
   private StackMemoryView stackMemoryView;
   // Vars that implement the method area of the JVM
   private final int methodAreaBase = 0x44440000;
   private MemorySection methodAreaMemorySection = new MemorySection(methodAreaBase,
       SimData.methodAreaMemorySectionSize);
   private MemoryView methodAreaMemoryView;
   // Vars that implement the Java registers
   private int pcRegister;
   private int optopRegister;
   private int frameRegister;
   private int varsRegister;
   public void init() {
       setBackground(SimData.appletBackgroundColor);
       setLayout(new BorderLayout(5, 5));
       threeParts = new ThreeParts(SimData.methodAreaMemorySectionSize);
       simulationController = new ControlPanel();
       stepButton = simulationController.getStepButton();
       resetButton = simulationController.getResetButton();
       runButton = simulationController.getRunButton();
       stopButton = simulationController.getStopButton();
       ColoredLabel title = new ColoredLabel(SimData.appletTitle, Label.CENTER, SimData.titleColor);
       title.setFont(new Font("Helvetica", Font.BOLD, 12));
       add("North", title);
       add("South", simulationController);
       add("Center", threeParts);
       // Get a reference to the UI objects that are actually manipulated by
       // the handlers of the Step and Reset buttons. These aren"t available
       // without this explicit get() because these objects are buried several
       // levels down in embedded panels.
       stackMemoryView = threeParts.getStackMemoryViewReference();
       methodAreaMemoryView = threeParts.getMethodAreaMemoryViewReference();
       registers = threeParts.getRegisterPanel();
       // Place the bytecodes into the method area
       for (int i = 0; i < SimData.methodAreaMemorySectionSize; ++i) {
           methodAreaMemorySection.setAtAddress(methodAreaBase + i,
               SimData.theProgram[i]);
           methodAreaMemorySection.setLogicalValueAtAddress(methodAreaBase + i,
               SimData.byteCodeMnemonics[i]);
       }
       ResetState();
       UpdateStateDisplay();
   }
   public boolean action(Event evt, Object arg) {
       if (evt.target instanceof Button) {
           String bname = (String) arg;
           if (bname.equals(StringTable.reset)) {
               stopButton.disable();
               runButton.enable();
               stepButton.enable();
               resetButton.disable();
               ResetState();
               UpdateStateDisplay();
           }
           else if (bname.equals(StringTable.step)) {
               resetButton.enable();
               ExecuteNextInstruction();
               UpdateStateDisplay();
           }
           else if (bname.equals(StringTable.run)) {
               stopButton.enable();
               runButton.disable();
               stepButton.disable();
               resetButton.disable();
               if (runner == null) {
                   runner = new Thread(this);
                   runner.start();
               }
           }
           else if (bname.equals(StringTable.stop)) {
               runButton.enable();
               stepButton.enable();
               resetButton.enable();
               stopButton.disable();
               if (runner != null) {
                   runner.stop();
                   runner = null;
               }
           }
       }
       return true;
   }
   // ExecuteNextInstruction() grabs the instruction pointed to by the program
   // counter, decodes it via the switch statement, and executes it by running the
   // code under the appropriate case statement. The program counter is always
   // set to the next instruction that should be executed, naturally. Only those
   // bytecodes that appear in the short sequence presented in this simulation
   // are interpreted here to save time (your time in downloading and my time
   // in writing.)
   void ExecuteNextInstruction() {
       int a, b, result, i, operand0, operand1, operand2, offset;
       float fa, fb, fresult;
       Float f;
       int nextOpCode = methodAreaMemorySection.getAtAddress(pcRegister);
       switch (nextOpCode) {
       case OpCode.AALOAD:
           executeAaload();
           break;
       case OpCode.ALOAD_0:
           executeAload_n(0);
           break;
       case OpCode.ASTORE_0:
           executeAstore_n(0);
           break;
       case OpCode.BIPUSH:
           operand0 = methodAreaMemorySection.getAtAddress(pcRegister + 1);
           stackMemorySection.setAtAddress(optopRegister, operand0);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, Integer.toString(operand0));
           optopRegister += 4;
           pcRegister += 2;
           break;
        // The BREAKPOINT opcode will serve as a stop sign for a running simulation.
       case OpCode.BREAKPOINT:
           stopButton.disable();
           runButton.disable();
           stepButton.disable();
           resetButton.enable();
           if (runner != null) {
               // If runner is not null, then this is probably the thread that
               // we want to stop. Therefore, as soon as stop has been executed,
               // nothing else will happen. So we must set runner to null before
               // we call runner.stop(). Therefore I copy runner to temp, assign
               // null to runner, and call stop() on temp.
               Thread temp = runner;
               runner = null;
               temp.stop();
           }
           break;
       case OpCode.FCONST_0:
           stackMemorySection.setAtAddress(optopRegister, Float.floatToIntBits((float) 0));
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "0");
           optopRegister += 4;
           ++pcRegister;
           break;
       case OpCode.FCONST_2:
           stackMemorySection.setAtAddress(optopRegister, Float.floatToIntBits((float) 2));
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "2");
           optopRegister += 4;
           ++pcRegister;
           break;
       case OpCode.FLOAD_0:
           a = stackMemorySection.getAtAddress(varsRegister);
           stackMemorySection.setAtAddress(optopRegister, a);
           fa = Float.intBitsToFloat(a);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, Float.toString(fa));
           optopRegister += 4;
           ++pcRegister;
           break;
       case OpCode.FMUL:
           optopRegister -= 4;
           a = stackMemorySection.getAtAddress(optopRegister);
           fa = Float.intBitsToFloat(a);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
           optopRegister -= 4;
           b = stackMemorySection.getAtAddress(optopRegister);
           fb = Float.intBitsToFloat(b);
           fresult = fa * fb;
           result = Float.floatToIntBits(fresult);
           stackMemorySection.setAtAddress(optopRegister, result);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, Float.toString(fresult));
           optopRegister += 4;
           ++pcRegister;
           break;
       case OpCode.FSTORE_0:
           optopRegister -= 4;
           a = stackMemorySection.getAtAddress(optopRegister);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
           stackMemorySection.setAtAddress(varsRegister, a);
           fa = Float.intBitsToFloat(a);
           stackMemorySection.setLogicalValueAtAddress(varsRegister, Float.toString(fa));
           ++pcRegister;
           break;
       case OpCode.FSUB:
           optopRegister -= 4;
           a = stackMemorySection.getAtAddress(optopRegister);
           fa = Float.intBitsToFloat(a);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
           optopRegister -= 4;
           b = stackMemorySection.getAtAddress(optopRegister);
           fb = Float.intBitsToFloat(b);
           fresult = fb - fa;
           result = Float.floatToIntBits(fresult);
           stackMemorySection.setAtAddress(optopRegister, result);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, Float.toString(fresult));
           optopRegister += 4;
           ++pcRegister;
           break;
       case OpCode.GOTO:
           operand1 = methodAreaMemorySection.getAtAddress(pcRegister + 1);
           operand0 = methodAreaMemorySection.getAtAddress(pcRegister + 2);
           offset = (operand1 << 8) | (operand0 & 0xff);
           pcRegister += offset;
           break;
       case OpCode.IADD:
           optopRegister -= 4;
           a = stackMemorySection.getAtAddress(optopRegister);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
           optopRegister -= 4;
           b = stackMemorySection.getAtAddress(optopRegister);
           result = a + b;
           stackMemorySection.setAtAddress(optopRegister, result);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, Integer.toString(result));
           optopRegister += 4;
           ++pcRegister;
           break;
       case OpCode.IAND:
           optopRegister -= 4;
           a = stackMemorySection.getAtAddress(optopRegister);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
           optopRegister -= 4;
           b = stackMemorySection.getAtAddress(optopRegister);
           result = a & b;
           stackMemorySection.setAtAddress(optopRegister, result);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, Integer.toString(result));
           optopRegister += 4;
           ++pcRegister;
           break;
       case OpCode.IASTORE:
           executeIastore();
           break;
       case OpCode.ICONST_M1:
           stackMemorySection.setAtAddress(optopRegister, -1);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "-1");
           optopRegister += 4;
           ++pcRegister;
           break;
       case OpCode.ICONST_0:
           stackMemorySection.setAtAddress(optopRegister, 0);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "0");
           optopRegister += 4;
           ++pcRegister;
           break;
       case OpCode.ICONST_1:
           stackMemorySection.setAtAddress(optopRegister, 1);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "1");
           optopRegister += 4;
           ++pcRegister;
           break;
       case OpCode.ICONST_2:
           stackMemorySection.setAtAddress(optopRegister, 2);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "2");
           optopRegister += 4;
           ++pcRegister;
           break;
       case OpCode.ICONST_3:
           stackMemorySection.setAtAddress(optopRegister, 3);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "3");
           optopRegister += 4;
           ++pcRegister;
           break;
       case OpCode.ICONST_4:
           stackMemorySection.setAtAddress(optopRegister, 4);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "4");
           optopRegister += 4;
           ++pcRegister;
           break;
       case OpCode.ICONST_5:
           stackMemorySection.setAtAddress(optopRegister, 5);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "5");
           optopRegister += 4;
           ++pcRegister;
           break;
       case OpCode.IFNE:
           optopRegister -= 4;
           a = stackMemorySection.getAtAddress(optopRegister);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
           // If a != 0 jump, else go on
           if (a != 0) {
               operand1 = methodAreaMemorySection.getAtAddress(pcRegister + 1);
               operand0 = methodAreaMemorySection.getAtAddress(pcRegister + 2);
               offset = (operand1 << 8) | (operand0 & 0xff);
               pcRegister += offset;
           }
           else {
               pcRegister += 3;
           }
           break;
       case OpCode.IF_ICMPLT:
           optopRegister -= 4;
           a = stackMemorySection.getAtAddress(optopRegister);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
           optopRegister -= 4;
           b = stackMemorySection.getAtAddress(optopRegister);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
           // If b < a jump, else go on
           if (b < a) {
               operand1 = methodAreaMemorySection.getAtAddress(pcRegister + 1);
               operand0 = methodAreaMemorySection.getAtAddress(pcRegister + 2);
               offset = (operand1 << 8) | (operand0 & 0xff);
               pcRegister += offset;
           }
           else {
               pcRegister += 3;
           }
           break;
       case OpCode.IINC:
           operand0 = methodAreaMemorySection.getAtAddress(pcRegister + 1);
           operand1 = methodAreaMemorySection.getAtAddress(pcRegister + 2);
           a = stackMemorySection.getAtAddress(varsRegister + (operand0 * 4));
           a += operand1;
           stackMemorySection.setAtAddress(varsRegister + (operand0 * 4), a);
           stackMemorySection.setLogicalValueAtAddress(varsRegister + (operand0 * 4), Integer.toString(a));
           pcRegister += 3;
           break;
       case OpCode.ILOAD_0:
           a = stackMemorySection.getAtAddress(varsRegister);
           stackMemorySection.setAtAddress(optopRegister, a);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, Integer.toString(a));
           optopRegister += 4;
           ++pcRegister;
           break;
       case OpCode.ILOAD_1:
           a = stackMemorySection.getAtAddress(varsRegister + 4);
           stackMemorySection.setAtAddress(optopRegister, a);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, Integer.toString(a));
           optopRegister += 4;
           ++pcRegister;
           break;
       case OpCode.ILOAD_2:
           a = stackMemorySection.getAtAddress(varsRegister + 8);
           stackMemorySection.setAtAddress(optopRegister, a);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, Integer.toString(a));
           optopRegister += 4;
           ++pcRegister;
           break;
       case OpCode.ILOAD_3:
           a = stackMemorySection.getAtAddress(varsRegister + 12);
           stackMemorySection.setAtAddress(optopRegister, a);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, Integer.toString(a));
           optopRegister += 4;
           ++pcRegister;
           break;
       case OpCode.IMUL:
           optopRegister -= 4;
           a = stackMemorySection.getAtAddress(optopRegister);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
           optopRegister -= 4;
           b = stackMemorySection.getAtAddress(optopRegister);
           result = a * b;
           stackMemorySection.setAtAddress(optopRegister, result);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, Integer.toString(result));
           optopRegister += 4;
           ++pcRegister;
           break;
       case OpCode.INT2BYTE:
           a = stackMemorySection.getAtAddress(optopRegister - 4);
           a = (byte) a;
           stackMemorySection.setAtAddress(optopRegister - 4, a);
           stackMemorySection.setLogicalValueAtAddress(optopRegister - 4, Integer.toString(a));
           ++pcRegister;
           break;
       case OpCode.IOR:
           optopRegister -= 4;
           a = stackMemorySection.getAtAddress(optopRegister);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
           optopRegister -= 4;
           b = stackMemorySection.getAtAddress(optopRegister);
           result = a | b;
           stackMemorySection.setAtAddress(optopRegister, result);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, Integer.toString(result));
           optopRegister += 4;
           ++pcRegister;
           break;
       case OpCode.ISHL:
           optopRegister -= 4;
           a = stackMemorySection.getAtAddress(optopRegister);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
           optopRegister -= 4;
           b = stackMemorySection.getAtAddress(optopRegister);
           result = b << (a & 0x1f);
           stackMemorySection.setAtAddress(optopRegister, result);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, Integer.toString(result));
           optopRegister += 4;
           ++pcRegister;
           break;
       case OpCode.ISTORE_0:
           optopRegister -= 4;
           a = stackMemorySection.getAtAddress(optopRegister);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
           stackMemorySection.setAtAddress(varsRegister, a);
           stackMemorySection.setLogicalValueAtAddress(varsRegister, Integer.toString(a));
           ++pcRegister;
           break;
       case OpCode.ISTORE_1:
           optopRegister -= 4;
           a = stackMemorySection.getAtAddress(optopRegister);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
           stackMemorySection.setAtAddress(varsRegister + 4, a);
           stackMemorySection.setLogicalValueAtAddress(varsRegister + 4, Integer.toString(a));
           ++pcRegister;
           break;
       case OpCode.ISTORE_2:
           optopRegister -= 4;
           a = stackMemorySection.getAtAddress(optopRegister);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
           stackMemorySection.setAtAddress(varsRegister + 8, a);
           stackMemorySection.setLogicalValueAtAddress(varsRegister + 8, Integer.toString(a));
           ++pcRegister;
           break;
       case OpCode.ISTORE_3:
           optopRegister -= 4;
           a = stackMemorySection.getAtAddress(optopRegister);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
           stackMemorySection.setAtAddress(varsRegister + 12, a);
           stackMemorySection.setLogicalValueAtAddress(varsRegister + 12, Integer.toString(a));
           ++pcRegister;
           break;
       case OpCode.IXOR:
           optopRegister -= 4;
           a = stackMemorySection.getAtAddress(optopRegister);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
           optopRegister -= 4;
           b = stackMemorySection.getAtAddress(optopRegister);
           result = a ^ b;
           stackMemorySection.setAtAddress(optopRegister, result);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, Integer.toString(result));
           optopRegister += 4;
           ++pcRegister;
           break;
       case OpCode.MULTIANEWARRAY:
           executeMultianewarray();
           pcRegister += 4;
           break;
       }
   }
   // Pushing the Reset button will cause ResetState() to be executed, which will
   // reset all the data to its initial values.
   void ResetState() {
       pcRegister = methodAreaBase;
       optopRegister = stackBase + SimData.optopOffset;
       frameRegister = stackBase + SimData.frameOffset;
       varsRegister = stackBase;
       int i;
       for (i = 0; i < SimData.stackMemorySectionSize; ++i) {
           stackMemorySection.setLogicalValueAtAddress(stackBase + (i * 4), "");
           stackMemorySection.setAtAddress(stackBase + (i * 4), 0);
       }
       methodAreaMemoryView.update(methodAreaMemorySection, methodAreaBase);
   }
   // UpdateStateDisplay writes the current state of the JVM to the UI.
   void UpdateStateDisplay() {
       registers.setPcRegister(pcRegister);
       registers.setOptopRegister(optopRegister);
       registers.setFrameRegister(frameRegister);
       registers.setVarsRegister(varsRegister);
       stackMemoryView.update(stackMemorySection, stackBase);
       methodAreaMemoryView.updateProgramCounter(pcRegister - methodAreaBase, methodAreaMemorySection);
       stackMemoryView.clearPointers();
       stackMemoryView.updatePointer((varsRegister - stackBase) / 4, StringTable.varsPointer);
       stackMemoryView.updatePointer((frameRegister - stackBase) / 4, StringTable.framePointer);
       stackMemoryView.updatePointer((optopRegister - stackBase) / 4, StringTable.optopPointer);
       int nextOpCode = methodAreaMemorySection.getAtAddress(pcRegister);
       switch (nextOpCode) {
       case OpCode.AALOAD:
           simulationController.setExplanationText(StringTable.aaloadText);
           break;
       case OpCode.ALOAD_0:
           simulationController.setExplanationText(StringTable.aload_0Text);
           break;
       case OpCode.ASTORE_0:
           simulationController.setExplanationText(StringTable.astore_0Text);
           break;
       case OpCode.BIPUSH:
           simulationController.setExplanationText(StringTable.bipushText);
           break;
       case OpCode.BREAKPOINT:
           simulationController.setExplanationText(StringTable.breakpointText);
           break;
       case OpCode.FCONST_0:
           simulationController.setExplanationText(StringTable.fconst_0Text);
           break;
       case OpCode.FCONST_2:
           simulationController.setExplanationText(StringTable.fconst_2Text);
           break;
       case OpCode.FLOAD_0:
           simulationController.setExplanationText(StringTable.fload_0Text);
           break;
       case OpCode.FMUL:
           simulationController.setExplanationText(StringTable.fmulText);
           break;
       case OpCode.FSTORE_0:
           simulationController.setExplanationText(StringTable.fstore_0Text);
           break;
       case OpCode.FSUB:
           simulationController.setExplanationText(StringTable.fsubText);
           break;
       case OpCode.GOTO:
           simulationController.setExplanationText(StringTable.gotoText);
           break;
       case OpCode.IADD:
           simulationController.setExplanationText(StringTable.iaddText);
           break;
       case OpCode.IAND:
           simulationController.setExplanationText(StringTable.iandText);
           break;
       case OpCode.IASTORE:
           simulationController.setExplanationText(StringTable.iastoreText);
           break;
       case OpCode.ICONST_M1:
           simulationController.setExplanationText(StringTable.iconst_m1Text);
           break;
       case OpCode.ICONST_0:
           simulationController.setExplanationText(StringTable.iconst_0Text);
           break;
       case OpCode.ICONST_1:
           simulationController.setExplanationText(StringTable.iconst_1Text);
           break;
       case OpCode.ICONST_2:
           simulationController.setExplanationText(StringTable.iconst_2Text);
           break;
       case OpCode.ICONST_3:
           simulationController.setExplanationText(StringTable.iconst_3Text);
           break;
       case OpCode.ICONST_4:
           simulationController.setExplanationText(StringTable.iconst_4Text);
           break;
       case OpCode.ICONST_5:
           simulationController.setExplanationText(StringTable.iconst_5Text);
           break;
       case OpCode.IF_ICMPLT:
           simulationController.setExplanationText(StringTable.if_icmpltText);
           break;
       case OpCode.IFNE:
           simulationController.setExplanationText(StringTable.ifneText);
           break;
       case OpCode.IINC:
           simulationController.setExplanationText(StringTable.iincText);
           break;
       case OpCode.ILOAD_0:
           simulationController.setExplanationText(StringTable.iload_0Text);
           break;
       case OpCode.ILOAD_1:
           simulationController.setExplanationText(StringTable.iload_1Text);
           break;
       case OpCode.ILOAD_2:
           simulationController.setExplanationText(StringTable.iload_2Text);
           break;
       case OpCode.ILOAD_3:
           simulationController.setExplanationText(StringTable.iload_3Text);
           break;
       case OpCode.IMUL:
           simulationController.setExplanationText(StringTable.imulText);
           break;
       case OpCode.INT2BYTE:
           simulationController.setExplanationText(StringTable.int2byteText);
           break;
       case OpCode.IOR:
           simulationController.setExplanationText(StringTable.iorText);
           break;
       case OpCode.ISHL:
           simulationController.setExplanationText(StringTable.ishlText);
           break;
       case OpCode.ISTORE_0:
           simulationController.setExplanationText(StringTable.istore_0Text);
           break;
       case OpCode.ISTORE_1:
           simulationController.setExplanationText(StringTable.istore_1Text);
           break;
       case OpCode.ISTORE_2:
           simulationController.setExplanationText(StringTable.istore_2Text);
           break;
       case OpCode.ISTORE_3:
           simulationController.setExplanationText(StringTable.istore_3Text);
           break;
       case OpCode.IXOR:
           simulationController.setExplanationText(StringTable.ixorText);
           break;
       case OpCode.MULTIANEWARRAY:
           simulationController.setExplanationText(StringTable.multianewarrayText);
           break;
       default:
           simulationController.setExplanationText("");
           break;
       }
   }
   // Make pretty border around entire applet panel
   public Insets insets() {
       return new Insets(5, 5, 5, 5);
   }
   public void stop() {
       if (runner != null) {
           runner.stop();
           runner = null;
       }
   }
   public void run() {
       while (true) {
           ExecuteNextInstruction();
           UpdateStateDisplay();
           try {
               Thread.sleep(millisecondDelayBetweenSteps);
           }
           catch (InterruptedException e) {
           }
       }
   }
   void executeAaload() {
       // Pop array index.
       optopRegister -= 4;
       int index = stackMemorySection.getAtAddress(optopRegister);
       stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
       // Pop reference to array of object references.
       // Cast generic object reference to a reference to an array of objects. This
       // will cause the JVM to do a checkcast instruction to make sure this is a
       // valid operation. An exception will be thrown if I"ve got any other kind
       // of array or object reference. Once this succeeds, I can use the arrayRef
       // as an array to get the index"th object reference and push it.
       optopRegister -= 4;
       Object objRef = stackMemorySection.getObjectAtAddress(optopRegister);
       Object[] arrayRef = (Object[]) objRef;
       // Push the object reference at arrayRef[index].
       stackMemorySection.setObjectAtAddress(optopRegister, arrayRef[index]);
       stackMemorySection.setLogicalValueAtAddress(optopRegister, StringTable.objectReference);
       optopRegister += 4;
       ++pcRegister;
   }
   void executeAload_n(int locVar) {
       Object objRef = stackMemorySection.getObjectAtAddress(varsRegister + (4 * locVar));
       stackMemorySection.setObjectAtAddress(optopRegister, objRef);
       stackMemorySection.setLogicalValueAtAddress(optopRegister, StringTable.objectReference);
       optopRegister += 4;
       ++pcRegister;
   }
   void executeAstore_n(int locVar) {
       optopRegister -= 4;
       Object objRef = stackMemorySection.getObjectAtAddress(optopRegister);
       stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
       stackMemorySection.setObjectAtAddress(varsRegister + (4 * locVar), objRef);
       stackMemorySection.setLogicalValueAtAddress(varsRegister + (4 * locVar), StringTable.objectReference);
       ++pcRegister;
   }
   void executeIastore() {
       // Pop int value.
       optopRegister -= 4;
       int value = stackMemorySection.getAtAddress(optopRegister);
       stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
       // Pop index.
       optopRegister -= 4;
       int index = stackMemorySection.getAtAddress(optopRegister);
       stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
       // Pop reference to an array of integers. Must cast the generic object
       // reference to a reference to an array of integers, then use that
       // to assign arrayRef[index] = value.
       optopRegister -= 4;
       Object objRef = stackMemorySection.getObjectAtAddress(optopRegister);
       stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
       int[] arrayRef = (int[]) objRef;
       arrayRef[index] = value;
       ++pcRegister;
   }
   void executeMultianewarray() {
       int indexbyte1 = methodAreaMemorySection.getAtAddress(pcRegister + 1);
       int indexbyte0 = methodAreaMemorySection.getAtAddress(pcRegister + 2);
       int dim = methodAreaMemorySection.getAtAddress(pcRegister + 3);
       if (dim < 1) {
           // this is an exception
           return;
       }
       // Fill an array with the sizes of the various arrays. The sizes go into the
       // array in the order in which they appear in the declaration, left to right.
       // This was the same order in which they were pushed onto the stack. Therefore,
       // the first element is assigned the value most buried (furthest down) in the
       // stack.
       int[] size = new int[dim];
       for (int i = dim - 1; i >= 0; --i) {
           optopRegister -= 4;
           size[i] = stackMemorySection.getAtAddress(optopRegister);
           stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
       }
       // This time around, I"ll just assume it"s an array of ints. In the future, I"ll
       // need to check the constant pool and pass down the type.
       Object result = createMultiDimArray(size);
       stackMemorySection.setObjectAtAddress(optopRegister, result);
       stackMemorySection.setLogicalValueAtAddress(optopRegister, StringTable.objectReference);
       optopRegister += 4;
   }
   Object createMultiDimArray(int[] size) {
       Object result;
       if (size.length == 1) {
           result = new int[size[0]];
       }
       else {
           // Create and initialize an array of arrays
           Object[] arrayOfArrays = new Object[size[0]];
           result = arrayOfArrays;
           // As soon as a size of zero is hit for the next array, we are done. This
           // will be the case if some of the square brackets were left empty in
           // the declaration, as in "new int[5][4][][]," in which the third and fourth
           // sizes will be zero.
           if (size[1] != 0) {
               // Create and initialize an array of sizes to be passed to a recursive call
               // to createMultiDimArray(). This array is identical to the array passed
               // to this function with the first element clipped off.
               int[] nextSize = new int[size.length - 1];
               for (int i = 1; i < size.length; ++i) {
                   nextSize[i - 1] = size[i];
               }
               // Call this function recursively to create initialize this array
               // of array with the sub-arrays.
               for (int i = 0; i < size[0]; ++i) {
                   arrayOfArrays[i] = createMultiDimArray(nextSize);
               }
           }
       }
       return result;
   }

} // 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 ControlPanel extends Panel {

   private ColoredLabel explanationLabel;
   private GrayButton stepButton = new GrayButton(StringTable.step);
   private GrayButton resetButton = new GrayButton(StringTable.reset);
   private GrayButton runButton = new GrayButton(StringTable.run);
   private GrayButton stopButton = new GrayButton(StringTable.stop);
   ControlPanel() {
       setLayout(new BorderLayout(5, 5));
       Panel leftButtonPanel = new Panel();
       leftButtonPanel.setLayout(new GridLayout(2,2,5,5));
       leftButtonPanel.add(stepButton);
       resetButton.disable();
       leftButtonPanel.add(runButton);
       leftButtonPanel.add(resetButton);
       leftButtonPanel.add(stopButton);
       stopButton.disable();
       explanationLabel = new ColoredLabel("This is where the explanation goes...",
           Label.CENTER, Color.lightGray);
       explanationLabel.setBackground(SimData.explanationLabel);
       Font plainFont = new Font("TimesRoman", Font.ITALIC, 12);
       explanationLabel.setFont(plainFont);
       add("West", leftButtonPanel);
       add("Center", explanationLabel);
   }
   public void setExplanationText(String explanation) {
       explanationLabel.setLabelText(explanation);
   }
   public Button getStepButton() {
       return stepButton;
   }
   public Button getResetButton() {
       return resetButton;
   }
   public Button getRunButton() {
       return runButton;
   }
   public Button getStopButton() {
       return stopButton;
   }
   public Insets insets() {
       // top, left, bottom, right
       return new Insets(0, 0, 0, 0);
   }

} class GrayButton extends Button {

   GrayButton(String label) {
       super(label);
       setBackground(Color.lightGray);
   }

} // GridSnapLayout lays out components in a grid that can have columns of // varying width. This is not a very general purpose layout manager. It // solves the specific problem of getting all the information I want to display about // the stack and method areas in a nice grid. Because some columns of info need // more room than others, and space is limited on a web page, I needed to be // able to specify varying widths of columns in a grid. class GridSnapLayout implements LayoutManager {

   // rows and cols are the number of rows and columns of the grid upon
   // which the components are placed. Components are always one row
   // in height, but may be more than one column in width. The number
   // of columns width of each component is stored in hComponentCellWidths.
   // The array length of hComponentCellWidths indicates the number of
   // components that will appear on each row.
   private int rows;
   private int cols;
   private int[] hComponentCellWidths;
   public GridSnapLayout(int rows, int cols, int[] hComponentCellWidths) {
     this.rows = rows;
     this.cols = cols;
     this.hComponentCellWidths = hComponentCellWidths;
   }
   public void addLayoutComponent(String name, Component comp) {
   }
   public void removeLayoutComponent(Component comp) {
   }
   // Calculate preferred size as if each component were taking an equal
   // share of the width of a row.
   public Dimension preferredLayoutSize(Container parent) {
     int rowCount = rows;
     int colCount = cols;
     Insets parentInsets = parent.insets();
     int componentCount = parent.countComponents();
     if (rowCount > 0) {
         colCount = (componentCount + rowCount - 1) / rowCount;
     } else {
         rowCount = (componentCount + colCount - 1) / colCount;
     }
       // Find the maximum preferred width and the maximum preferred height
       // of any component.
     int w = 0;
     int h = 0;
     for (int i = 0; i < componentCount; i++) {
         Component comp = parent.getComponent(i);
         Dimension d = comp.preferredSize();
         if (w < d.width) {
           w = d.width;
         }
         if (h < d.height) {
           h = d.height;
         }
     }
     // Return the maximum preferred component width and height times the number
     // of columns and rows, respectively, plus any insets in the parent.
     return new Dimension(parentInsets.left + parentInsets.right + colCount*w,
         parentInsets.top + parentInsets.bottom + rowCount*h);
   }
   // Calculate minimum size as if each component were taking an equal
   // share of the width of a row.
   public Dimension minimumLayoutSize(Container parent) {
     Insets parentInsets = parent.insets();
     int componentCount = parent.countComponents();
     int rowCount = rows;
     int colCount = cols;
     if (rowCount > 0) {
         colCount = (componentCount + rowCount - 1) / rowCount;
     } else {
         rowCount = (componentCount + colCount - 1) / colCount;
     }
       // Find the maximum "minimum width" and the maximum "minimum height"
       // of any component.
     int w = 0;
     int h = 0;
     for (int i = 0; i < componentCount; i++) {
         Component comp = parent.getComponent(i);
         Dimension d = comp.minimumSize();
         if (w < d.width) {
           w = d.width;
         }
         if (h < d.height) {
           h = d.height;
         }
     }
     // Return the maximum "minimum component width and height" times the number
     // of columns and rows, respectively, plus any insets in the parent.
     return new Dimension(parentInsets.left + parentInsets.right + colCount*w,
         parentInsets.top + parentInsets.bottom + rowCount*h);
   }
   // Layout the container such that the widths of columns correspond
   // to the number of columns in that components hComponentCellWidth
   // array element. For example, if the
   public void layoutContainer(Container parent) {
     int rowCount = rows;
     int colCount = hComponentCellWidths.length;
     Insets parentInsets = parent.insets();
     int componentCount = parent.countComponents();
     if (componentCount == 0) {
         return;
     }
       // Calculate the width and height of each grid cell. The height will
       // be the height of each component, but the width may not. The width
       // of a component will be some multiple of a grid cell width. The
       // number of grid cells for each component is defined by the
       // hComponentCellWidths array. w is width of each grid cell. h is
       // height of each grid cell.
     Dimension parentDim = parent.size();
     int w = parentDim.width - (parentInsets.left + parentInsets.right);
     int h = parentDim.height - (parentInsets.top + parentInsets.bottom);
     w /= cols;
     h /= rowCount;
       // For each row and column of components (not grid cells) position
       // the component.
     for (int c = 0, x = parentInsets.left ; c < colCount ; c++) {
         for (int r = 0, y = parentInsets.top ; r < rowCount ; r++) {
           int i = r * colCount + c;
           if (i < componentCount) {
               parent.getComponent(i).reshape(x, y, w * hComponentCellWidths[c], h);
           }
           y += h;
         }
         x += (w * hComponentCellWidths[c]);
     }
   }

} class HexString {

   private final String hexChar = "0123456789abcdef";
   private StringBuffer buf = new StringBuffer();
   void Convert(int val, int maxNibblesToConvert) {
       buf.setLength(0);
       int v = val;
       for (int i = 0; i < maxNibblesToConvert; ++i) {
           if (v == 0) {
               if (i == 0) {
                   buf.insert(0, "0");
               }
               break;
           }
           // Get lowest nibble
           int remainder = v & 0xf;
           // Convert nibble to a character and insert it into the beginning of the string
           buf.insert(0, hexChar.charAt(remainder));
           // Shift the int to the right four bits
           v >>>= 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();
   }

} class LabeledRegister extends Panel {

   private ColoredLabel registerContents;
   LabeledRegister(String labelText) {
       setLayout(new BorderLayout(5,5));
       registerContents = new ColoredLabel("00000000", Label.CENTER, Color.lightGray);
       registerContents.setFont(new Font("TimesRoman", Font.PLAIN, 11));
       Label title = new Label(labelText, Label.RIGHT);
       title.setFont(new Font("Helvetica", Font.ITALIC, 11));
       add("East", registerContents);
       add("Center", title);
   }
   public void setRegister(int val) {
       HexString hexString = new HexString(val, 8);
       registerContents.setLabelText(hexString.getString());
   }
   public Insets insets() {
       return new Insets(0, 0, 0, 0);
   }

}

// MemorySection is just used for the method area in this applet. This implements // the functionality of the method area and has nothing to do with the UI. class MemorySection {

   private int[] memory;
   private int baseAddress;
   private String[] logicalValueString;
   MemorySection(int base, int size) {
       baseAddress = base;
       memory = new int[size];
       logicalValueString = new String[size];
       for (int i = 0; i < size; ++i) {
           logicalValueString[i] = new String();
       }
   }
   int getBaseAddress() {
       return baseAddress;
   }
   public int getAtAddress(int address) {
       return memory[address - baseAddress];
   }
   public String getLogicalValueAtAddress(int address) {
       return logicalValueString[address - baseAddress];
   }
   public void setAtAddress(int address, int value) {
       memory[address - baseAddress] = value;
   }
   public void setLogicalValueAtAddress(int address, String s) {
       logicalValueString[address - baseAddress] = s;
   }
   int getSize() {
       return memory.length;
   }

} // MemoryView is just used for the method area in this applet. It implements the // UI of the method area. class MemoryView extends Panel {

   private final int memoryLocationsVisibleCount = SimData.methodAreaMemoryLocationsVisibleCount;
   private Label[] pointer = new Label[memoryLocationsVisibleCount];
   private Label[] address = new Label[memoryLocationsVisibleCount];
   private Label[] byteValue = new Label[memoryLocationsVisibleCount];
   private Label[] logicalValue = new Label[memoryLocationsVisibleCount];
   private int firstVisibleRow;
   private int currentProgramCounterRow;
   MemoryView(int methodAreaMemSectionSize) {
       int[] hComponentCellWidths = new int[4];
       hComponentCellWidths[0] = 2;
       hComponentCellWidths[1] = 2;
       hComponentCellWidths[2] = 2;
       hComponentCellWidths[3] = 3;
       setLayout(new GridSnapLayout(memoryLocationsVisibleCount, 9, hComponentCellWidths));
       setBackground(Color.lightGray);
       Font plainFont = new Font("TimesRoman", Font.PLAIN, 11);
       setFont(plainFont);
       Font italicFont = new Font("TimesRoman", Font.ITALIC, 11);
       for (int i = 0; i < memoryLocationsVisibleCount; ++i) {
           pointer[i] = new Label("", Label.RIGHT);
           pointer[i].setFont(italicFont);
           add(pointer[i]);
           address[i] = new Label("", Label.CENTER);
           add(address[i]);
           byteValue[i] = new Label("", Label.CENTER);
           add(byteValue[i]);
           logicalValue[i] = new Label("", Label.LEFT);
           add(logicalValue[i]);
       }
   }
   public void setAt(int i, int addressValue, int value, String logicalValueStr) {
       HexString addressValueHexString = new HexString(addressValue, 8);
       HexString byteValueHexString = new HexString(value, 2);
       address[i].setText(addressValueHexString.getString());
       byteValue[i].setText(byteValueHexString.getString());
       logicalValue[i].setText(logicalValueStr);
   }
   public void update(MemorySection memorySection, int initialAddress){
       for (int i = 0; i < memoryLocationsVisibleCount; ++i) {
           int theByte = memorySection.getAtAddress(initialAddress + i);
           String logicalValue = memorySection.getLogicalValueAtAddress(
               initialAddress + i);
           setAt(i, initialAddress + i, theByte, logicalValue);
       }
   }
   public void clearPointers() {
       for (int i = 0; i < memoryLocationsVisibleCount; ++i) {
           pointer[i].setText("");
       }
   }
   public void updateProgramCounter(int i, MemorySection memorySection) {
       pointer[currentProgramCounterRow - firstVisibleRow].setText("");
       if (i - firstVisibleRow >= memoryLocationsVisibleCount) {
           firstVisibleRow = i;
           if (firstVisibleRow > memorySection.getSize() - memoryLocationsVisibleCount) {
               firstVisibleRow = memorySection.getSize() - memoryLocationsVisibleCount;
           }
           update(memorySection, memorySection.getBaseAddress() + firstVisibleRow);
       }
       else if (i < firstVisibleRow) {
           firstVisibleRow = i;
           update(memorySection, memorySection.getBaseAddress() + firstVisibleRow);
       }
       pointer[i - firstVisibleRow].setText("pc >");
       currentProgramCounterRow = i;
   }
   public Insets insets() {
       // top, left, bottom, right
       return new Insets(0, 0, 0, 0);
   }

} class MemoryViewTitlePanel extends Panel {

   MemoryViewTitlePanel () {
       int[] hComponentCellWidths = new int[4];
       hComponentCellWidths[0] = 2;
       hComponentCellWidths[1] = 2;
       hComponentCellWidths[2] = 2;
       hComponentCellWidths[3] = 3;
       setLayout(new GridSnapLayout(1, 9, hComponentCellWidths));
       setFont(new Font("Helvetica", Font.ITALIC, 11));
       add(new Label("", Label.CENTER));
       add(new Label(StringTable.address, Label.CENTER));
       add(new Label(StringTable.bytecodes, Label.CENTER));
       add(new Label(StringTable.mnemonics, Label.LEFT));
   }
   public Insets insets() {
       // top, left, bottom, right
       return new Insets(0, 0, 0, 0);
   }

} class MemoryViewWithTitles extends Panel {

   private MemoryView memoryView;
   MemoryViewWithTitles(int methodAreaMemorySectionSize) {
       memoryView = new MemoryView(methodAreaMemorySectionSize);
       setLayout(new BorderLayout());
       add("North", new MemoryViewTitlePanel());
       add("Center", memoryView);
   }
   public MemoryView getMemoryViewReference(){
       return memoryView;
   }
   public Insets insets() {
       // top, left, bottom, right
       return new Insets(0, 0, 0, 0);
   }

} class MethodAreaPanel extends Panel {

   private Label title;
   private MemoryViewWithTitles memoryView;
   MethodAreaPanel(int methodAreaMemorySectionSize) {
       memoryView = new MemoryViewWithTitles(methodAreaMemorySectionSize);
       setLayout(new BorderLayout());
       title = new Label("Method Area", Label.CENTER);
       title.setFont(new Font("Helvetica", Font.BOLD, 11));
       add("North", title);
       add("Center", memoryView);
   }
   public MemoryView getMemoryViewReference() {
       return memoryView.getMemoryViewReference();
   }
   public Insets insets() {
       return new Insets(5, 5, 5, 5);
   }

}

class OpCode {

   final static int NOP = 0;
   final static int ACONST_NULL = 1;
   final static int ICONST_M1 = 2;
   final static int ICONST_0 = 3;
   final static int ICONST_1 = 4;
   final static int ICONST_2 = 5;
   final static int ICONST_3 = 6;
   final static int ICONST_4 = 7;
   final static int ICONST_5 = 8;
   final static int LCONST_0 = 9;
   final static int LCONST_1 = 10;
   final static int FCONST_0 = 11;
   final static int FCONST_1 = 12;
   final static int FCONST_2 = 13;
   final static int DCONST_0 = 14;
   final static int DCONST_1 = 15;
   final static int BIPUSH = 16;
   final static int SIPUSH = 17;
   final static int LDC1 = 18;
   final static int LDC2 = 19;
   final static int LDC2W = 20;
   final static int ILOAD = 21;
   final static int LLOAD = 22;
   final static int FLOAD = 23;
   final static int DLOAD = 24;
   final static int ALOAD = 25;
   final static int ILOAD_0 = 26;
   final static int ILOAD_1 = 27;
   final static int ILOAD_2 = 28;
   final static int ILOAD_3 = 29;
   final static int LLOAD_0 = 30;
   final static int LLOAD_1 = 31;
   final static int LLOAD_2 = 32;
   final static int LLOAD_3 = 33;
   final static int FLOAD_0 = 34;
   final static int FLOAD_1 = 35;
   final static int FLOAD_2 = 36;
   final static int FLOAD_3 = 37;
   final static int DLOAD_0 = 38;
   final static int DLOAD_1 = 39;
   final static int DLOAD_2 = 40;
   final static int DLOAD_3 = 41;
   final static int ALOAD_0 = 42;
   final static int ALOAD_1 = 43;
   final static int ALOAD_2 = 44;
   final static int ALOAD_3 = 45;
   final static int IALOAD = 46;
   final static int LALOAD = 47;
   final static int FALOAD = 48;
   final static int DALOAD = 49;
   final static int AALOAD = 50;
   final static int BALOAD = 51;
   final static int CALOAD = 52;
   final static int SALOAD = 53;
   final static int ISTORE = 54;
   final static int LSTORE = 55;
   final static int FSTORE = 56;
   final static int DSTORE = 57;
   final static int ASTORE = 58;
   final static int ISTORE_0 = 59;
   final static int ISTORE_1 = 60;
   final static int ISTORE_2 = 61;
   final static int ISTORE_3 = 62;
   final static int LSTORE_0 = 63;
   final static int LSTORE_1 = 64;
   final static int LSTORE_2 = 65;
   final static int LSTORE_3 = 66;
   final static int FSTORE_0 = 67;
   final static int FSTORE_1 = 68;
   final static int FSTORE_2 = 69;
   final static int FSTORE_3 = 70;
   final static int DSTORE_0 = 71;
   final static int DSTORE_1 = 72;
   final static int DSTORE_2 = 73;
   final static int DSTORE_3 = 74;
   final static int ASTORE_0 = 75;
   final static int ASTORE_1 = 76;
   final static int ASTORE_2 = 77;
   final static int ASTORE_3 = 78;
   final static int IASTORE = 79;
   final static int LASTORE = 80;
   final static int FASTORE = 81;
   final static int DASTORE = 82;
   final static int AASTORE = 83;
   final static int BASTORE = 84;
   final static int CASTORE = 85;
   final static int SASTORE = 86;
   final static int POP = 87;
   final static int POP2 = 88;
   final static int DUP = 89;
   final static int DUP_X1 = 90;
   final static int DUP_X2 = 91;
   final static int DUP2 = 92;
   final static int DUP2_X1 = 93;
   final static int DUP2_X2 = 94;
   final static int SWAP = 95;
   final static int IADD = 96;
   final static int LADD = 97;
   final static int FADD = 98;
   final static int DADD = 99;
   final static int ISUB = 100;
   final static int LSUB = 101;
   final static int FSUB = 102;
   final static int DSUB = 103;
   final static int IMUL = 104;
   final static int LMUL = 105;
   final static int FMUL = 106;
   final static int DMUL = 107;
   final static int IDIV = 108;
   final static int LDIV = 109;
   final static int FDIV = 110;
   final static int DDIV = 111;
   final static int IREM = 112;
   final static int LREM = 113;
   final static int FREM = 114;
   final static int DREM = 115;
   final static int INEG = 116;
   final static int LNEG = 117;
   final static int FNEG = 118;
   final static int DNEG = 119;
   final static int ISHL = 120;
   final static int LSHL = 121;
   final static int ISHR = 122;
   final static int LSHR = 123;
   final static int IUSHR = 124;
   final static int LUSHR = 125;
   final static int IAND = 126;
   final static int LAND = 127;
   final static int IOR = 128;
   final static int LOR = 129;
   final static int IXOR = 130;
   final static int LXOR = 131;
   final static int IINC = 132;
   final static int I2L = 133;
   final static int I2F = 134;
   final static int I2D = 135;
   final static int L2I = 136;
   final static int L2F = 137;
   final static int L2D = 138;
   final static int F2I = 139;
   final static int F2L = 140;
   final static int F2D = 141;
   final static int D2I = 142;
   final static int D2L = 143;
   final static int D2F = 144;
   final static int INT2BYTE = 145;
   final static int INT2CHAR = 146;
   final static int INT2SHORT = 147;
   final static int LCMP = 148;
   final static int FCMPL = 149;
   final static int FCMPG = 150;
   final static int DCMPL = 151;
   final static int DCMPG = 152;
   final static int IFEQ = 153;
   final static int IFNE = 154;
   final static int IFLT = 155;
   final static int IFGE = 156;
   final static int IFGT = 157;
   final static int IFLE = 158;
   final static int IF_ICMPEQ = 159;
   final static int IF_ICMPNE = 160;
   final static int IF_ICMPLT = 161;
   final static int IF_ICMPGT = 163;
   final static int IF_ICMPLE = 164;
   final static int IF_ICMPGE = 162;
   final static int IF_ACMPEQ = 165;
   final static int IF_ACMPNE = 166;
   final static int GOTO = 167;
   final static int JSR = 168;
   final static int RET = 169;
   final static int TABLESWITCH = 170;
   final static int LOOKUPSWITCH = 171;
   final static int IRETURN = 172;
   final static int LRETURN = 173;
   final static int FRETURN = 174;
   final static int DRETURN = 175;
   final static int ARETURN = 176;
   final static int RETURN = 177;
   final static int INVOKEVIRTUAL = 182;
   final static int INVOKENONVIRTUAL = 183;
   final static int INVOKESTATIC = 184;
   final static int INVOKEINTERFACE = 185;
   final static int NEW = 187;
   final static int NEWARRAY = 188;
   final static int ANEWARRAY = 189;
   final static int ARRAYLENGTH = 190;
   final static int ATHROW = 191;
   final static int CHECKCAST = 192;
   final static int INSTANCEOF = 193;
   final static int MONITORENTER = 194;
   final static int MONITOREXIT = 195;
   final static int WIDE = 196;
   final static int MULTIANEWARRAY = 197;
   final static int IFNULL = 198;
   final static int IFNONNULL = 199;
   final static int GOTO_W = 200;
   final static int JSR_W = 201;
   final static int BREAKPOINT = 202;
   final static int RET_W = 209;

} class RegisterPanel extends Panel {

   private LabeledRegister pcRegister;
   private LabeledRegister optopRegister;
   private LabeledRegister frameRegister;
   private LabeledRegister varsRegister;
   RegisterPanel() {
       setLayout(new BorderLayout(5,5));
       pcRegister = new LabeledRegister(StringTable.pc);
       optopRegister = new LabeledRegister(StringTable.optop);
       frameRegister = new LabeledRegister(StringTable.frame);
       varsRegister = new LabeledRegister(StringTable.vars);
       setBackground(SimData.registersAreaColor);
       Panel labeledRegisterPanel = new Panel();
       labeledRegisterPanel.setLayout(new GridLayout(1, 4, 5, 5));
       labeledRegisterPanel.add(pcRegister);
       labeledRegisterPanel.add(optopRegister);
       labeledRegisterPanel.add(frameRegister);
       labeledRegisterPanel.add(varsRegister);
       Label title = new Label(StringTable.Registers, Label.CENTER);
       title.setFont(new Font("Helvetica", Font.BOLD, 11));
       add("West", title);
       add("Center", labeledRegisterPanel);
   }
   public void setPcRegister(int val) {
       pcRegister.setRegister(val);
   }
   public void setOptopRegister(int val) {
       optopRegister.setRegister(val);
   }
   public void setFrameRegister(int val) {
       frameRegister.setRegister(val);
   }
   public void setVarsRegister(int val) {
       varsRegister.setRegister(val);
   }
   public Insets insets() {
       // top, left, bottom, right
       return new Insets(5, 5, 5, 5);
   }

} class RepeaterButton extends GrayButton {

   RepeaterButton(String label) {
       super(label);
   }

} // SimData is like a personality module for the JVMSimulator. It contains all // the data that is unique to this particular simulation applet. class SimData {

   public final static String appletTitle = "THREE DIMENSIONAL ARRAY";
   // stackSize, localsSize, and argsSize define the size of the stack for
   // one method, which each simulator executes. These three sizes vary for
   // each method and can be found for a method by running javap -v on the
   // class file. The execEnvSize is constant for every method and only
   // depends on how the JVM was implemented.
   static final int stackSize = 4;
   static final int localsSize = 4;
   static final int argsSize = 0;
   static final int execEnvSize = 4;
   // methodArea sizes are based on the length of the bytecode stream for
   // this method.
   static final int methodAreaMemorySectionSize = 60;
   static final int methodAreaMemoryLocationsVisibleCount = 13;
   // stack sizes are based on the sizes of each portion of the stack (local
   // variables, execution environment, and operands) that are defined above
   // for the method simulated by this applet. One is added to stackMemorySectionSize
   // because this JVM implementation has the optop register pointing to the
   // next available slot in the stack instead of the current top. This means
   // that when the operand stack is full, I still need one more slot to show
   // the location that is pointed to by the optop register, even though we
   // know nothing will ever be pushed there by this method.
   static final int stackMemorySectionSize = stackSize + localsSize + argsSize + execEnvSize + 1;
   static final int stackMemoryLocationsVisibleCount = stackMemorySectionSize;
   static final int frameOffset = (4 * localsSize) + (4 * argsSize); // 4 bytes for each local variable
   static final int optopOffset = frameOffset + (4 * execEnvSize); // 4 bytes for each loc var & exec env slot
   static int[] theProgram = {
       OpCode.ICONST_5,
       OpCode.ICONST_4,
       OpCode.ICONST_3,
       OpCode.MULTIANEWARRAY, (byte) 0x00, (byte) 0x02, (byte) 0x03,
       OpCode.ASTORE_0,
       OpCode.ICONST_0,
       OpCode.ISTORE_1,
       OpCode.GOTO, (byte) 0x00, (byte) 0x2c,
       OpCode.ICONST_0,
       OpCode.ISTORE_2,
       OpCode.GOTO, (byte) 0x00, (byte) 0x1f,
       OpCode.ICONST_0,
       OpCode.ISTORE_3,
       OpCode.GOTO, (byte) 0x00, (byte) 0x12,
       OpCode.ALOAD_0,
       OpCode.ILOAD_1,
       OpCode.AALOAD,
       OpCode.ILOAD_2,
       OpCode.AALOAD,
       OpCode.ILOAD_3,
       OpCode.ILOAD_1,
       OpCode.ILOAD_2,
       OpCode.IADD,
       OpCode.ILOAD_3,
       OpCode.IADD,
       OpCode.IASTORE,
       OpCode.IINC, (byte) 0x03, (byte) 0x01,
       OpCode.ILOAD_3,
       OpCode.ICONST_3,
       OpCode.IF_ICMPLT, (byte) 0xff, (byte) 0xef,
       OpCode.IINC, (byte) 0x02, (byte) 0x01,
       OpCode.ILOAD_2,
       OpCode.ICONST_4,
       OpCode.IF_ICMPLT, (byte) 0xff, (byte) 0xe2,
       OpCode.IINC, (byte) 0x01, (byte) 0x01,
       OpCode.ILOAD_1,
       OpCode.ICONST_5,
       OpCode.IF_ICMPLT, (byte) 0xff, (byte) 0xd5,
       OpCode.BREAKPOINT
   };
   static String[] byteCodeMnemonics = {
       "iconst_5",
       "iconst_4",
       "iconst_3",
       "multianewarray 2 3", "", "", "",
       "astore_0",
       "iconst_0",
       "istore_1",
       "goto +44", "", "",
       "iconst_0",
       "istore_2",
       "goto +31", "", "",
       "iconst_0",
       "istore_3",
       "goto +18", "", "",
       "aload_0",
       "iload_1",
       "aaload",
       "iload_2",
       "aaload",
       "iload_3",
       "iload_1",
       "iload_2",
       "iadd",
       "iload_3",
       "iadd",
       "iastore",
       "iinc 3 1", "", "",
       "iload_3",
       "iconst_3",
       "if_icmplt -17", "", "",
       "iinc 2 1", "", "",
       "iload_2",
       "iconst_4",
       "if_icmplt -30", "", "",
       "iinc 1 1", "", "",
       "iload_1",
       "iconst_5",
       "if_icmplt -43", "", "",
       "breakpoint"
   };
   static final Color appletBackgroundColor = Color.blue;
   static final Color registersAreaColor = Color.cyan;
   static final Color stackAreaColor = Color.cyan;
   static final Color methodAreaColor = Color.cyan;
   static final Color titleColor = Color.green;
   static final Color explanationLabel = Color.green;

} // StackMemorySection is just used for the stack in this applet. This implements // the functionality of the stack and has nothing to do with the UI. A separate // array is used for primitive types and object references because there is no // way to convert between an object reference and a primitive type (that would // be a pointer.) The int array (memory) is used to store types boolean, byte, // char, short, int, long, float, and double. The object reference array (objectMemory) // is used to store references to objects and arrays. class StackMemorySection {

   private int[] memory;
   private Object[] objectMemory;
   private int baseAddress;
   private String[] logicalValueString;
   StackMemorySection(int base, int size) {
       baseAddress = base;
       memory = new int[size];
       objectMemory = new Object[size];
       logicalValueString = new String[size];
       for (int i = 0; i < size; ++i) {
           memory[i] = 0;
           logicalValueString[i] = new String();
       }
   }
   public int getAtAddress(int address) {
       return memory[(address - baseAddress) / 4];
   }
   public Object getObjectAtAddress(int address) {
       return objectMemory[(address - baseAddress) / 4];
   }
   public String getLogicalValueAtAddress(int address) {
       return logicalValueString[(address - baseAddress) / 4];
   }
   public void setAtAddress(int address, int value) {
       memory[(address - baseAddress) / 4] = value;
   }
   public void setObjectAtAddress(int address, Object value) {
       objectMemory[(address - baseAddress) / 4] = value;
   }
   public void setLogicalValueAtAddress(int address, String s) {
       logicalValueString[(address - baseAddress) / 4] = s;
   }

} // StackMemoryView is just used for the stack in this applet. It implements the // UI of the stack. class StackMemoryView extends Panel {

   private final int memoryLocationsVisibleCount = SimData.stackMemoryLocationsVisibleCount;
   private Label[] pointer = new Label[memoryLocationsVisibleCount];
   private Label[] address = new Label[memoryLocationsVisibleCount];
   private Label[] wordValue = new Label[memoryLocationsVisibleCount];
   private Label[] logicalValue = new Label[memoryLocationsVisibleCount];
   StackMemoryView () {
       int[] hComponentCellWidths = new int[4];
       hComponentCellWidths[0] = 2;
       hComponentCellWidths[1] = 2;
       hComponentCellWidths[2] = 2;
       hComponentCellWidths[3] = 3;
       setLayout(new GridSnapLayout(memoryLocationsVisibleCount, 9, hComponentCellWidths));
       setBackground(Color.lightGray);
       Font plainFont = new Font("TimesRoman", Font.PLAIN, 11);
       setFont(plainFont);
       Font italicFont = new Font("TimesRoman", Font.ITALIC, 11);
       for (int i = memoryLocationsVisibleCount - 1; i >= 0; --i) {
           pointer[i] = new Label("", Label.RIGHT);
           pointer[i].setFont(italicFont);
           add(pointer[i]);
           address[i] = new Label("", Label.CENTER);
           add(address[i]);
           wordValue[i] = new Label("", Label.CENTER);
           add(wordValue[i]);
           logicalValue[i] = new Label("", Label.CENTER);
           add(logicalValue[i]);
       }
   }
   public void setAt(int i, int addressValue, int value, String logicalValueString) {
       HexString addressValueString = new HexString(addressValue, 8);
       HexString wordValueString = new HexString(value, 8);
       address[memoryLocationsVisibleCount - 1 - i].setText(addressValueString.getString());
       wordValue[memoryLocationsVisibleCount - 1 - i].setText(wordValueString.getString());
       logicalValue[memoryLocationsVisibleCount - 1 - i].setText(logicalValueString);
   }
   public void update(StackMemorySection memorySection, int initialAddress){
       for (int i = 0; i < memoryLocationsVisibleCount; ++i) {
           int theWord = memorySection.getAtAddress(initialAddress + (i * 4));
           String logicalValue = memorySection.getLogicalValueAtAddress(
               initialAddress + (i * 4));
           setAt(i, initialAddress + (i * 4), theWord, logicalValue);
       }
   }
   public void clearPointers() {
       for (int i = 0; i < memoryLocationsVisibleCount; ++i) {
           pointer[i].setText("");
       }
   }
   public void updatePointer(int i, String pointerString) {
       pointer[memoryLocationsVisibleCount - 1 - i].setText(pointerString);
   }
   public Insets insets() {
       // top, left, bottom, right
       return new Insets(0, 0, 0, 0);
   }

} class StackMemoryViewTitlePanel extends Panel {

   StackMemoryViewTitlePanel () {
       int[] hComponentCellWidths = new int[4];
       hComponentCellWidths[0] = 2;
       hComponentCellWidths[1] = 2;
       hComponentCellWidths[2] = 2;
       hComponentCellWidths[3] = 3;
       setLayout(new GridSnapLayout(1, 9, hComponentCellWidths));
       setFont(new Font("Helvetica", Font.ITALIC, 11));
       add(new Label("", Label.CENTER));
       add(new Label(StringTable.address, Label.CENTER));
       add(new Label(StringTable.hexValue, Label.CENTER));
       add(new Label(StringTable.value, Label.CENTER));
   }
   public Insets insets() {
       // top, left, bottom, right
       return new Insets(0, 0, 0, 0);
   }

} class StackMemoryViewWithTitles extends Panel {

   private StackMemoryView memoryView = new StackMemoryView();
   StackMemoryViewWithTitles () {
       setLayout(new BorderLayout());
       add("North", new StackMemoryViewTitlePanel());
       add("Center", memoryView);
   }
   public StackMemoryView getMemoryViewReference(){
       return memoryView;
   }
   public Insets insets() {
       // top, left, bottom, right
       return new Insets(0, 0, 0, 0);
   }

} class StackPanel extends Panel {

   private Label title;
   private StackMemoryViewWithTitles memoryView = new StackMemoryViewWithTitles();
   StackPanel() {
       setLayout(new BorderLayout());
       title = new Label("Stack", Label.CENTER);
       title.setFont(new Font("Helvetica", Font.BOLD, 11));
       add("North", title);
       add("Center", memoryView);
   }
   public StackMemoryView getMemoryViewReference() {
       return memoryView.getMemoryViewReference();
   }
   public Insets insets() {
       return new Insets(5, 5, 5, 5);
   }

}

class StringTable {

   public final static String step = "Step";
   public final static String reset = "Reset";
   public final static String run = "Run";
   public final static String stop = "Stop";
   public final static String operand = "operand";
   public final static String execEnv = "exec env";
   public final static String localVars = "local vars";
   public final static String varsPointer = "vars >";
   public final static String framePointer = "frame >";
   public final static String optopPointer = "optop >";
   public final static String address = "address";
   public final static String bytecodes = "bytecode";
   public final static String mnemonics = "mnemonic";
   public final static String hexValue = "hex value";
   public final static String value = "value";
   public final static String Registers = "Registers";
   public final static String pc = "pc";
   public final static String optop = "optop";
   public final static String frame = "frame";
   public final static String vars = "vars";
   public final static String objectReference = "object";
   public final static String objectRefHexRepresentation = "OBJ REF";
   public final static String aaloadText = "aaload will pop an index and array reference and push the object ref at that index of the array.";
   public final static String aload_0Text = "aload_0 will push the object ref at local variable 0 onto the stack.";
   public final static String astore_0Text = "astore_0 will pop the object ref off the top of the stack and store it in local variable 0.";
   public final static String bipushText = "bipush will expand the next byte to an int and push it onto the stack.";
   public final static String breakpointText = "breakpoint will stop the simulation.";
   public final static String fconst_0Text = "fconst_0 will push float 0.0 onto the stack.";
   public final static String fconst_2Text = "fconst_2 will push float 2.0 onto the stack.";
   public final static String fload_0Text = "fload_0 will push the float at local variable 0 onto the stack.";
   public final static String fmulText = "fmul will pop two floats, multiply them, and push the result.";
   public final static String fstore_0Text = "fstore_0 will pop the float off the top of the stack and store it in local variable 0.";
   public final static String fsubText = "fsub will pop two floats, subtract them, and push the result.";
   public final static String gotoText = "goto will cause a jump to the specified offset.";
   public final static String iaddText = "iadd will pop the top two ints off the stack, add them, and push the result back onto the stack.";
   public final static String iandText = "iand will pop the top two ints off the stack, bitwise-and them, and push the result back onto the stack.";
   public final static String iastoreText = "iastore will pop an int value, an index, and an arrayref and assign arrayref[index] = value.";
   public final static String iconst_m1Text = "iconst_m1 will push -1 onto the stack.";
   public final static String iconst_0Text = "iconst_0 will push 0 onto the stack.";
   public final static String iconst_1Text = "iconst_1 will push 1 onto the stack.";
   public final static String iconst_2Text = "iconst_2 will push 2 onto the stack.";
   public final static String iconst_3Text = "iconst_3 will push 3 onto the stack.";
   public final static String iconst_4Text = "iconst_4 will push 4 onto the stack.";
   public final static String iconst_5Text = "iconst_5 will push 5 onto the stack.";
   public final static String if_icmpltText = "if_icmplt will branch if the next to topmost int is less than the topmost int.";
   public final static String ifneText = "ifne will branch if the topmost int is not equal to zero.";
   public final static String iincText = "iinc will increment the specified local variable by the specified amount.";
   public final static String iload_0Text = "iload_0 will push the integer at local variable 0 onto the stack.";
   public final static String iload_1Text = "iload_1 will push the integer at local variable 1 onto the stack.";
   public final static String iload_2Text = "iload_2 will push the integer at local variable 2 onto the stack.";
   public final static String iload_3Text = "iload_3 will push the integer at local variable 3 onto the stack.";
   public final static String imulText = "imul will pop two integers, multiply them, and push the result.";
   public final static String int2byteText = "int2byte will convert the topmost int on the stack to a value valid for the byte type.";
   public final static String iorText = "ior will pop the top two ints off the stack, bitwise-or them, and push the result back onto the stack.";
   public final static String ishlText = "ishl will shift the next to topmost int to the left by amount indicated by topmost int.";
   public final static String istore_0Text = "istore_0 will pop the integer off the top of the stack and store it in local variable 0.";
   public final static String istore_1Text = "istore_1 will pop the integer off the top of the stack and store it in local variable 1.";
   public final static String istore_2Text = "istore_2 will pop the integer off the top of the stack and store it in local variable 2.";
   public final static String istore_3Text = "istore_3 will pop the integer off the top of the stack and store it in local variable 3.";
   public final static String ixorText = "ixor will pop the top two ints off the stack, biwise-xor them, and push the result back onto the stack.";
   public final static String multianewarrayText = "multianewarray will allocate memory for a new multi-dim array and push reference.";

}

class ThreeParts extends Panel {

   private RegisterPanel registers;
   private TwoParts twoParts;
   ThreeParts(int methodAreaMemorySectionSize) {
       setLayout(new BorderLayout(5, 5));
       registers = new RegisterPanel();
       twoParts = new TwoParts(methodAreaMemorySectionSize);
       add("North", registers);
       add("Center", twoParts);
   }
   StackMemoryView getStackMemoryViewReference() {
       return twoParts.getStackMemoryViewReference();
   }
   MemoryView getMethodAreaMemoryViewReference() {
       return twoParts.getMethodAreaMemoryViewReference();
   }
   RegisterPanel getRegisterPanel() {
       return registers;
   }

} // TwoParts is the panel that contains the Stack and Method Area panels class TwoParts extends Panel {

   private StackPanel stack;
   private MethodAreaPanel methodArea;
   TwoParts(int methodAreaMemorySectionSize) {
       setLayout(new GridLayout(1, 2, 5, 5));
       stack = new StackPanel();
       methodArea = new MethodAreaPanel(methodAreaMemorySectionSize);
       stack.setBackground(SimData.stackAreaColor);
       methodArea.setBackground(SimData.methodAreaColor);
       add(stack);
       add(methodArea);
   }
   public StackMemoryView getStackMemoryViewReference() {
       return stack.getMemoryViewReference();
   }
   public MemoryView getMethodAreaMemoryViewReference() {
       return methodArea.getMemoryViewReference();
   }
   // top, left, bottom, right
   // Want a 10 pixel separation between the twoparts and the register panel
   // above and the control panel below.
   public Insets insets() {
       return new Insets(0, 0, 0, 0);
   }

}


 </source>
   
  
 
  



JVM Tool Interface agent utilities

Logic and Integer Arithmetic

   <source lang="java">
  

/*

* Copyright (c) 1996 Artima Software Company. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for EVALUATION purposes only
* is hereby granted provided that this copyright notice
* appears in all copies. "Evaluation purposes" are any uses which
* do not constitute the sale, sharing, or redistribution of this
* software with or to any other persons in any medium.
*
* ARTIMA SOFTWARE COMPANY MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT
* THE SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. ARTIMA SOFTWARE COMPANY
* SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
* USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*
*/

/*

* ExposedInt.java
*
* This file contains all the code for the signed twos-complement int demo
* applet, named Exposed Int, that accompanies the JavaWorld Under The Hood
* article titled, "Logic and Integer Arithmetic".
*
* Bill Venners, September 1996
*
*/

import java.awt.*; import java.applet.*; /**

* An applet that interactively demonstrates the format and behavior
* of signed twos-complement ints in Java.
*
* @author      Bill Venners
*
*/

public class ExposedInt extends Applet {

   private Label binaryField;
   private Label hexField;
   private Label decimalField;
   private int value;
   private GrayButton maximumButton = new GrayButton(ExposedIntStringTable.max);
   private GrayButton minimumButton = new GrayButton(ExposedIntStringTable.min);
   private GrayButton zeroButton = new GrayButton(ExposedIntStringTable.zero);
   public void init() {
       Panel buttonPanel = new PanelWithInsets(0, 0, 0, 0);
       buttonPanel.setLayout(new GridLayout(3, 2, 5, 5));
       buttonPanel.add(new GrayButton(ExposedIntStringTable.increment));
       buttonPanel.add(new GrayButton(ExposedIntStringTable.decrement));
       buttonPanel.add(minimumButton);
       buttonPanel.add(maximumButton);
       buttonPanel.add(zeroButton);
       buttonPanel.add(new GrayButton(ExposedIntStringTable.negate));
       zeroButton.disable();
       binaryField = new Label("00000000000000000000000000000000");
       hexField = new Label("00000000");
       decimalField = new Label("0");
       Font fieldFont = new Font("TimesRoman", Font.PLAIN, 12);
       binaryField.setFont(fieldFont);
       hexField.setFont(fieldFont);
       decimalField.setFont(fieldFont);
       Panel numberPanel = new Panel();
       numberPanel.setBackground(Color.white);
       numberPanel.setLayout(new GridLayout(3, 1));
       Panel binaryPanel = new Panel();
       binaryPanel.setLayout(new BorderLayout());
       binaryPanel.add("Center", binaryField);
       numberPanel.add(binaryPanel);
       Panel hexPanel = new Panel();
       hexPanel.setLayout(new BorderLayout());
       hexPanel.add("Center", hexField);
       numberPanel.add(hexPanel);
       numberPanel.add(decimalField);
       Panel labelPanel = new Panel();
       labelPanel.setBackground(Color.white);
       labelPanel.setLayout(new GridLayout(3, 1));
       Label label = new Label(ExposedIntStringTable.binary, Label.CENTER);
       Font labelFont = new Font("Helvetica", Font.ITALIC, 11);
       label.setFont(labelFont);
       labelPanel.add(label);
       label = new Label(ExposedIntStringTable.hex, Label.CENTER);
       label.setFont(labelFont);
       labelPanel.add(label);
       label = new Label(ExposedIntStringTable.decimal, Label.CENTER);
       label.setFont(labelFont);
       labelPanel.add(label);
       Panel dataPanel = new Panel();
       dataPanel.setLayout(new BorderLayout());
       dataPanel.add("West", labelPanel);
       dataPanel.add("Center", numberPanel);
       ColoredLabel title = new ColoredLabel(ExposedIntStringTable.title, Label.CENTER, Color.yellow);
       title.setFont(new Font("Helvetica", Font.BOLD, 12));
       setBackground(Color.red);
       setLayout(new BorderLayout(5, 5));
       add("North", title);
       add("West", buttonPanel);
       add("Center", dataPanel);
   }
   public boolean action(Event evt, Object arg) {
       if (evt.target instanceof Button) {
           String bname = (String) arg;
           if (bname.equals(ExposedIntStringTable.increment)) {
               ++value;
           }
           else if (bname.equals(ExposedIntStringTable.decrement)) {
               --value;
           }
           else if (bname.equals(ExposedIntStringTable.min)) {
               value = 0x80000000;
           }
           else if (bname.equals(ExposedIntStringTable.max)) {
               value = 0x7fffffff;
           }
           else if (bname.equals(ExposedIntStringTable.zero)) {
               value = 0;
           }
           else if (bname.equals(ExposedIntStringTable.negate)) {
               value *= -1;
           }
           UpdateNumberFields();
           enableDisableButton(maximumButton, Integer.MAX_VALUE);
           enableDisableButton(minimumButton, Integer.MIN_VALUE);
           enableDisableButton(zeroButton, 0);
       }
       return true;
   }
   void enableDisableButton(Button b, int val) {
       if (!b.isEnabled()) {
           if (value != val) {
               b.enable();
           }
       } else if (value == val) {
           b.disable();
       }
   }
   void UpdateNumberFields() {
       decimalField.setText(Integer.toString(value));
       int v = value;
       StringBuffer buf = new StringBuffer();
       for (int i = 0; i < 8; ++i) {
           // Get lowest bit
           int remainder = v & 0xf;
           // Convert bit to a character and insert it into the beginning of the string
           switch (remainder) {
           case 0:
               buf.insert(0, "0");
               break;
           case 1:
               buf.insert(0, "1");
               break;
           case 2:
               buf.insert(0, "2");
               break;
           case 3:
               buf.insert(0, "3");
               break;
           case 4:
               buf.insert(0, "4");
               break;
           case 5:
               buf.insert(0, "5");
               break;
           case 6:
               buf.insert(0, "6");
               break;
           case 7:
               buf.insert(0, "7");
               break;
           case 8:
               buf.insert(0, "8");
               break;
           case 9:
               buf.insert(0, "9");
               break;
           case 10:
               buf.insert(0, "a");
               break;
           case 11:
               buf.insert(0, "b");
               break;
           case 12:
               buf.insert(0, "c");
               break;
           case 13:
               buf.insert(0, "d");
               break;
           case 14:
               buf.insert(0, "e");
               break;
           case 15:
               buf.insert(0, "f");
               break;
           }
           // Shift the int to the right one bit
           v >>>= 4;
       }
       hexField.setText(buf.toString());
       v = value;
       buf.setLength(0);
       for (int i = 0; i < 32; ++i) {
           // Get lowest bit
           int remainder = v & 0x1;
           // Convert bit to a character and insert it into the beginning of the string
           if (remainder == 0) {
               buf.insert(0, "0");
           }
           else {
               buf.insert(0, "1");
           }
           // Shift the int to the right one bit
           v >>>= 1;
       }
       binaryField.setText(buf.toString());
   }
   public Insets insets() {
       return new Insets(5, 5, 5, 5);
   }

} class ExposedIntStringTable {

   public static final String title = "EXPOSED INT";
   public static final String binary = "binary";
   public static final String hex = "hex";
   public static final String decimal = "decimal";
   public static final String max = "Max";
   public static final String min = "Min";
   public static final String zero = "Zero";
   public static final String increment = "++";
   public static final String decrement = "--";
   public static final String negate = "*=(-1)";

} // 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 GrayButton extends Button {

   GrayButton(String label) {
       super(label);
       setBackground(Color.lightGray);
   }

} class PanelWithInsets extends Panel {

   private int top;
   private int left;
   private int bottom;
   private int right;
   PanelWithInsets(int t, int l, int b, int r) {
       top = t;
       left = l;
       bottom = b;
       right = r;
   }
   PanelWithInsets() {
       top = 5;
       left = 5;
       bottom = 5;
       right = 5;
   }
   public Insets insets() {
       return new Insets(top, left, bottom, right);
   }

}


 </source>
   
  
 
  



Memory related

   <source lang="java">
   

/*

* Copyright (c) 1998-2002 Carnegie Mellon University.  All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in
*    the documentation and/or other materials provided with the
*    distribution.
*
* THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS"" AND
* ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY
* NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

public abstract class Mem {

   public static long free () {
       return Runtime.getRuntime ().freeMemory ();
   }
   public static long used () {
       Runtime r = Runtime.getRuntime ();
       return r.totalMemory() - r.freeMemory ();
   }
   public static long total () {
       return Runtime.getRuntime ().totalMemory ();
   }
   public static String getReport () {
       return "Memory: used " + (used()/1000) + "KB, free "
           + (free()/1000) + "KB, total " + (total()/1000) + "KB";
   }
   public static void gc () {
       Runtime r = Runtime.getRuntime ();
       r.runFinalization ();
       r.gc ();
   }
   public static void dumpThreadInfo () {
       ThreadGroup g = Thread.currentThread().getThreadGroup ();
       Thread[] t = new Thread[g.activeCount ()];
       g.enumerate (t);
       System.err.println ("Active threads in " + g);
       for (int i=0; i<t.length; ++i)
           System.err.println (t[i]);
   }

}



 </source>
   
  
 
  



Set the memory available to the JVM

   <source lang="java">
   

java -mx20m myApp // for max java -ms20m myApp // for start



 </source>
   
  
 
  



Stack memory view

   <source lang="java">
  

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

Copyright (c) 1996 Artima Software Company. All Rights Reserved.
* Permission to use, copy, modify, and distribute this software
* and its documentation for EVALUATION purposes only
* is hereby granted provided that this copyright notice
* appears in all copies. "Evaluation purposes" are any uses which
* do not constitute the sale, sharing, or redistribution of this
* software with or to any other persons in any medium.
*
* ARTIMA SOFTWARE COMPANY MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT
* THE SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. ARTIMA SOFTWARE COMPANY
* SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
* USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
PROJECT:  JavaWorld
MODULE:   Under The Hood
FILE:   CircleOfSquares.java
AUTHOR:   Bill Venners, August 1996
DESCRIPTION:
This file contains all the code for the java virtual machine simulation
applet, named Circle Of Squares, that accompanies the Under The Hood article
titled, "Floating Point Arithmetic".
As I developed this applet I had every class in a separate file. I combined
them in one file here to make it easier to download.
*********************************************************************/

import java.awt.BorderLayout; import java.awt.Button; import java.awt.Color; import java.awt.ruponent; import java.awt.Container; import java.awt.Dimension; import java.awt.Event; import java.awt.Font; import java.awt.GridLayout; import java.awt.Insets; import java.awt.Label; import java.awt.LayoutManager; import java.awt.Panel; public class CircleOfSquares extends java.applet.Applet {

 // Vars for the three outer panels that are contained inside the Applet"s
 // panel.
 // twoParts contains the stack and the method area. simulationController
 // contains the Step and Reset buttons and the hint label.
 private ThreeParts threeParts;
 private RegisterPanel registers;
 private ControlPanel simulationController;
 // Local reference to reset button on control panel allows for easy enabling
 // and
 // disabling of this button.
 private Button resetButton;
 // Vars that implement the Java stack
 private final int stackBase = 0x33330000;
 private final int stackMemorySectionSize = 8;
 private StackMemorySection stackMemorySection = new StackMemorySection(stackBase,
     stackMemorySectionSize);
 private StackMemoryView stackMemoryView;
 // Vars that implement the method area of the JVM
 private final int methodAreaBase = 0x44440000;
 private MemorySection methodAreaMemorySection = new MemorySection(methodAreaBase,
     SimData.methodAreaMemorySectionSize);
 private MemoryView methodAreaMemoryView;
 // Vars that implement the Java registers
 private int pcRegister;
 private int optopRegister;
 private int frameRegister;
 private int varsRegister;
 public void init() {
   setBackground(ColorTable.appletBackgroundColor);
   setLayout(new BorderLayout(5, 5));
   threeParts = new ThreeParts(SimData.methodAreaMemorySectionSize);
   simulationController = new ControlPanel();
   resetButton = simulationController.getResetButton();
   ColoredLabel title = new ColoredLabel(StringTable.appletTitle, Label.CENTER,
       ColorTable.titleColor);
   title.setFont(new Font("Helvetica", Font.BOLD, 12));
   add("North", title);
   add("South", simulationController);
   add("Center", threeParts);
   // Get a reference to the UI objects that are actually manipulated by
   // the handlers of the Step and Reset buttons. These aren"t available
   // without this explicit get() because these objects are buried several
   // levels down in embedded panels.
   stackMemoryView = threeParts.getStackMemoryViewReference();
   methodAreaMemoryView = threeParts.getMethodAreaMemoryViewReference();
   registers = threeParts.getRegisterPanel();
   // Place the bytecodes into the method area
   for (int i = 0; i < SimData.methodAreaMemorySectionSize; ++i) {
     methodAreaMemorySection.setAtAddress(methodAreaBase + i, SimData.theProgram[i]);
     methodAreaMemorySection.setLogicalValueAtAddress(methodAreaBase + i,
         SimData.byteCodeMnemonics[i]);
   }
   ResetState();
   UpdateStateDisplay();
 }
 public boolean action(Event evt, Object arg) {
   if (evt.target instanceof Button) {
     String bname = (String) arg;
     if (bname.equals(StringTable.reset)) {
       resetButton.disable();
       ResetState();
       UpdateStateDisplay();
     } else if (bname.equals(StringTable.step)) {
       if (!resetButton.isEnabled()) {
         resetButton.enable();
       }
       ExecuteNextInstruction();
       UpdateStateDisplay();
     }
   }
   return true;
 }
 // ExecuteNextInstruction() grabs the instruction pointed to by the program
 // counter, decodes it via the switch statement, and executes it by running
 // the
 // code under the appropriate case statement. The program counter is always
 // set to the next instruction that should be executed, naturally. Only those
 // bytecodes that appear in the short sequence presented in this simulation
 // are interpreted here to save time (your time in downloading and my time
 // in writing.)
 void ExecuteNextInstruction() {
   int a, b, result, i;
   float fa, fb, fresult;
   Float f;
   int operand0, operand1;
   int nextOpCode = methodAreaMemorySection.getAtAddress(pcRegister);
   switch (nextOpCode) {
   case OpCode.BIPUSH:
     operand0 = methodAreaMemorySection.getAtAddress(pcRegister + 1);
     stackMemorySection.setAtAddress(optopRegister, operand0);
     stackMemorySection.setLogicalValueAtAddress(optopRegister, StringTable.operand);
     optopRegister += 4;
     pcRegister += 2;
     break;
   case OpCode.FCONST_0:
     stackMemorySection.setAtAddress(optopRegister, Float.floatToIntBits((float) 0));
     stackMemorySection.setLogicalValueAtAddress(optopRegister, "0");
     optopRegister += 4;
     ++pcRegister;
     break;
   case OpCode.FCONST_2:
     stackMemorySection.setAtAddress(optopRegister, Float.floatToIntBits((float) 2));
     stackMemorySection.setLogicalValueAtAddress(optopRegister, "2");
     optopRegister += 4;
     ++pcRegister;
     break;
   case OpCode.FLOAD_0:
     a = stackMemorySection.getAtAddress(varsRegister);
     stackMemorySection.setAtAddress(optopRegister, a);
     fa = Float.intBitsToFloat(a);
     stackMemorySection.setLogicalValueAtAddress(optopRegister, Float.toString(fa));
     optopRegister += 4;
     ++pcRegister;
     break;
   case OpCode.FMUL:
     optopRegister -= 4;
     a = stackMemorySection.getAtAddress(optopRegister);
     fa = Float.intBitsToFloat(a);
     stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
     optopRegister -= 4;
     b = stackMemorySection.getAtAddress(optopRegister);
     fb = Float.intBitsToFloat(b);
     fresult = fa * fb;
     result = Float.floatToIntBits(fresult);
     stackMemorySection.setAtAddress(optopRegister, result);
     stackMemorySection.setLogicalValueAtAddress(optopRegister, Float.toString(fresult));
     optopRegister += 4;
     ++pcRegister;
     break;
   case OpCode.FSTORE_0:
     optopRegister -= 4;
     a = stackMemorySection.getAtAddress(optopRegister);
     stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
     stackMemorySection.setAtAddress(varsRegister, a);
     fa = Float.intBitsToFloat(a);
     stackMemorySection.setLogicalValueAtAddress(varsRegister, Float.toString(fa));
     ++pcRegister;
     break;
   case OpCode.FSUB:
     optopRegister -= 4;
     a = stackMemorySection.getAtAddress(optopRegister);
     fa = Float.intBitsToFloat(a);
     stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
     optopRegister -= 4;
     b = stackMemorySection.getAtAddress(optopRegister);
     fb = Float.intBitsToFloat(b);
     fresult = fb - fa;
     result = Float.floatToIntBits(fresult);
     stackMemorySection.setAtAddress(optopRegister, result);
     stackMemorySection.setLogicalValueAtAddress(optopRegister, Float.toString(fresult));
     optopRegister += 4;
     ++pcRegister;
     break;
   case OpCode.GOTO:
     operand1 = methodAreaMemorySection.getAtAddress(pcRegister + 1);
     operand0 = methodAreaMemorySection.getAtAddress(pcRegister + 2);
     int offset = (operand1 << 8) | (operand0 & 0xff);
     pcRegister += offset;
     break;
   case OpCode.IADD:
     optopRegister -= 4;
     a = stackMemorySection.getAtAddress(optopRegister);
     stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
     optopRegister -= 4;
     b = stackMemorySection.getAtAddress(optopRegister);
     result = a + b;
     stackMemorySection.setAtAddress(optopRegister, result);
     optopRegister += 4;
     ++pcRegister;
     break;
   case OpCode.ICONST_M1:
     stackMemorySection.setAtAddress(optopRegister, -1);
     stackMemorySection.setLogicalValueAtAddress(optopRegister, StringTable.operand);
     optopRegister += 4;
     ++pcRegister;
     break;
   case OpCode.ICONST_0:
     stackMemorySection.setAtAddress(optopRegister, 0);
     stackMemorySection.setLogicalValueAtAddress(optopRegister, StringTable.operand);
     optopRegister += 4;
     ++pcRegister;
     break;
   case OpCode.ICONST_1:
     stackMemorySection.setAtAddress(optopRegister, 1);
     stackMemorySection.setLogicalValueAtAddress(optopRegister, StringTable.operand);
     optopRegister += 4;
     ++pcRegister;
     break;
   case OpCode.ICONST_2:
     stackMemorySection.setAtAddress(optopRegister, 2);
     stackMemorySection.setLogicalValueAtAddress(optopRegister, StringTable.operand);
     optopRegister += 4;
     ++pcRegister;
     break;
   case OpCode.IINC:
     operand0 = methodAreaMemorySection.getAtAddress(pcRegister + 1);
     operand1 = methodAreaMemorySection.getAtAddress(pcRegister + 2);
     a = stackMemorySection.getAtAddress(varsRegister + (operand0 * 4));
     a += operand1;
     stackMemorySection.setAtAddress(varsRegister + (operand0 * 4), a);
     pcRegister += 3;
     break;
   case OpCode.ILOAD_0:
     a = stackMemorySection.getAtAddress(varsRegister);
     stackMemorySection.setAtAddress(optopRegister, a);
     stackMemorySection.setLogicalValueAtAddress(optopRegister, StringTable.operand);
     optopRegister += 4;
     ++pcRegister;
     break;
   case OpCode.ILOAD_1:
     a = stackMemorySection.getAtAddress(varsRegister + 4);
     stackMemorySection.setAtAddress(optopRegister, a);
     stackMemorySection.setLogicalValueAtAddress(optopRegister, StringTable.operand);
     optopRegister += 4;
     ++pcRegister;
     break;
   case OpCode.IMUL:
     optopRegister -= 4;
     a = stackMemorySection.getAtAddress(optopRegister);
     stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
     optopRegister -= 4;
     b = stackMemorySection.getAtAddress(optopRegister);
     result = a * b;
     stackMemorySection.setAtAddress(optopRegister, result);
     optopRegister += 4;
     ++pcRegister;
     break;
   case OpCode.INT2BYTE:
     a = stackMemorySection.getAtAddress(optopRegister - 4);
     a = (byte) a;
     stackMemorySection.setAtAddress(optopRegister - 4, a);
     stackMemorySection.setLogicalValueAtAddress(optopRegister - 4, StringTable.operand);
     ++pcRegister;
     break;
   case OpCode.ISTORE_0:
     optopRegister -= 4;
     a = stackMemorySection.getAtAddress(optopRegister);
     stackMemorySection.setLogicalValueAtAddress(optopRegister, "");
     stackMemorySection.setAtAddress(varsRegister, a);
     ++pcRegister;
     break;
   case OpCode.ISTORE_1:
     optopRegister -= 4;
     a = stackMemorySection.getAtAddress(optopRegister);
     stackMemorySection.setLogicalValueAtAddress(optopRegister + 4, "");
     stackMemorySection.setAtAddress(varsRegister + 4, a);
     ++pcRegister;
     break;
   }
 }
 // Pushing the Reset button will cause ResetState() to be executed, which will
 // reset all the data to its initial values.
 void ResetState() {
   pcRegister = methodAreaBase;
   optopRegister = stackBase + SimData.optopOffset;
   frameRegister = stackBase + SimData.frameOffset;
   varsRegister = stackBase;
   int i;
   for (i = 0; i < 7; ++i) {
     stackMemorySection.setLogicalValueAtAddress(stackBase + (i * 4), "");
     stackMemorySection.setAtAddress(stackBase + (i * 4), 0);
   }
   methodAreaMemoryView.update(methodAreaMemorySection, methodAreaBase);
 }
 // UpdateStateDisplay writes the current state of the JVM to the UI.
 void UpdateStateDisplay() {
   registers.setPcRegister(pcRegister);
   registers.setOptopRegister(optopRegister);
   registers.setFrameRegister(frameRegister);
   registers.setVarsRegister(varsRegister);
   stackMemoryView.update(stackMemorySection, stackBase);
   methodAreaMemoryView.updateProgramCounter(pcRegister - methodAreaBase, methodAreaMemorySection);
   stackMemoryView.clearPointers();
   stackMemoryView.updatePointer((varsRegister - stackBase) / 4, StringTable.varsPointer);
   stackMemoryView.updatePointer((frameRegister - stackBase) / 4, StringTable.framePointer);
   stackMemoryView.updatePointer((optopRegister - stackBase) / 4, StringTable.optopPointer);
   int nextOpCode = methodAreaMemorySection.getAtAddress(pcRegister);
   switch (nextOpCode) {
   case OpCode.BIPUSH:
     simulationController.setExplanationText(StringTable.bipushText);
     break;
   case OpCode.FCONST_0:
     simulationController.setExplanationText(StringTable.fconst_0Text);
     break;
   case OpCode.FCONST_2:
     simulationController.setExplanationText(StringTable.fconst_2Text);
     break;
   case OpCode.FLOAD_0:
     simulationController.setExplanationText(StringTable.fload_0Text);
     break;
   case OpCode.FMUL:
     simulationController.setExplanationText(StringTable.fmulText);
     break;
   case OpCode.FSTORE_0:
     simulationController.setExplanationText(StringTable.fstore_0Text);
     break;
   case OpCode.FSUB:
     simulationController.setExplanationText(StringTable.fsubText);
     break;
   case OpCode.GOTO:
     simulationController.setExplanationText(StringTable.gotoText);
     break;
   case OpCode.IADD:
     simulationController.setExplanationText(StringTable.iaddText);
     break;
   case OpCode.ICONST_M1:
     simulationController.setExplanationText(StringTable.iconst_m1Text);
     break;
   case OpCode.ICONST_0:
     simulationController.setExplanationText(StringTable.iconst_0Text);
     break;
   case OpCode.ICONST_1:
     simulationController.setExplanationText(StringTable.iconst_1Text);
     break;
   case OpCode.ICONST_2:
     simulationController.setExplanationText(StringTable.iconst_2Text);
     break;
   case OpCode.IINC:
     simulationController.setExplanationText(StringTable.iincText);
     break;
   case OpCode.ILOAD_0:
     simulationController.setExplanationText(StringTable.iload_0Text);
     break;
   case OpCode.ILOAD_1:
     simulationController.setExplanationText(StringTable.iload_1Text);
     break;
   case OpCode.IMUL:
     simulationController.setExplanationText(StringTable.imulText);
     break;
   case OpCode.INT2BYTE:
     simulationController.setExplanationText(StringTable.int2byteText);
     break;
   case OpCode.ISTORE_0:
     simulationController.setExplanationText(StringTable.istore_0Text);
     break;
   case OpCode.ISTORE_1:
     simulationController.setExplanationText(StringTable.istore_1Text);
     break;
   default:
     simulationController.setExplanationText("");
     break;
   }
 }
 // Make pretty border around entire applet panel
 public Insets insets() {
   return new Insets(5, 5, 5, 5);
 }

} // 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 ColorTable {

 static final Color appletBackgroundColor = Color.blue;
 static final Color registersAreaColor = Color.magenta;
 static final Color stackAreaColor = Color.magenta;
 static final Color methodAreaColor = Color.magenta;
 static final Color titleColor = Color.cyan;
 static final Color explanationLabel = Color.cyan;

} class ControlPanel extends Panel {

 private ColoredLabel explanationLabel;
 private GrayButton resetButton = new GrayButton(StringTable.reset);
 ControlPanel() {
   setLayout(new BorderLayout(5, 5));
   Panel leftButtonPanel = new Panel();
   leftButtonPanel.setLayout(new GridLayout(2, 1, 0, 5));
   leftButtonPanel.add(new GrayButton(StringTable.step));
   resetButton.disable();
   leftButtonPanel.add(resetButton);
   explanationLabel = new ColoredLabel("This is where the explanation goes...", Label.CENTER,
       Color.lightGray);
   explanationLabel.setBackground(ColorTable.explanationLabel);
   Font plainFont = new Font("TimesRoman", Font.ITALIC, 12);
   explanationLabel.setFont(plainFont);
   add("West", leftButtonPanel);
   add("Center", explanationLabel);
 }
 public void setExplanationText(String explanation) {
   explanationLabel.setLabelText(explanation);
 }
 public Button getResetButton() {
   return resetButton;
 }
 public Insets insets() {
   // top, left, bottom, right
   return new Insets(0, 0, 0, 0);
 }

} class GrayButton extends Button {

 GrayButton(String label) {
   super(label);
   setBackground(Color.lightGray);
 }

} // GridSnapLayout lays out components in a grid that can have columns of // varying width. This is not a very general purpose layout manager. It // solves the specific problem of getting all the information I want to display // about // the stack and method areas in a nice grid. Because some columns of info need // more room than others, and space is limited on a web page, I needed to be // able to specify varying widths of columns in a grid. class GridSnapLayout implements LayoutManager {

 // rows and cols are the number of rows and columns of the grid upon
 // which the components are placed. Components are always one row
 // in height, but may be more than one column in width. The number
 // of columns width of each component is stored in hComponentCellWidths.
 // The array length of hComponentCellWidths indicates the number of
 // components that will appear on each row.
 private int rows;
 private int cols;
 private int[] hComponentCellWidths;
 public GridSnapLayout(int rows, int cols, int[] hComponentCellWidths) {
   this.rows = rows;
   this.cols = cols;
   this.hComponentCellWidths = hComponentCellWidths;
 }
 public void addLayoutComponent(String name, Component comp) {
 }
 public void removeLayoutComponent(Component comp) {
 }
 // Calculate preferred size as if each component were taking an equal
 // share of the width of a row.
 public Dimension preferredLayoutSize(Container parent) {
   int rowCount = rows;
   int colCount = cols;
   Insets parentInsets = parent.insets();
   int componentCount = parent.countComponents();
   if (rowCount > 0) {
     colCount = (componentCount + rowCount - 1) / rowCount;
   } else {
     rowCount = (componentCount + colCount - 1) / colCount;
   }
   // Find the maximum preferred width and the maximum preferred height
   // of any component.
   int w = 0;
   int h = 0;
   for (int i = 0; i < componentCount; i++) {
     Component comp = parent.getComponent(i);
     Dimension d = comp.preferredSize();
     if (w < d.width) {
       w = d.width;
     }
     if (h < d.height) {
       h = d.height;
     }
   }
   // Return the maximum preferred component width and height times the number
   // of columns and rows, respectively, plus any insets in the parent.
   return new Dimension(parentInsets.left + parentInsets.right + colCount * w, parentInsets.top
       + parentInsets.bottom + rowCount * h);
 }
 // Calculate minimum size as if each component were taking an equal
 // share of the width of a row.
 public Dimension minimumLayoutSize(Container parent) {
   Insets parentInsets = parent.insets();
   int componentCount = parent.countComponents();
   int rowCount = rows;
   int colCount = cols;
   if (rowCount > 0) {
     colCount = (componentCount + rowCount - 1) / rowCount;
   } else {
     rowCount = (componentCount + colCount - 1) / colCount;
   }
   // Find the maximum "minimum width" and the maximum "minimum height"
   // of any component.
   int w = 0;
   int h = 0;
   for (int i = 0; i < componentCount; i++) {
     Component comp = parent.getComponent(i);
     Dimension d = comp.minimumSize();
     if (w < d.width) {
       w = d.width;
     }
     if (h < d.height) {
       h = d.height;
     }
   }
   // Return the maximum "minimum component width and height" times the number
   // of columns and rows, respectively, plus any insets in the parent.
   return new Dimension(parentInsets.left + parentInsets.right + colCount * w, parentInsets.top
       + parentInsets.bottom + rowCount * h);
 }
 // Layout the container such that the widths of columns correspond
 // to the number of columns in that components hComponentCellWidth
 // array element. For example, if the
 public void layoutContainer(Container parent) {
   int rowCount = rows;
   int colCount = hComponentCellWidths.length;
   Insets parentInsets = parent.insets();
   int componentCount = parent.countComponents();
   if (componentCount == 0) {
     return;
   }
   // Calculate the width and height of each grid cell. The height will
   // be the height of each component, but the width may not. The width
   // of a component will be some multiple of a grid cell width. The
   // number of grid cells for each component is defined by the
   // hComponentCellWidths array. w is width of each grid cell. h is
   // height of each grid cell.
   Dimension parentDim = parent.size();
   int w = parentDim.width - (parentInsets.left + parentInsets.right);
   int h = parentDim.height - (parentInsets.top + parentInsets.bottom);
   w /= cols;
   h /= rowCount;
   // For each row and column of components (not grid cells) position
   // the component.
   for (int c = 0, x = parentInsets.left; c < colCount; c++) {
     for (int r = 0, y = parentInsets.top; r < rowCount; r++) {
       int i = r * colCount + c;
       if (i < componentCount) {
         parent.getComponent(i).reshape(x, y, w * hComponentCellWidths[c], h);
       }
       y += h;
     }
     x += (w * hComponentCellWidths[c]);
   }
 }

} class HexString {

 private final String hexChar = "0123456789abcdef";
 private StringBuffer buf = new StringBuffer();
 void Convert(int val, int maxNibblesToConvert) {
   buf.setLength(0);
   int v = val;
   for (int i = 0; i < maxNibblesToConvert; ++i) {
     if (v == 0) {
       if (i == 0) {
         buf.insert(0, "0");
       }
       break;
     }
     // Get lowest nibble
     int remainder = v & 0xf;
     // Convert nibble to a character and insert it into the beginning of the
     // string
     buf.insert(0, hexChar.charAt(remainder));
     // Shift the int to the right four bits
     v >>>= 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();
 }

} class LabeledRegister extends Panel {

 private ColoredLabel registerContents;
 LabeledRegister(String labelText) {
   setLayout(new BorderLayout(5, 5));
   registerContents = new ColoredLabel("00000000", Label.CENTER, Color.lightGray);
   registerContents.setFont(new Font("TimesRoman", Font.PLAIN, 11));
   Label title = new Label(labelText, Label.RIGHT);
   title.setFont(new Font("Helvetica", Font.ITALIC, 11));
   add("East", registerContents);
   add("Center", title);
 }
 public void setRegister(int val) {
   HexString hexString = new HexString(val, 8);
   registerContents.setLabelText(hexString.getString());
 }
 public Insets insets() {
   return new Insets(0, 0, 0, 0);
 }

} // MemorySection is just used for the method area in this applet. This // implements // the functionality of the method area and has nothing to do with the UI. class MemorySection {

 private int[] memory;
 private int baseAddress;
 private String[] logicalValueString;
 MemorySection(int base, int size) {
   baseAddress = base;
   memory = new int[size];
   logicalValueString = new String[size];
   for (int i = 0; i < size; ++i) {
     logicalValueString[i] = new String();
   }
 }
 int getBaseAddress() {
   return baseAddress;
 }
 public int getAtAddress(int address) {
   return memory[address - baseAddress];
 }
 public String getLogicalValueAtAddress(int address) {
   return logicalValueString[address - baseAddress];
 }
 public void setAtAddress(int address, int value) {
   memory[address - baseAddress] = value;
 }
 public void setLogicalValueAtAddress(int address, String s) {
   logicalValueString[address - baseAddress] = s;
 }
 int getSize() {
   return memory.length;
 }

} // MemoryView is just used for the method area in this applet. It implements the // UI of the method area. class MemoryView extends Panel {

 private final int memoryLocationsVisibleCount = SimData.methodAreaMemoryLocationsVisibleCount;
 private Label[] pointer = new Label[memoryLocationsVisibleCount];
 private Label[] address = new Label[memoryLocationsVisibleCount];
 private Label[] byteValue = new Label[memoryLocationsVisibleCount];
 private Label[] logicalValue = new Label[memoryLocationsVisibleCount];
 private int firstVisibleRow;
 private int currentProgramCounterRow;
 MemoryView(int methodAreaMemSectionSize) {
   setLayout(new GridLayout(memoryLocationsVisibleCount, 4));
   setBackground(Color.lightGray);
   Font plainFont = new Font("TimesRoman", Font.PLAIN, 11);
   setFont(plainFont);
   Font italicFont = new Font("TimesRoman", Font.ITALIC, 11);
   for (int i = 0; i < memoryLocationsVisibleCount; ++i) {
     pointer[i] = new Label("", Label.RIGHT);
     pointer[i].setFont(italicFont);
     add(pointer[i]);
     address[i] = new Label("", Label.CENTER);
     add(address[i]);
     byteValue[i] = new Label("", Label.CENTER);
     add(byteValue[i]);
     logicalValue[i] = new Label("", Label.LEFT);
     add(logicalValue[i]);
   }
 }
 public void setAt(int i, int addressValue, int value, String logicalValueStr) {
   HexString addressValueHexString = new HexString(addressValue, 8);
   HexString byteValueHexString = new HexString(value, 2);
   address[i].setText(addressValueHexString.getString());
   byteValue[i].setText(byteValueHexString.getString());
   logicalValue[i].setText(logicalValueStr);
 }
 public void update(MemorySection memorySection, int initialAddress) {
   for (int i = 0; i < memoryLocationsVisibleCount; ++i) {
     int theByte = memorySection.getAtAddress(initialAddress + i);
     String logicalValue = memorySection.getLogicalValueAtAddress(initialAddress + i);
     setAt(i, initialAddress + i, theByte, logicalValue);
   }
 }
 public void clearPointers() {
   for (int i = 0; i < memoryLocationsVisibleCount; ++i) {
     pointer[i].setText("");
   }
 }
 public void updateProgramCounter(int i, MemorySection memorySection) {
   pointer[currentProgramCounterRow - firstVisibleRow].setText("");
   if (i - firstVisibleRow >= memoryLocationsVisibleCount) {
     firstVisibleRow += 5;
     if (firstVisibleRow > memorySection.getSize() - memoryLocationsVisibleCount) {
       firstVisibleRow = memorySection.getSize() - memoryLocationsVisibleCount;
     }
     update(memorySection, memorySection.getBaseAddress() + firstVisibleRow);
   } else if (i < firstVisibleRow) {
     firstVisibleRow = i;
     update(memorySection, memorySection.getBaseAddress() + firstVisibleRow);
   }
   pointer[i - firstVisibleRow].setText("pc >");
   currentProgramCounterRow = i;
 }
 public Insets insets() {
   // top, left, bottom, right
   return new Insets(0, 0, 0, 0);
 }

} class MemoryViewTitlePanel extends Panel {

 MemoryViewTitlePanel() {
   setLayout(new GridLayout(1, 4));
   setFont(new Font("Helvetica", Font.ITALIC, 11));
   add(new Label("", Label.CENTER));
   add(new Label(StringTable.address, Label.CENTER));
   add(new Label(StringTable.bytecodes, Label.CENTER));
   add(new Label(StringTable.mnemonics, Label.CENTER));
 }
 public Insets insets() {
   // top, left, bottom, right
   return new Insets(0, 0, 0, 0);
 }

} class MemoryViewWithTitles extends Panel {

 private MemoryView memoryView;
 MemoryViewWithTitles(int methodAreaMemorySectionSize) {
   memoryView = new MemoryView(methodAreaMemorySectionSize);
   setLayout(new BorderLayout());
   add("North", new MemoryViewTitlePanel());
   add("Center", memoryView);
 }
 public MemoryView getMemoryViewReference() {
   return memoryView;
 }
 public Insets insets() {
   // top, left, bottom, right
   return new Insets(0, 0, 0, 0);
 }

} class MethodAreaPanel extends Panel {

 private Label title;
 private MemoryViewWithTitles memoryView;
 MethodAreaPanel(int methodAreaMemorySectionSize) {
   memoryView = new MemoryViewWithTitles(methodAreaMemorySectionSize);
   setLayout(new BorderLayout());
   title = new Label("Method Area", Label.CENTER);
   title.setFont(new Font("Helvetica", Font.BOLD, 11));
   add("North", title);
   add("Center", memoryView);
 }
 public MemoryView getMemoryViewReference() {
   return memoryView.getMemoryViewReference();
 }
 public Insets insets() {
   return new Insets(5, 5, 5, 5);
 }

} class OpCode {

 final static int NOP = 0;
 final static int ACONST_NULL = 1;
 final static int ICONST_M1 = 2;
 final static int ICONST_0 = 3;
 final static int ICONST_1 = 4;
 final static int ICONST_2 = 5;
 final static int ICONST_3 = 6;
 final static int ICONST_4 = 7;
 final static int ICONST_5 = 8;
 final static int LCONST_0 = 9;
 final static int LCONST_1 = 10;
 final static int FCONST_0 = 11;
 final static int FCONST_1 = 12;
 final static int FCONST_2 = 13;
 final static int DCONST_0 = 14;
 final static int DCONST_1 = 15;
 final static int BIPUSH = 16;
 final static int SIPUSH = 17;
 final static int LDC1 = 18;
 final static int LDC2 = 19;
 final static int LDC2W = 20;
 final static int ILOAD = 21;
 final static int LLOAD = 22;
 final static int FLOAD = 23;
 final static int DLOAD = 24;
 final static int ALOAD = 25;
 final static int ILOAD_0 = 26;
 final static int ILOAD_1 = 27;
 final static int ILOAD_2 = 28;
 final static int ILOAD_3 = 29;
 final static int LLOAD_0 = 30;
 final static int LLOAD_1 = 31;
 final static int LLOAD_2 = 32;
 final static int LLOAD_3 = 33;
 final static int FLOAD_0 = 34;
 final static int FLOAD_1 = 35;
 final static int FLOAD_2 = 36;
 final static int FLOAD_3 = 37;
 final static int DLOAD_0 = 38;
 final static int DLOAD_1 = 39;
 final static int DLOAD_2 = 40;
 final static int DLOAD_3 = 41;
 final static int ALOAD_0 = 42;
 final static int ALOAD_1 = 43;
 final static int ALOAD_2 = 44;
 final static int ALOAD_3 = 45;
 final static int IALOAD = 46;
 final static int LALOAD = 47;
 final static int FALOAD = 48;
 final static int DALOAD = 49;
 final static int AALOAD = 50;
 final static int BALOAD = 51;
 final static int CALOAD = 52;
 final static int SALOAD = 53;
 final static int ISTORE = 54;
 final static int LSTORE = 55;
 final static int FSTORE = 56;
 final static int DSTORE = 57;
 final static int ASTORE = 58;
 final static int ISTORE_0 = 59;
 final static int ISTORE_1 = 60;
 final static int ISTORE_2 = 61;
 final static int ISTORE_3 = 62;
 final static int LSTORE_0 = 63;
 final static int LSTORE_1 = 64;
 final static int LSTORE_2 = 65;
 final static int LSTORE_3 = 66;
 final static int FSTORE_0 = 67;
 final static int FSTORE_1 = 68;
 final static int FSTORE_2 = 69;
 final static int FSTORE_3 = 70;
 final static int DSTORE_0 = 71;
 final static int DSTORE_1 = 72;
 final static int DSTORE_2 = 73;
 final static int DSTORE_3 = 74;
 final static int ASTORE_0 = 75;
 final static int ASTORE_1 = 76;
 final static int ASTORE_2 = 77;
 final static int ASTORE_3 = 78;
 final static int IASTORE = 79;
 final static int LASTORE = 80;
 final static int FASTORE = 81;
 final static int DASTORE = 82;
 final static int AASTORE = 83;
 final static int BASTORE = 84;
 final static int CASTORE = 85;
 final static int SASTORE = 86;
 final static int POP = 87;
 final static int POP2 = 88;
 final static int DUP = 89;
 final static int DUP_X1 = 90;
 final static int DUP_X2 = 91;
 final static int DUP2 = 92;
 final static int DUP2_X1 = 93;
 final static int DUP2_X2 = 94;
 final static int SWAP = 95;
 final static int IADD = 96;
 final static int LADD = 97;
 final static int FADD = 98;
 final static int DADD = 99;
 final static int ISUB = 100;
 final static int LSUB = 101;
 final static int FSUB = 102;
 final static int DSUB = 103;
 final static int IMUL = 104;
 final static int LMUL = 105;
 final static int FMUL = 106;
 final static int DMUL = 107;
 final static int IDIV = 108;
 final static int LDIV = 109;
 final static int FDIV = 110;
 final static int DDIV = 111;
 final static int IREM = 112;
 final static int LREM = 113;
 final static int FREM = 114;
 final static int DREM = 115;
 final static int INEG = 116;
 final static int LNEG = 117;
 final static int FNEG = 118;
 final static int DNEG = 119;
 final static int ISHL = 120;
 final static int LSHL = 121;
 final static int ISHR = 122;
 final static int LSHR = 123;
 final static int IUSHR = 124;
 final static int LUSHR = 125;
 final static int IAND = 126;
 final static int LAND = 127;
 final static int IOR = 128;
 final static int LOR = 129;
 final static int IXOR = 130;
 final static int LXOR = 131;
 final static int IINC = 132;
 final static int I2L = 133;
 final static int I2F = 134;
 final static int I2D = 135;
 final static int L2I = 136;
 final static int L2F = 137;
 final static int L2D = 138;
 final static int F2I = 139;
 final static int F2L = 140;
 final static int F2D = 141;
 final static int D2I = 142;
 final static int D2L = 143;
 final static int D2F = 144;
 final static int INT2BYTE = 145;
 final static int INT2CHAR = 146;
 final static int INT2SHORT = 147;
 final static int LCMP = 148;
 final static int FCMPL = 149;
 final static int FCMPG = 150;
 final static int DCMPL = 151;
 final static int DCMPG = 152;
 final static int IFEQ = 153;
 final static int IFNE = 154;
 final static int IFLT = 155;
 final static int IFGE = 156;
 final static int IFGT = 157;
 final static int IFLE = 158;
 final static int IF_ICMPEQ = 159;
 final static int IF_ICMPNE = 160;
 final static int IF_ICMPLT = 161;
 final static int IF_ICMPGT = 163;
 final static int IF_ICMPLE = 164;
 final static int IF_ICMPGE = 162;
 final static int IF_ACMPEQ = 165;
 final static int IF_ACMPNE = 166;
 final static int GOTO = 167;
 final static int JSR = 168;
 final static int RET = 169;
 final static int TABLESWITCH = 170;
 final static int LOOKUPSWITCH = 171;
 final static int IRETURN = 172;
 final static int LRETURN = 173;
 final static int FRETURN = 174;
 final static int DRETURN = 175;
 final static int ARETURN = 176;
 final static int RETURN = 177;
 final static int INVOKEVIRTUAL = 182;
 final static int INVOKENONVIRTUAL = 183;
 final static int INVOKESTATIC = 184;
 final static int INVOKEINTERFACE = 185;
 final static int NEW = 187;
 final static int NEWARRAY = 188;
 final static int ANEWARRAY = 189;
 final static int ARRAYLENGTH = 190;
 final static int ATHROW = 191;
 final static int CHECKCAST = 192;
 final static int INSTANCEOF = 193;
 final static int MONITORENTER = 194;
 final static int MONITOREXIT = 195;
 final static int WIDE = 196;
 final static int MULTIANEWARRAY = 197;
 final static int IFNULL = 198;
 final static int IFNONNULL = 199;
 final static int GOTO_W = 200;
 final static int JSR_W = 201;
 final static int BREAKPOINT = 202;
 final static int RET_W = 209;

} class PanelWithInsets extends Panel {

 private int top;
 private int left;
 private int bottom;
 private int right;
 PanelWithInsets(int t, int l, int b, int r) {
   top = t;
   left = l;
   bottom = b;
   right = r;
 }
 PanelWithInsets() {
   top = 5;
   left = 5;
   bottom = 5;
   right = 5;
 }
 public Insets insets() {
   return new Insets(top, left, bottom, right);
 }

} class RegisterPanel extends Panel {

 private LabeledRegister pcRegister;
 private LabeledRegister optopRegister;
 private LabeledRegister frameRegister;
 private LabeledRegister varsRegister;
 RegisterPanel() {
   setLayout(new BorderLayout(5, 5));
   pcRegister = new LabeledRegister(StringTable.pc);
   optopRegister = new LabeledRegister(StringTable.optop);
   frameRegister = new LabeledRegister(StringTable.frame);
   varsRegister = new LabeledRegister(StringTable.vars);
   setBackground(ColorTable.registersAreaColor);
   Panel labeledRegisterPanel = new Panel();
   labeledRegisterPanel.setLayout(new GridLayout(1, 4, 5, 5));
   labeledRegisterPanel.add(pcRegister);
   labeledRegisterPanel.add(optopRegister);
   labeledRegisterPanel.add(frameRegister);
   labeledRegisterPanel.add(varsRegister);
   Label title = new Label(StringTable.Registers, Label.CENTER);
   title.setFont(new Font("Helvetica", Font.BOLD, 11));
   add("West", title);
   add("Center", labeledRegisterPanel);
 }
 public void setPcRegister(int val) {
   pcRegister.setRegister(val);
 }
 public void setOptopRegister(int val) {
   optopRegister.setRegister(val);
 }
 public void setFrameRegister(int val) {
   frameRegister.setRegister(val);
 }
 public void setVarsRegister(int val) {
   varsRegister.setRegister(val);
 }
 public Insets insets() {
   // top, left, bottom, right
   return new Insets(5, 5, 5, 5);
 }

} class RepeaterButton extends GrayButton {

 RepeaterButton(String label) {
   super(label);
 }

} class SimData {

 static final int methodAreaMemorySectionSize = 13;
 static final int methodAreaMemoryLocationsVisibleCount = 13;
 static final int frameOffset = 4;
 static final int optopOffset = 16;
 static int[] theProgram = { OpCode.FCONST_2, OpCode.FSTORE_0, OpCode.FLOAD_0, OpCode.FLOAD_0,
     OpCode.FMUL, OpCode.FSTORE_0, OpCode.FCONST_0, OpCode.FLOAD_0, OpCode.FSUB, OpCode.FSTORE_0,
     OpCode.GOTO, (byte) 0xff, (byte) 0xf8 };
 static String[] byteCodeMnemonics = { "fconst_2", "fstore_0", "fload_0", "fload_0", "fmul",
     "fstore_0", "fconst_0", "fload_0", "fsub", "fstore_0", "goto -17", "", "" };

} // StackMemorySection is just used for the stack in this applet. This implements // the functionality of the stack and has nothing to do with the UI. class StackMemorySection {

 private int[] memory;
 private int baseAddress;
 private String[] logicalValueString;
 StackMemorySection(int base, int size) {
   baseAddress = base;
   memory = new int[size];
   logicalValueString = new String[size];
   for (int i = 0; i < size; ++i) {
     memory[i] = 0;
     logicalValueString[i] = new String();
   }
 }
 public int getAtAddress(int address) {
   return memory[(address - baseAddress) / 4];
 }
 public String getLogicalValueAtAddress(int address) {
   return logicalValueString[(address - baseAddress) / 4];
 }
 public void setAtAddress(int address, int value) {
   memory[(address - baseAddress) / 4] = value;
 }
 public void setLogicalValueAtAddress(int address, String s) {
   logicalValueString[(address - baseAddress) / 4] = s;
 }

} // StackMemoryView is just used for the stack in this applet. It implements the // UI of the stack. class StackMemoryView extends Panel {

 private final int memoryLocationsVisibleCount = 8;
 private Label[] pointer = new Label[memoryLocationsVisibleCount];
 private Label[] address = new Label[memoryLocationsVisibleCount];
 private Label[] wordValue = new Label[memoryLocationsVisibleCount];
 private Label[] logicalValue = new Label[memoryLocationsVisibleCount];
 StackMemoryView() {
   int[] hComponentCellWidths = new int[4];
   hComponentCellWidths[0] = 2;
   hComponentCellWidths[1] = 2;
   hComponentCellWidths[2] = 2;
   hComponentCellWidths[3] = 3;
   setLayout(new GridSnapLayout(memoryLocationsVisibleCount, 9, hComponentCellWidths));
   setBackground(Color.lightGray);
   Font plainFont = new Font("TimesRoman", Font.PLAIN, 11);
   setFont(plainFont);
   Font italicFont = new Font("TimesRoman", Font.ITALIC, 11);
   for (int i = memoryLocationsVisibleCount - 1; i >= 0; --i) {
     pointer[i] = new Label("", Label.RIGHT);
     pointer[i].setFont(italicFont);
     add(pointer[i]);
     address[i] = new Label("", Label.CENTER);
     add(address[i]);
     wordValue[i] = new Label("", Label.CENTER);
     add(wordValue[i]);
     logicalValue[i] = new Label("", Label.CENTER);
     add(logicalValue[i]);
   }
 }
 public void setAt(int i, int addressValue, int value, String logicalValueString) {
   HexString addressValueString = new HexString(addressValue, 8);
   HexString wordValueString = new HexString(value, 8);
   address[memoryLocationsVisibleCount - 1 - i].setText(addressValueString.getString());
   wordValue[memoryLocationsVisibleCount - 1 - i].setText(wordValueString.getString());
   logicalValue[memoryLocationsVisibleCount - 1 - i].setText(logicalValueString);
 }
 public void update(StackMemorySection memorySection, int initialAddress) {
   for (int i = 0; i < memoryLocationsVisibleCount; ++i) {
     int theWord = memorySection.getAtAddress(initialAddress + (i * 4));
     String logicalValue = memorySection.getLogicalValueAtAddress(initialAddress + (i * 4));
     setAt(i, initialAddress + (i * 4), theWord, logicalValue);
   }
 }
 public void clearPointers() {
   for (int i = 0; i < memoryLocationsVisibleCount; ++i) {
     pointer[i].setText("");
   }
 }
 public void updatePointer(int i, String pointerString) {
   pointer[memoryLocationsVisibleCount - 1 - i].setText(pointerString);
 }
 public Insets insets() {
   // top, left, bottom, right
   return new Insets(0, 0, 0, 0);
 }

} class StackMemoryViewTitlePanel extends Panel {

 StackMemoryViewTitlePanel() {
   // setLayout(new GridLayout(1, 4));
   int[] hComponentCellWidths = new int[4];
   hComponentCellWidths[0] = 2;
   hComponentCellWidths[1] = 2;
   hComponentCellWidths[2] = 2;
   hComponentCellWidths[3] = 3;
   setLayout(new GridSnapLayout(1, 9, hComponentCellWidths));
   setFont(new Font("Helvetica", Font.ITALIC, 11));
   add(new Label("", Label.CENTER));
   add(new Label(StringTable.address, Label.CENTER));
   add(new Label(StringTable.hexValue, Label.CENTER));
   add(new Label(StringTable.value, Label.CENTER));
 }
 public Insets insets() {
   // top, left, bottom, right
   return new Insets(0, 0, 0, 0);
 }

} class StackMemoryViewWithTitles extends Panel {

 private StackMemoryView memoryView = new StackMemoryView();
 StackMemoryViewWithTitles() {
   setLayout(new BorderLayout());
   add("North", new StackMemoryViewTitlePanel());
   add("Center", memoryView);
 }
 public StackMemoryView getMemoryViewReference() {
   return memoryView;
 }
 public Insets insets() {
   // top, left, bottom, right
   return new Insets(0, 0, 0, 0);
 }

} class StackPanel extends Panel {

 private Label title;
 private StackMemoryViewWithTitles memoryView = new StackMemoryViewWithTitles();
 StackPanel() {
   setLayout(new BorderLayout());
   title = new Label("Stack", Label.CENTER);
   title.setFont(new Font("Helvetica", Font.BOLD, 11));
   add("North", title);
   add("Center", memoryView);
 }
 public StackMemoryView getMemoryViewReference() {
   return memoryView.getMemoryViewReference();
 }
 public Insets insets() {
   return new Insets(5, 5, 5, 5);
 }

} class StringTable {

 public final static String appletTitle = "CIRCLE OF SQUARES";
 public final static String step = "Step";
 public final static String reset = "Reset";
 public final static String operand = "operand";
 public final static String execEnv = "exec env";
 public final static String localVars = "local vars";
 public final static String varsPointer = "vars >";
 public final static String framePointer = "frame >";
 public final static String optopPointer = "optop >";
 public final static String address = "address";
 public final static String bytecodes = "bytecodes";
 public final static String mnemonics = "mnemonics";
 public final static String hexValue = "hex value";
 public final static String value = "value";
 public final static String Registers = "Registers";
 public final static String pc = "pc";
 public final static String optop = "optop";
 public final static String frame = "frame";
 public final static String vars = "vars";
 public final static String bipushText = "bipush will expand the next byte to an int and push it onto the stack.";
 public final static String fconst_0Text = "fconst_0 will push float 0.0 onto the stack.";
 public final static String fconst_2Text = "fconst_2 will push float 2.0 onto the stack.";
 public final static String fload_0Text = "fload_0 will push the float at local variable 0 onto the stack.";
 public final static String fmulText = "fmul will pop two floats, multiply them, and push the result.";
 public final static String fstore_0Text = "fstore_0 will pop the float off the top of the stack and store it in local variable 0.";
 public final static String fsubText = "fsub will pop two floats, subtract them, and push the result.";
 public final static String gotoText = "goto will cause a jump to the specified offset.";
 public final static String iaddText = "iadd will pop the top two integers off the stack, add them, and push the result back onto the stack.";
 public final static String iconst_m1Text = "iconst_m1 will push -1 onto the stack.";
 public final static String iconst_0Text = "iconst_0 will push 0 onto the stack.";
 public final static String iconst_1Text = "iconst_1 will push 1 onto the stack.";
 public final static String iconst_2Text = "iconst_2 will push 2 onto the stack.";
 public final static String iincText = "iinc will increment the specified local variable by the specified amount.";
 public final static String iload_0Text = "iload_0 will push the integer at local variable 0 onto the stack.";
 public final static String iload_1Text = "iload_1 will push the integer at local variable 1 onto the stack.";
 public final static String imulText = "imul will pop two integers, multiply them, and push the result.";
 public final static String int2byteText = "int2byte will convert the topmost int on the stack to a value valid for the byte type.";
 public final static String istore_0Text = "istore_0 will pop the integer off the top of the stack and store it in local variable 0.";
 public final static String istore_1Text = "istore_1 will pop the integer off the top of the stack and store it in local variable 1.";

} class ThreeParts extends Panel {

 private RegisterPanel registers;
 private TwoParts twoParts;
 ThreeParts(int methodAreaMemorySectionSize) {
   setLayout(new BorderLayout(5, 5));
   registers = new RegisterPanel();
   twoParts = new TwoParts(methodAreaMemorySectionSize);
   add("North", registers);
   add("Center", twoParts);
 }
 StackMemoryView getStackMemoryViewReference() {
   return twoParts.getStackMemoryViewReference();
 }
 MemoryView getMethodAreaMemoryViewReference() {
   return twoParts.getMethodAreaMemoryViewReference();
 }
 RegisterPanel getRegisterPanel() {
   return registers;
 }

} // TwoParts is the panel that contains the Stack and Method Area panels class TwoParts extends Panel {

 private StackPanel stack;
 private MethodAreaPanel methodArea;
 TwoParts(int methodAreaMemorySectionSize) {
   setLayout(new GridLayout(1, 2, 5, 5));
   stack = new StackPanel();
   methodArea = new MethodAreaPanel(methodAreaMemorySectionSize);
   stack.setBackground(ColorTable.stackAreaColor);
   methodArea.setBackground(ColorTable.methodAreaColor);
   add(stack);
   add(methodArea);
 }
 public StackMemoryView getStackMemoryViewReference() {
   return stack.getMemoryViewReference();
 }
 public MemoryView getMethodAreaMemoryViewReference() {
   return methodArea.getMemoryViewReference();
 }
 // top, left, bottom, right
 // Want a 10 pixel separation between the twoparts and the register panel
 // above and the control panel below.
 public Insets insets() {
   return new Insets(0, 0, 0, 0);
 }

}


 </source>
   
  
 
  



System memory

   <source lang="java">
   

/*

* This file is part of JGAP.
*
* JGAP offers a dual license model containing the LGPL as well as the MPL.
*
* For licensing information please see the file license.txt included with JGAP
* or have a look at the top of class org.jgap.Chromosome which representatively
* includes the JGAP license policy applicable for any file delivered with JGAP.
*/

import java.io.*; /**

* System-related utility functions.
*
* @author Klaus Meffert
* @since 3.2
*/

public class SystemKit {

 /** String containing the CVS revision. Read out via reflection!*/
 private final static String CVS_REVISION = "$Revision: 1.8 $";
 /**
  * @return total memory available by the VM in megabytes.
  *
  * @author Klaus Meffert
  * @since 3.2 (since 3.0 in GPGenotype)
  */
 public static double getTotalMemoryMB() {
   return getTotalMemoryKB() / 1024;
 }
 /**
  * @return total memory available by the VM in kilobytes.
  *
  * @author Klaus Meffert
  * @since 3.2.1
  */
 public static double getTotalMemoryKB() {
   return (Runtime.getRuntime().totalMemory() / 1024);
 }
 /**
  * @return free memory available in the VM in megabytes.
  *
  * @author Klaus Meffert
  * @since 3.2 (since 3.0 in GPGenotype)
  */
 public static double getFreeMemoryMB() {
   return getFreeMemoryKB() / 1024;
 }
 /**
  * @return free memory available in the VM in kilobytes.
  *
  * @author Klaus Meffert
  * @since 3.2.1
  */
 public static double getFreeMemoryKB() {
   return (Runtime.getRuntime().freeMemory() / 1024);
 }
 /**
  * Nicifies a decimal string by cutting of all but two decimal places.
  *
  * @param a_mem the number to make nice
  * @return nicified number as a string
  *
  * @since 3.3.1
  */
 public static String niceMemory(double a_mem) {
   String freeMB = "" + a_mem;
   int index = freeMB.indexOf(".");
   int len = freeMB.length();
   if (len - index > 2) {
     freeMB = freeMB.substring(0, index + 2);
   }
   return freeMB;
 }
 /**
  * Returns the first line of the result of a shell command.
  * Taken from UUID.
  *
  * @param commands the commands to run
  * @return the first line of the command
  * @throws IOException
  *
  * @since 3.3.3
  */
 static String getFirstLineOfCommand(String[] commands)
     throws IOException {
   Process p = null;
   BufferedReader reader = null;
   try {
     p = Runtime.getRuntime().exec(commands);
     reader = new BufferedReader(new InputStreamReader(
         p.getInputStream()), 128);
     return reader.readLine();
   } finally {
     if (p != null) {
       if (reader != null) {
         try {
           reader.close();
         } catch (IOException ex) {}
       }
       try {
         p.getErrorStream().close();
       } catch (IOException ex) {}
       try {
         p.getOutputStream().close();
       } catch (IOException ex) {}
       p.destroy();
     }
   }
 }

}



 </source>
   
  
 
  



This agent library can be used to track garbage collection events

This agent library can be used to track threads that wait on monitors.

Track method call and return counts

Track object allocations