![]() |
|||||||||||||||||||
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
|
Table of Contents |
|
Java's out-of-the-box cross-platform compatibility is achieved by compiling Java into Java Byte Code, a compact but still fairly high-level set of machine instructions that must be executed (interpreted) on a Java Virtual Machine (JVM). The JVM is commonly implemented in the form of a native program (rather than being a real, physical CPU on your computer's main board.)
The overhead of interpreting the Java Byte Code requires a fairly significant commitment of CPU power. Although this is not as steep as interpreting BASIC programs or ARexx scripts, for example, you can expect a plain JVM to execute programs at about 10% the speed that a native program might run.
The Amiga, relying for much of its speed on peripheral I/O processors, is not endowed with the fairly hefty CPU power that interpreting Java Byte Code at a decent speed requires. This presents a problem for running Java on the Amiga.
Another problem for the Amiga is the fact that the JVM available for it does not implement a Just In Time (JIT) compiler, which performs a translation of the Java Byte Code to native machine code, but only for the purpose of executing the code. The result is not stored to your harddisk. JVMs that implement JIT compilation can expect to execute Java Byte Code at about 25% the speed of native code. As much as the Amiga could benefit from that, it doesn't have a JIT-capable JVM at this time.
Yet another problem for the Amiga is the fact that the Abstract
Windowing Toolkit (AWT) is not available for the Amiga in completed
form.
A
preliminary (and incomplete) AWT for the Amiga, along with a JVM (Kaffe
0.8.4) can be found here.
So, is it worth the effort trying to get Java to run on my Amiga?
That depends entirely on how serious you are: On a scale from zero to ten (with ten being utterly determined to get it to work) you'd have to be at least at a seven or eight. If you're just trying to use your Amiga to see what the Java hype is all about, you're not going to be impressed.
But let me not discourage you any further. There are distinct benefits to getting Java to run on your Amiga. In no particular order, these are:
|
Although you may not yet be able to do much in the way of Java programs with Graphic User Interfaces (GUIs), you will be able to write networking programs quite easily! I've written a simple HTTPD (web server) in about fifty or so lines of code that worked fine on the Amiga (until the JVM crashed, but that's the kind of problem that only your efforts and mine can locate, report and help fix.)
On a 35MHz 68040, Java runs quite slow, but still acceptably well if you don't expect too much. The afforementioned web server performed quite well, actually. If you have a 50MHz 68060 you might actually find Java to be a bit slow, but not too bad. If you only have a 14Mhz 68020 you will probably look at Java as no more than a novelty. Don't say I didn't warn you.
But if you have the CPU power and you're still serious, then by all means: read on!
|
MOca is a JVM by Finale Development; MERAPI, by Haage & Partner. Both are to offer JIT support. Of the two, MERAPI is supposed to be closer to being finished, but various implementation problems appear to be keeping both of these JVMs from being released.
In any case, until they are released they are no more than vaporware. Neither is likely to be released at this point.
Here is how to get the files you need:
|
Create yourself a nice development directory for your Java stuff.
I chose WORK:Java/
and permanently assigned a logical volume
name Java:
to it. If you don't know how to do this kind
of thing, then you shouldn't be trying your hand at any of this anyway.
Sorry.
md WORK:Java assign Java: WORK:Java cd Java: tar -xf kaffe-0.7.1-bin.tar lha -x kaffe-0.7.1-sun-bin.lha |
Now you need to setup a CLASSPATH environment variable so that your
(and other) Java software can find all the other classes installed that
it will need to run. If you use a Java:
assign like I do,
then you can just type this:
copy console: env:CLASSPATH Java:share/kaffe/classes.zip;. |
and press ^\ (ctrl-\ i.e.EOF signal); notice that after the ``. . . classes.zip'' there is a semicolon followed by a dot. The semicolon is a separator between multiple paths (or .zip or .jar files) and the dot represents the current directory. This current directory is important, otherwise you cannot execute classes without placing them into a directory where they are visible (the current directory is not visible by default, that is what the dot does.)
I have also created two aliases in my s:Shell-Startup
and added the Java:bin
directory to my paths (you can do
that in s:Shell-Startup
or in your s:startup-sequence
before the LoadWB to make the addition system wide.) Make sure you get
the capitalization on sun.tools.javac.Main correct--Java is case sensitive!
alias javac "Java:bin/kaffe sun.tools.javac.Main []" alias java "Java:bin/kaffe []" |
That's it! You can now type
javac FunTest.java |
to compile the FunTest
class in the FunTest.java
file (see below). Again, note that class names are case sensitive and
must (exactly) match the file in which they're defined. Although this
may seem like a pain, C/C++ programmers will be familiar with such requirements,
and after a while you'll find that this enforces more careful naming
and makes the managment of many packages and class files easier and
more reliable.
To run your compiled class, type
java FunTest |
(without the .class extension)
Here is a tiny little (and fairly banal) program just to see if you have everything working. After you've tried it out, go out and buy yourself a good Java book! I can happily recommend the following: Just Java, second edition, by Peter van der Linden; The Sunsoft Press, Java Series. The author has a great sense of humor and is quite aware of how Microsoft has been trying to fuck up the Java initiative. Great reading, great introduction to most all aspects of Java. 550 pages.
Store the following in a file named
FunTest.java
; the example after the aliases above will
help you compile and run this file:
public class FunTest { public static void main( String argv[] ) { if( argv.length == 0 ) { for( int i=0; i<argv.length; i++ ) { System.out.println( "Argument #" + i + " = '" + argv[i] + "'" ); } System.out.println( "Hey, wasn't that fun?" ); } else { System.out.println( "How about giving me a few command line " + "arguments to print?" ); } } } |
If you have anything less than a fast 68030 or 68040 in your Amiga you will probably be disappointed by the performance. Compilation is quite slow (the compiler is itself an interpreted Java program!) and execution is, of course, accomplished by interpreting the byte code.
The important thing is, however: Your Amiga can do Java. It just does not yet have a production-quality JVM. But for now, you'll do well to learn Java with what you've got: a free JVM for your Amiga: Kaffe!
Also, see the ADE-Java Mailing List FAQ!
I know how tempting it is to dive right in, type the old Hello World program into a file, then compile and execute it. From there, your ability to manage dozens of classes will quickly go downhill until one day you wake up and say to yourself: I should have done something about this mess a long time ago. . .
What are packages?
You will notice that there are some classes, such as Hashtable or
Vector, that are actually named java.util.Hashtable
and
java.util.Vector
. You cannot just omit the java.util.
when you reference these classes, unless you provide that in an import
statement, such as import java.util.Hashtable
or the more
general form, java.util.*
, which includes everything from
the java.util package.
Did you notice that I just mentioned the ``java.util package''?
That is because the Hashtable class is defined to be part of the java.util package. If you wanted to create a class of your own, you should decide on a good package name and then indicate that your class is part of this package. Let me show you how:
package com.ringlord.util; // import com.ringlord.3d.*; import com.ringlord.net.*; // import java.util.Hashtable; import java.net.ServerSocket; // public class TheWebIn3D extends Frame implements ActionListener,ItemListener; { public static void main( String args[] ) { //your code goes here :) } } |
Let's look at the first line. My company's domain name is ringlord.com
,
so it makes good sense to use the ``backwards'' representation of this,
namely com.ringlord
as the basename for all my packages.
That way my packages would not conflict with yours.
A really bad choice for your package name would be your first name,
or just my.util
. The idea is that you may end up distributing
your packages with an application whose package names conflict with
others. The result is that things would utterly fail to work. You definitely
want to avoid conflicts. Take my word for it!
Another thing to avoid is naming your packages with anything that
begins with java.
or javax.
or sun.
,
etc. These names are already taken and are reserved. Don't mess with
them!
So, a good base package name will last you a long time, and forms the basis for all your software. If you end up distributing it or using it only privately, proper organization will prove highly valuable eventually.
As many of us don't necessarily have our own domain name registered,
there is a fairly good way to name your packages that is not likely
to end up in immediate conflicts: use your last and first name, possibly
with some other addition. If your name happened to be Alan Turing, you
could use org.turing.alan
for your base package name, and
create any set of package names under that set, such as org.turing.alan.machine
or org.turing.alan.test
.
Are you still with me? Good!
If you think like me, you've been shaking your head at all this long-winded babble, and are hoping that this isn't necessary. No, it isn't necessary, but it will make things a great deal easier in the long run! Trust me on this, it's true. If you don't believe me, try your hand at anything more than trivial things and you'll come to regret not using packages.
Once you have put something like package org.turing.alan.machine
at the top of your nifty new graphical Turing Machine demonstration
class, you can then simply, and easily reference this class from any
other class, without regard to directory structures, current working
directory, etc. as long as the directory where the package name
starts (org
in the example) is in the classpath.
You reference a class in this package with an import
statement. Yes, there are a number of them in the example above. Some
of these end in a .* and some in a normal name. The last portion
is always a class name, such as TuringMachineDemo (with the .class extension
left off); if the import statement has a * at the end, then you are
including all classes from the named package, not just a specific one.
This is convenient, but will slow the compiler down a little bit and
also lacks specificity, which is often helpful during the debugging
phase.
Let's continue with the pesky Turing Machine example, and let's set up the following directory structure:
WORK:java/ org/ turing/ alan/ machine/ test/ demo/
If WORK:java
is in the classpath environment variable,
then this directory structure represents (on most computer systems,
including the Amiga) the following packages:
org org.turing org.turing.alan org.turing.alan.machine org.turing.alan.machine.util org.turing.alan.machine.net org.turing.alan.machine.io org.turing.alan.test org.turing.alan.demo
The first two are just an incidental result of the directory structure and should really be ignored as incomplete. The third is the minimal package name, and the remainder are sub-packages that represent your own organizational style. You can create subpackages within those, as deep as you like or is necessary.
Now, create your Turing Machine class as part of the org.turing.alan.machine
package. The file would be stored in the directory WORK:java/org/turing/alan/machine/
and define itself to be part of that particular package with a statement
at the very top: package org.turing.alan.machine;
To compile this class, while in that source file's directory, you'd enter this command:
javac -d WORK:java TMComputer.java |
This assumes, of course, that you create a file WORK:java/org/turing/alan/machine/TMComputer.java
that the javac compiler could compile. But what's the -d java?
It tells the compiler that the output file (a .class) is to be stored such that the root of its package starts at the WORK:java directory. This happens to coincide with an entry in your classpath environment variable, and with good reason!
If you were to omit the directory argument, the compiler might not know where the source file is to go. Sun's latest compilers just dump the .class into the current directory, which is usually correct, but older versions, including those currently available for the Amiga will assume the current directory as the root of the package and create a path for the package ``downward'' from where you are compiling. You'd then end up with a useless and rather confusing set of directories below the current one.
The easiest way to deal with this is to create yourself a little script to compile the classes for you, and you rarely again have to worry about where exactly the root of your packages starts.
What does this really buy you?
java org.turing.alan.machine.TMComputer
I hope the above is clear enough to follow, that you are convinced of the usefulness of packages, and that you make good use of them while you venture into the world of Java!
There are reasons for and against the use of the CLASSPATH environment variable. Proponents might argue that adding all your packages and JAR and ZIP files into the CLASSPATH makes it easier. The problem is one of maintenance and performance: if you have a hundred different Java packages installed, your CLASSPATH will not only become unwieldy but also contain references to package directories and files that are not needed most of the time.
Considering that you may soon tire of typing java mystuff.test.FunTest
you will probably find yourself anyway writing a little wrapper script
to execute this command. The easiest thing to do, therefore, is to modify
such a script to include a -classpath argument listing all
the packages that this particular program needs, and only those
packages.
I have found that it's useful to reference in the CLASSPATH only the packages that are part of the standard Java installation. This would be the classes.zip file containing the java.* packages, as well as the swingall.jar file that represents the javax.swing.* packages of the Java Foundation Classes.
NOTE: JFC/Swing is a completely platform independent set of GUI components. While this may sound like the ideal solution to the Amiga's lack of not having a full AWT available, you must understand that all GUI stuff eventually has to interface with a native operating systems. In this case, JFC/Swing extends AWT components. For this reason, mention of the JFC/Swing packages for the Amiga is merely academic and will not actually work.
All package references that are specific to your program would then need to be referenced in the wrapper script:
java -classpath ${CLASSPATH};Java:Swing/swingall.jar mystuff.test.FunTest |