/*********************************************************************** * 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 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 Panel linkPanel; 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