Name: rmT116609			Date: 05/08/2003
FULL PRODUCT VERSION :
D:\Temp>"c:\Program Files\Java\j2re1.4.2\bin\java" -version
java version "1.4.2-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2-beta-b19)
Java HotSpot(TM) Client VM (build 1.4.2-beta-b19, mixed mode)
FULL OS VERSION :
Microsoft Windows 2000 [Version 5.00.2195]
A DESCRIPTION OF THE PROBLEM :
On this small benchmark application, the Pi calculation gives a wrong result, when running on JDK 1.4.2 Beta.
This does not occur with other JDK versions or when extracting the Pi calculation code from the program. So I suppose it depends on the context (GC running before...). Using strictfp does not change the behavior.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the Zjb program
java -cp . Zjb
EXPECTED VERSUS ACTUAL BEHAVIOR :
With other JDK: Pi=3.141591698659554
With JDK 1.4.2 Beta: Pi=3.1413934230804443
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.List;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
/**
 * Zjb: Zaurus Java Bechmark
 * @author GenePi
 */
class Zjb
	extends Frame
{
	static Zjb _mainWindow;
	
	
	/**
	 * Number of benchmark runs.
	 */
	private final TextField _runs;
	
	
	/**
	 * Results list
	 */
	private final List _results;
	
	
	/**
	 * Wait, program is thinking...
	 */
	private final Label _wait;
	
	
	/**
	 * Start button
	 */
	private final Button _start;
	
	
	/**
	 * Benchmark running
	 */
	private volatile boolean _running = false;
	
	
	/**
	 * Layout the main window.
	 **/
	Zjb()
	{
		super("Zaurus java benchmark 1.0");
		setLayout(new BorderLayout());
		// Input fields
		Panel top = new Panel(new GridLayout(1, 0));
		top.add(new Label("Number of runs"));
		_runs = new TextField("1");
		top.add(_runs);
		add(top, BorderLayout.NORTH);
		// Results list
		_results = new List();
		add(_results, BorderLayout.CENTER);
		// Start button
		final Panel bottom = new Panel(new FlowLayout(FlowLayout.RIGHT));
		_wait = new Label();
		bottom.add(_wait);
		_start = new Button("Start");
		_start.addActionListener(new ActionListener()
		{
			public void actionPerformed(final ActionEvent evt)
			{
				if (!_running)
				{
					// Clear previous results and start benchmark.
					_results.clear();
					_start.setLabel("Stop");
					_wait.setText("Running...          ");
					bottom.validate();
					_running = true;
				}
				else
				{
					_start.setLabel("Start");
					_wait.setText("");
					_running = false;
				}
			}
		});
		bottom.add(_start);
		// Quit button
		final Button quit = new Button("Quit");
		quit.addActionListener(new ActionListener()
		{
			public void actionPerformed(final ActionEvent evt)
			{
				System.exit(0);
			}
		});
		bottom.add(quit);
		add(bottom, BorderLayout.SOUTH);
		// Exit when main window closes
		addWindowListener(new WindowAdapter()
		{
			public void windowClosing(final WindowEvent evt)
			{
				System.exit(0);
			}
		});
		Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
		setSize(dim);
		validate();
	}
	
	
	
	/**
	 * The benchmarks
	 *
	 * @param runs Number of runs
	 */
	private static void runBenchmarks(final int runs)
	{
		long start;
		long end;
		long totalStart;
		long totalEnd;
		
		// Integer arithmetic
		start = System.currentTimeMillis();
		totalStart = start;
		int resultInt = 0;
		for (int i = 0; i < runs; i++)
		{
			resultInt = ackerman(3, 9);
			// resultInt = ackerman(3, 7);
		}
		end = System.currentTimeMillis();
		_mainWindow._results.add("Integer arithmetic: " + ((end - start) / 1000.0) + " s [Ack(3,9)=" + resultInt + "]");
		
		if (!_mainWindow._running)
		{
			return;
		}
		
		
		// Float and double
		start = System.currentTimeMillis();
		double resultDouble = 0.0;
		for (int i = 0; i < runs; i++)
		{
			resultDouble = 0.0;
			for (int j = 1; j < 1000000; j++)
			{
				resultDouble += 1.0 / ((double) j * (double) j);
			}
			resultDouble = Math.sqrt(resultDouble * 6.0);
		}
		end = System.currentTimeMillis();
		_mainWindow._results.add("Double arithmetic: " + ((end - start) / 1000.0) + " s [Pi=" + resultDouble + "]");
		
		if (!_mainWindow._running)
		{
			return;
		}
		
		
		// Big operations
		start = System.currentTimeMillis();
		BigInteger resultBig = new BigInteger("1");
		for (int i = 0; i < runs; i++)
		{
			resultBig = fact(3000);
		}
		end = System.currentTimeMillis();
		_mainWindow._results.add("Infinite arithmetic: " + ((end - start) / 1000.0) + " s [3000!=" + resultBig.toString().substring(1, 20) + "...]");
		
		if (!_mainWindow._running)
		{
			return;
		}
		
		
		// Strings
		start = System.currentTimeMillis();
		String resultString = null;
		for (int i = 0; i < runs; i++)
		{
			final String alphabet = " qwertyuioplkjhgfdsazxcvbnm0789456123./*";
			StringBuffer buf = new StringBuffer();
			for (int j = 0; j < 100000; j++)
			{
				int pos = j % alphabet.length();
				buf.append(alphabet.substring(pos, pos + 1));
			}
			resultString = buf.toString();
		}
		end = System.currentTimeMillis();
		_mainWindow._results.add("Strings: " + ((end - start) / 1000.0) + " s [" + resultString.substring(1, 20) + "...]");
		
		if (!_mainWindow._running)
		{
			return;
		}
		
		// Drawing
		start = System.currentTimeMillis();
		for (int i = 0; i < runs; i++)
		{
			final int size = 200;
			Dialog dialog = new Dialog(_mainWindow, "Drawing...", true);
			dialog.add(new TestPanel(dialog));
			dialog.setSize(size, size);
			dialog.show();
		}
		end = System.currentTimeMillis();
		_mainWindow._results.add("Drawing: " + ((end - start) / 1000.0) + " s");
		
		if (!_mainWindow._running)
		{
			return;
		}
		
		// File copy
		start = System.currentTimeMillis();
		String resultIO = "OK";
		loopIO:
		for (int i = 0; i < runs; i++)
		{
			final String tempName = "/tmp/Zjb.tmp";
			try
			{
				BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(tempName));
				for (int j = 0; j < 1000000; j++)
				{
					out.write((byte) j);
				}
				out.close();
				
				BufferedInputStream in = new BufferedInputStream(new FileInputStream(tempName));
				for (int j = 0; j < 1000000; j++)
				{
					int r = in.read();
					if ((byte) r != (byte) j)
					{
						resultIO = "Failed";
						System.err.println("Content mismatch at " + j);
						break loopIO;
					}
				}
				in.close();
				
				new File(tempName).delete();
			}
			catch(IOException ioe)
			{
				resultIO = "Failed";
				System.err.println(ioe);
				break loopIO;
			}
		}
		end = System.currentTimeMillis();
		_mainWindow._results.add("Files I/O: " + ((end - start) / 1000.0) + " s [1MB written/read/deleted: " + resultIO + "]");
		
		totalEnd = end;
		_mainWindow._results.add("");
		_mainWindow._results.add("Total: " + ((totalEnd - totalStart) / 1000.0) + " s");
	}
	
	
	/**
	 * Utility functions: Ackerman function
	 *
	 * @param m
	 * @param n
	 */
	private static int ackerman(final int m, final int n)
	{
		if (m == 0)
		{
			return (n + 1);
		}
		else if (n == 0)
		{
			return (ackerman(m - 1, 1));
		}
		else
		{
			return ackerman(m - 1, ackerman(m, (n - 1)));
		}
	}
	
	
	/**
	 * Factorial of big numbers.
	 *
	 * @param n
	 * @return
	 */
	private static BigInteger fact(final int n)
	{
		final BigInteger one = new BigInteger("1");
		BigInteger num = new BigInteger("1");
		BigInteger fact = new BigInteger("1");
		for (int i = 2; i <= n; i++)
		{
			num = num.add(one);
			fact = fact.multiply(num);
		}
		
		return fact;
	}
	
	
	/**
	 * Benchmark entry point.
	 *
	 * @param args Command line arguments
	 */
	public static void main(String[] args)
	{
		_mainWindow = new Zjb();
		_mainWindow.show();
		
		synchronized (Zjb.class)
		{
			while (true)
			{
				try
				{
					Zjb.class.wait(500L);
				}
				catch (InterruptedException ie)
				{
					// Wake
				}
				if (_mainWindow._running)
				{
					try
					{
						runBenchmarks(Integer.parseInt(_mainWindow._runs.getText()));
					}
					catch (NumberFormatException nfe)
					{
						_mainWindow._runs.setText("1");
						runBenchmarks(1);
					}
					_mainWindow._running = false;
					_mainWindow._start.setLabel("Start");
					_mainWindow._wait.setText("");
				}
			}
		}
	}
}
class TestPanel
	extends Panel
{
	/**
	 * The dialog containing the panel.
	 */
	private final Dialog _dialog;
	
	
	TestPanel(final Dialog dialog)
	{
		_dialog = dialog;
	}
	
	
	public void paint(final Graphics g)
	{
		Dimension dim = getSize();
		g.setColor(Color.white);
		g.fillRect(0, 0, dim.width, dim.height);
		for (int i = 0; i < 1000; i++)
		{
			Color color = new Color((int) (Math.random() * Integer.MAX_VALUE));
			int x = (int) (Math.random() * dim.width);
			int y = (int) (Math.random() * dim.height);
			int width = (int) (Math.random() * dim.width);
			int height = (int) (Math.random() * dim.height);
			g.setColor(color);
			g.fillRect(x, y, width, height);
		}
		
		g.setColor(Color.white);
		g.fillRect(0, 0, dim.width, dim.height);
		for (int i = 0; i < 1000; i++)
		{
			Color color = new Color((int) (Math.random() * Integer.MAX_VALUE));
			int x = (int) (Math.random() * dim.width);
			int y = (int) (Math.random() * dim.height);
			int width = (int) (Math.random() * dim.width);
			int height = (int) (Math.random() * dim.height);
			g.setColor(color);
			g.fillOval(x, y, width, height);
		}
		
		
		// Hide dialog when finished
		_dialog.hide();
	}
}
---------- END SOURCE ----------
(Review ID: 184686) 
======================================================================