/***********************************************************************
* GarbageTracker.java - Source Code (requires java 1.1) *
* Version release date : May 23, 2001 *
* Copyright (C) 1999-2001 Neural Semantics sprl, Belgium *
* Author : Michel Petre mpetre@neuralsemantics.com *
* *
* http://www.neuralsemantics.com/ *
* *
* This code is released under GNU GPL license, version 2 or later. *
* *
* This notice must remain intact in all copies of this code. *
* This code is distributed WITHOUT ANY WARRANTY OF ANY KIND. *
* The GNU GPL license can be found at : *
* http://www.gnu.org/copyleft/gpl.html *
* *
* Feel free to use any portion of this code for your best purposes. *
***********************************************************************/
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class GarbageTracker extends Applet
implements Runnable, ItemListener,
MouseListener, AdjustmentListener {
// program name
final static String TITLE = "The garbage tracker";
// optimization modes
final static int NONE = 0;
final static int REUSE = 1;
// number of color rectangles displayed on 1 line/1 column
// on the screen. The dynamic color area is divided into
// (MATRIX * MATRIX) rectangles.
static int MATRIX = 20;
// basic color increment at each pass
static int COLOR_INCREMENT = 1;
static String[] sPct = {"0%","20%","40%","60%","80%","100%"};
// current optimization mode
private int optimization;
// width & height of the canvas
private int cw, ch;
// width & height of the gauge
private int gw, gh;
// array of colors (used in object recycling mode)
private Color[][] colorRecycled;
private Color[] colorReused;
private int[] rgb;
// current color index
private int colorIndex;
// current color increment (signed)
private int colorIncrement;
// current number of passes (for time calculation)
private int nPass;
// current start time for timer
private long timerStart;
// offscreen Image and Graphics objects
private Image imgCanvas, imgGauge;
private Graphics graphCanvas, graphGauge;
// awt controls
private Canvas canvas, gauge;
private Panel linkPanel, control;
private Checkbox checkGC = new Checkbox("Automatic GC");
private Checkbox checkRecycle = new Checkbox("Optimized ");
private Scrollbar barSleep =
new Scrollbar(Scrollbar.HORIZONTAL, 1, 1, 3, 101);
private Label labelSleep = new Label();
private Label labelTime = new Label();
private Label labelBar = new Label();
// hyperlink objects
private Label labelNS;
private Color inactiveLinkColor = Color.yellow;
private Color activeLinkColor = Color.white;
private Font inactiveLinkFont = new Font("Dialog", Font.PLAIN, 14);
private Font activeLinkFont = new Font("Dialog", Font.ITALIC, 14);
// flag automatic GC mode
private boolean isAutomaticGC = true;
// initial sleep time for thread
private int sleepTime = 30;
// thread
private Thread runner;
// this applet's Runtime object
private Runtime runtime = Runtime.getRuntime();
//**********************************************************************
// Constructors
//**********************************************************************
public GarbageTracker() { }
//**********************************************************************
// Methods
//**********************************************************************
public void init() {
setLayout(new BorderLayout());
setBackground(Color.black);
control = new Panel();
this.composeControl();
add("South", control);
linkPanel = new Panel();
this.composeLink();
add("North", linkPanel);
Panel west = new Panel();
west.add(new Label(" "));
add("West", west);
gauge = new Canvas();
gauge.setSize(60, 20);
add("East", gauge);
canvas = new Canvas();
add("Center", canvas);
}
//------------------------------------------------------------------------
private void composeControl() {
checkGC.addItemListener(this);
checkGC.setState(isAutomaticGC);
checkGC.setBackground(Color.darkGray);
checkGC.setForeground(Color.white);
checkRecycle.addItemListener(this);
checkRecycle.setState(false);
checkRecycle.setBackground(Color.darkGray);
checkRecycle.setForeground(Color.white);
labelBar.setText(" Sleep :");
labelBar.setForeground(Color.white);
barSleep.addAdjustmentListener(this);
// assign fixed size to the scrollbar
barSleep.setValue(sleepTime);
barSleep.setSize(90, 16);
Panel pSleep = new Panel();
pSleep.setLayout(null);
pSleep.add(barSleep);
pSleep.setSize(90, 16);
labelSleep.setText(sleepTime + " ms");
labelSleep.setForeground(Color.white);
labelTime.setText(" Cycle : ... ");
labelTime.setForeground(Color.yellow);
Panel pControl = new Panel();
pControl.setLayout(new FlowLayout(FlowLayout.CENTER));
pControl.add(checkGC);
pControl.add(checkRecycle);
pControl.add(labelBar);
pControl.add(pSleep);
pControl.add(labelSleep);
pControl.add(labelTime);
control.setBackground(Color.darkGray);
control.setLayout(new BorderLayout());
control.add("South", pControl);
}
//------------------------------------------------------------------------
private void composeLink() {
linkPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 5));
linkPanel.setFont(inactiveLinkFont);
linkPanel.setForeground(Color.yellow);
// create a hand cursor for the hyperlink area
Cursor linkCursor = new Cursor(Cursor.HAND_CURSOR);
linkPanel.setCursor(linkCursor);
Label labelName = new Label(TITLE + " \u00a9");
labelName.setForeground(inactiveLinkColor);
labelName.setAlignment(Label.RIGHT);
labelName.addMouseListener(this);
labelNS = new Label(" Neural Semantics ");
labelNS.setForeground(inactiveLinkColor);
labelNS.setFont(inactiveLinkFont);
labelNS.setAlignment(Label.LEFT);
labelNS.addMouseListener(this);
linkPanel.add(labelName);
linkPanel.add(labelNS);
}
//------------------------------------------------------------------------
private void setTimer(long baseTime) {
if (baseTime > 0) {
double time = (double)((int)(baseTime - nPass * sleepTime) / 10) / 100d;
labelTime.setText(" Cycle : " + time + " sec");
}
else {
labelTime.setText(" Cycle : .... sec");
colorIncrement = COLOR_INCREMENT;
colorIndex = MATRIX + 1;
}
timerStart = System.currentTimeMillis();
nPass = 0;
control.doLayout();
}
//**********************************************************************
// Thread
//**********************************************************************
public void start() {
// start the runner thread
if (runner == null) {
runner = new Thread(this);
runner.start();
}
}
//------------------------------------------------------------------------
public void run() {
setTimer(0L);
int colorMin = MATRIX;
int colorMax = 255 - MATRIX;
while (true) {
if ((colorIndex >= colorMax) || (colorIndex <= colorMin)) {
colorIncrement = -colorIncrement;
setTimer(System.currentTimeMillis() - timerStart);
nPass = 0;
}
colorIndex += colorIncrement;
repaint();
// call the garbage collector in non-automatic GC mode
if (! isAutomaticGC)
runtime.gc();
try { Thread.sleep(sleepTime); }
catch (InterruptedException e) { break; }
nPass += 1;
}
}
//------------------------------------------------------------------------
public void stop() {
this.cleanup();
}
//------------------------------------------------------------------------
public void destroy() {
this.cleanup();
}
//------------------------------------------------------------------------
private synchronized void cleanup() {
// kill the runner thread
if (runner != null) {
try {
runner.stop();
runner.join();
runner = null;
}
catch(Exception e) { }
}
}
//**********************************************************************
// MouseListener Interface
//**********************************************************************
public void mouseClicked(MouseEvent e) {
}
//-------------------------------------------
public void mouseEntered(MouseEvent e) {
// text color rollover
labelNS.setForeground(activeLinkColor);
labelNS.setFont(activeLinkFont);
invalidate();
transferFocus();
showStatus("Click to connect to Neural Semantics home page");
}
//-------------------------------------------
public void mouseExited(MouseEvent e) {
// text color rollover
labelNS.setForeground(inactiveLinkColor);
labelNS.setFont(inactiveLinkFont);
invalidate();
transferFocus();
showStatus("");
}
//-------------------------------------------
public void mousePressed(MouseEvent e) {
// link to Neural Semantics website
try {
java.net.URL url = new java.net.URL("http://www.neuralsemantics.com/");
AppletContext ac = getAppletContext();
if (ac != null)
ac.showDocument(url);
}
catch(Exception ex){ }
}
//-------------------------------------------
public void mouseReleased(MouseEvent e) {
}
//**********************************************************************
// ItemListener Interface
//**********************************************************************
public void itemStateChanged(ItemEvent e) {
Object source = e.getSource();
if (source == checkGC) {
isAutomaticGC = checkGC.getState();
setTimer(0L);
}
else if (source == checkRecycle) {
if (checkRecycle.getState()) {
optimization = REUSE;
colorRecycled = null;
if (colorReused == null)
colorReused = new Color[256];
for (int i=0;i<256;i++)
colorReused[i] = new Color(i, i, i);
}
else
optimization = NONE;
setTimer(0L);
}
}
//**********************************************************************
// AdjustmentListener Interface
//**********************************************************************
public void adjustmentValueChanged(AdjustmentEvent e) {
Object source = e.getSource();
// sleepTime range : 3 ms - 100 ms
if (source == barSleep) {
sleepTime = barSleep.getValue();
labelSleep.setText(sleepTime + " ms");
setTimer(0L);
}
}
//**********************************************************************
// Painter
//**********************************************************************
public void update (Graphics g) {
Graphics canvasGraph = canvas.getGraphics();
Graphics gaugeGraph = gauge.getGraphics();
if (imgCanvas == null) {
Dimension dim = canvas.getSize();
cw = dim.width;
ch = dim.height;
if ((cw > 0) && (ch > 0)) {
imgCanvas = createImage(cw, ch);
graphCanvas = imgCanvas.getGraphics();
}
}
if (imgGauge == null) {
Dimension dim = gauge.getSize();
gw = dim.width;
gh = dim.height;
if ((gw > 0) && (gh > 0)) {
imgGauge = createImage(gw, gh);
graphGauge = imgGauge.getGraphics();
}
}
if ((graphCanvas == null) || (graphGauge == null))
return;
graphCanvas.clearRect(0, 0, cw, ch);
int cx = (int)(cw / MATRIX);
int cy = (int)(ch / MATRIX);
int idx;
switch (optimization) {
case NONE:
// create (MATRIX * MATRIX) new Color objects.
// previously created Color objects can be garbage collected
for (int i=0; i<MATRIX; i++) {
idx = colorIndex + colorIncrement*i;
for (int j=0; j<MATRIX; j++) {
graphCanvas.setColor(new Color(idx, idx, idx));
graphCanvas.fillRect(i*cx, j*cy, cx, cy);
}
}
break;
case REUSE:
// use the previously created Color objects, switching
// their location
for (int i=0; i<MATRIX; i++) {
idx = colorIndex + colorIncrement*i;
for (int j=0; j<MATRIX; j++) {
graphCanvas.setColor(colorReused[idx]);
graphCanvas.fillRect(i*cx, j*cy, cx, cy);
}
}
}
// draw gauge scale
graphGauge.clearRect(0, 0, gw, gh);
graphGauge.setColor(Color.lightGray);
int gy = gh - 3;
int dgy = (int)((gh - 60) / 10);
graphGauge.drawLine(0, gy, gw, gy);
graphGauge.drawLine(0, gy-dgy*10, gw, gy-dgy*10);
for (int i=1;i<10;i++)
graphGauge.drawLine(35, gy-dgy*i, gw, gy-dgy*i);
for (int i=1;i<5;i++)
graphGauge.drawString(sPct[i], 0, gy-dgy*i*2);
// estimate JVM's current memory state (gauge height)
int memlevel = (int)(runtime.freeMemory() * gh / runtime.totalMemory());
// draw gauge
graphGauge.setColor(Color.green);
graphGauge.fillRect (45, gy-memlevel, 10, memlevel);
graphGauge.drawString(" %", 0, 15);
graphGauge.drawString(" free", 0, 30);
graphGauge.drawString("memory", 0, 45);
// paint canvas
if (canvasGraph != null) {
canvasGraph.drawImage(imgCanvas, 0, 0, canvas);
canvasGraph.dispose();
}
// paint gauge
if (gaugeGraph != null) {
gaugeGraph.drawImage(imgGauge, 0, 0, gauge);
gaugeGraph.dispose();
}
}
}
|