Java Newsletter by Glen McCluskey - Issue 14
Issue #014
February, 1997
Contents
- Serialization
- Introduction to Java Security Part 1 - Virtual Machine
- Web Site for Java Indexing Software
- Comparing C/C++ and Java Part 14 - Local Declarations
- Introduction to AWT Programming Part 1 - A Simple Example
- Correction
SERIALIZATION
Imagine that you have a complex data structure in memory, one with many internal links and fields in it. At the end of the execution of an application, you'd like to somehow save this data structure permanently and then restore it for the next execution of the application.
Java serialization, new in version 1.1, is a way of doing this. It's a mechanism for turning a data structure into a stream of bytes, which can be written to a file, and then read back in to another data structure.
Let's look at a simple example of this:
// file write.java
import java.io.*;
public class write {
private static final int N = 25;
public static void main(String args[])
{
int x[][] = new int[N][2];
for (int i = 0; i < N; i++) {
x[i][0] = i;
x[i][1] = i * i;
}
try {
FileOutputStream fos =
new FileOutputStream("xxx");
ObjectOutputStream oos =
new ObjectOutputStream(fos);
oos.writeObject(x);
oos.flush();
fos.close();
}
catch (Throwable e) {
System.err.println("exception thrown");
}
}
}
// file read.java
import java.io.*;
public class read {
public static void main(String args[])
{
int x[][] = null;
try {
FileInputStream fis =
new FileInputStream("xxx");
ObjectInputStream ois =
new ObjectInputStream(fis);
x = (int[][])ois.readObject();
fis.close();
}
catch (Throwable e) {
System.err.println("exception thrown");
}
for (int i = 0; i < x.length; i++)
System.out.println(x[i][0] + " " + x[i][1]);
}
}
In this example, we build a table of squares in a two-dimensional array, then write the array to a file using writeObject(). We then read the array back into a separate program using readObject(), casting the Object reference to the appropriate type.
This operation may not seem like much, but it's hard to do in other languages, and it's necessary to devise various ad hoc methods for doing so.
For a class to be serializable, it must implement the Serializable interface:
public class xxx implements java.io.Serializable {
// stuff
}
This interface is empty, and simply serves as a flag to allow you to specify which classes are serializable. In the example above, the object we serialized was an array, treated as a class type by Java.
Classes which require special handling during serialization can implement their own writeObject() and readObject() methods.
There are several interesting quirks with serialization which we may discuss at some point.
INTRODUCTION TO JAVA SECURITY PART 1 - VIRTUAL MACHINE
If you've paid much attention at all to coverage of Java in the technical and business press, you might have encountered discussions on Java security, and read about malicious applets and so on. This is an interesting and complex subject to contemplate, and we'll spend several issues looking at it. There are multiple types and levels of security to consider.
Let's first look at a short C program:
void main()
{
char c;
int fd;
char* p = 0;
char buf[1024];
fd = open("data", 0);
while (read(fd, &c, 1) == 1)
*p++ = c;
close(fd);
}
This is a mixture of C code and UNIX system calls. It opens a data file, reads from it, and places the read characters into a character buffer.
Unfortunately, this program has a bug, in that the statement:
p = buf;
was omitted. So the program will write via the pointer p, but p is null (0), and the bytes will get written into memory location 0 and succeeding locations. If you're running on a DOS machine, this will probably silently crash your computer. If you are on a UNIX machine with virtual address space starting at 0, with text (the program itself) in low memory, then perhaps you'll get a segmentation violation error.
The point is that a language like C is "close" to the hardware. This is literally true if running with DOS, somewhat less true if using virtual memory and process protection. Direct use of system calls for doing I/O in the example above is another illustration of this point. This feature of C is both a strength and a weakness. For example, C is a good language for writing I/O device drivers, because it's close to the hardware.
Java takes a different tack. It has no user-visible pointers, and no notion of an explicit memory address that you can manipulate or print out. With Java it's still possible to make the dumb mistake found in the example above, but the result would simply be an immediate null pointer exception. There is no way to write a byte to physical or virtual address 0.
Similarly, there is no direct access to system calls. A Java program can certainly do I/O to disk files (applets are restricted in this area), but it can't make system calls itself.
This insulation from the physical machine, via the Java Virtual Machine, means that program execution tends to be safer as far as program crashes and interference with other programs go. The tradeoff is inability to control the actual physical machine, and some loss of efficiency. This implies that Java is suited for a somewhat different set of applications than a language like C, though of course there is much overlap between the two.
WEB SITE FOR JAVA INDEXING SOFTWARE
We mentioned last time about the availability of a trial version of some Java software for indexing files on disk. If you want to find out further about this, you can look at the Web site:
http://www.sni.net/~glenm/index/index.htm
COMPARING C/C++ AND JAVA PART 14 - LOCAL DECLARATIONS
In C, when you declare local variables, it's necessary to group them all together at the top of a function:
void f()
{
int i;
double d;
char* p;
// stuff
}
C++ and Java relax this restriction, and allow the declaration of variables anywhere within the function or method:
void f()
{
int i = 0;
g(i);
String s = "xxx";
h(s);
}
and so on. The scope of such declarations is to the end of the block they're declared in.
It's also possible to declare loop variables within the loop initialization, as in:
for (int i = 1; i <= 10; i++) {
System.out.println(i);
}
i = 37; // invalid
and the scope is to the end of the for block.
This feature is useful in several ways. In general, it's best to minimize the scope of a given declaration, to help in avoiding dumb programming errors (for example in "recycling" a variable), and doing so can also help to optimize memory management.
The tradeoff is that introducing declarations in the middle of a block of code can be confusing to the reader of that code.
INTRODUCTION TO AWT PROGRAMMING PART 1 - A SIMPLE EXAMPLE
In previous issues we've discussed various aspects of applet programming. Starting with this issue, we're going to branch out a bit and consider the more general topic of constructing Graphical User Interfaces (GUIs) using the AWT (Abstract Windowing Toolkit). The examples we present will be actual Java standalone programs rather than applets. That is, they'll have their own main() method.
The AWT can be viewed as a high-level abstract means of describing what a window or windows should look like. The AWT is actually implemented differently on different platforms, using windowing primitives appropriate to each platform. You can view GUI programming using the AWT as construction of a complex data structure describing a window, which is interpreted at program execution time.
Let's start out by looking at a simple example. This program takes a single argument, which is the name of a text file, and displays that file in a scrollable window. This is kind of like the "more" program available in UNIX and DOS:
import java.awt.*;
import java.io.*;
public class More extends Frame {
private static Button b1 = new Button("New File");
private static Button b2 = new Button("Exit");
private static TextArea ta = new TextArea(24, 80);
// handle mouse events
public boolean action(Event e, Object arg)
{
if (e.target instanceof Button) {
if (e.target == b1) {
new_file();
return true;
}
if (e.target == b2) {
System.exit(0);
return true;
}
return false;
}
else {
return false;
}
}
// select a new file to view
private void new_file()
{
FileDialog fd = new FileDialog(this, "Open File",
FileDialog.LOAD);
fd.show();
if (fd.getDirectory() == null ||
fd.getDirectory().equals(""))
return;
if (fd.getFile() == null || fd.getFile().equals(""))
return;
if (fd.getFile().equals("*.*"))
return;
String fn = fd.getDirectory() + File.separator +
fd.getFile();
load(fn);
}
// load a file
private void load(String fn)
{
RandomAccessFile raf = null;
StringBuffer sb = new StringBuffer();
try {
String s = null;
raf = new RandomAccessFile(fn, "r");
while ((s = raf.readLine()) != null) {
sb.append(s);
sb.append('\n');
}
raf.close();
}
catch (Throwable e) {
System.err.println("file I/O error");
System.exit(1);
}
ta.setText(sb.toString());
}
// constructor
public More(String title, String fn)
{
super(title);
resize(600, 450);
Panel p1 = new Panel();
p1.setLayout(new FlowLayout(
FlowLayout.CENTER, 100, 0));
p1.add(b1);
p1.add(b2);
Panel p2 = new Panel();
ta.setEditable(false);
p2.add(ta);
setLayout(new FlowLayout());
add(p1);
add(p2);
load(fn);
show();
}
public static void main(String args[])
{
Frame f = new More("More", args[0]);
}
}
We start by constructing a Frame, an AWT type suitable for representing a top-level application window. We resize the frame, and then add a couple of panels to it. What are panels? A panel is an AWT entity useful for holding or representing a logical chunk of a larger interface. In this example, one of the panels holds a couple of buttons used for switching files and for exiting, and the other holds the text area that actually displays the file.
Given two buttons within a panel, or two panels in a frame, how does the AWT know how to order or arrange these items? We tell the AWT about this via a layout manager, in this case by establishing a FlowLayout object and attaching it to the frame. This type of layout arranges objects in rows left to right, and goes to the next row when it runs out of space. So the two buttons are arranged left to right within panel p1. Panel p2 is laid out on the next "row" after p1, because you can't fit a large text area right next to a set of buttons.
Actual file loading is straightforward. We read the lines in from the file, append them together, and when done call setText() to set the text for the TextArea object. A TextArea object already has scroll bars with it and we don't need to worry about those.
If we want to switch files, we can use a FileDialog entity, which handles most of the work of file selection. This brings up a menu of files that looks similar to what you see on a PC running Windows.
Finally, we define an action() method for handling events in the frame, in this case file switching or exiting.
This program has a couple of deficiencies, most notably that it reads a whole file in at one time. With fairly slow I/O this can be a problem for very large files. But the program does serve to illustrate some of the basics of AWT use. We'll be looking at some of these areas in more detail in future issues.
CORRECTION
In issue #013 there was this bit of code, dealing with image filtering:
int a = rgb & 0xff000000;
int r = ((rgb & 0xff0000) + 0xff0000) / 2;
int g = ((rgb & 0xff00) + 0xff00) / 2;
int b = ((rgb & 0xff) + 0xff) / 2;
This should be:
int a = rgb & 0xff000000;
int r = (((rgb & 0xff0000) + 0xff0000) / 2) & 0xff0000;
int g = (((rgb & 0xff00) + 0xff00) / 2) & 0xff00;
int b = (((rgb & 0xff) + 0xff) / 2) & 0xff;
Without this change, a low bit can "leak" into the next 8-bit slot in the 32-bit quantity.
Thanks to David Springer for pointing this out.
ACKNOWLEDGEMENTS
Thanks to Jay Burgess, Thierry Ciot, Irv Kanode, Mike Paluka, Srihari Sampathkumar, Jason Sharp, and Bob Shore for help with proofreading.
SUBSCRIPTION INFORMATION / BACK ISSUES
To subscribe to the newsletter, send mail to majordomo@world.std.com with this line as its message body:
subscribe java_letter
Back issues are available via FTP from:
rmi.net /pub2/glenm/javalett
or on the Web at:
There is also a C++ newsletter. To subscribe to it, say:
subscribe c_plus_plus
using the same majordomo@world.std.com address.
-------------------------
Copyright (c) 1997 Glen McCluskey. All Rights Reserved.
This newsletter may be further distributed provided that it is copied in its entirety, including the newsletter number at the top and the copyright and contact information at the bottom.
Glen McCluskey & Associates
Professional Computer Consulting
Internet: glenm@glenmccl.com
Phone: (800) 722-1613 or (970) 490-2462
Fax: (970) 490-2463
FTP: rmi.net /pub2/glenm/javalett (for back issues)
Web: http://rainbow.rmi.net/~glenm