PROGRAMMING

 PC Hardware  |  PC Software  |  Networking  |  Web Designs  |  News Letter   |  Home

 

 JAVA 5

 

You can get 'Just Java' at Amazon.com                             You can get 'Not Just Java' at Amazon.com 


15. Networking and Distributed Objects

RMI Issues

Note that there is an RMI FAQ at http://java.sun.com/products/jdk/1.2/docs/guide/rmi/faq.html

  1. (Sect. 15) Should I use CORBA in preference to RMI? Or DCOM? Or what?

*If your distributed programs are wholly written in the Java programming language, then RMI provides a simpler mechanism that allows the transfer of code, pass-by-value of objects, and automatic garbage collection of remote objects.
If you need to connect to C++ (or other language) systems or you need CORBA-specific services, then CORBA is your choice.
In Java 1.3 Sun has aligned RMI to work more closely with CORBA. Sun has simply added an IIOP transport layer to RMI to support interoperability with CORBA. Java technology-enabled programs can now use RMI to access CORBA-based objects through IIOP, the OMG's CORBA-based protocol. This is very good news for those building heterogenous Enterprise systems, although it will take some additions to IIOP to support the pieces that RMI uses.
Microsoft spokespeople have tried to promote DCOM by spreading misinformation that RMI is changing or being dropped. That is totally wrong. The RMI API continues unchanged in its current form. Using DCOM would restrict your code to only ever run on Microsoft platforms using Intel hardware, and negates the "write once, run anywhere" Java philosophy. You would have to recompile your DCOM code to run it on other Microsoft platforms like Compaq's (formerly DEC's) alpha computer. Non-portable, single vendor code should be avoided. DCOM/DNA has limitations for use in the enterprise.
Other sites:

http://www.javaworld.com/javaworld/jw-10-1997/jw-10-corbajava.html has a good intro to CORBA in the Java world.
http://www.objenv.com/cetus has a CORBA/RMI comparison.

  1. (Sect. 15) How do I do RMI into a different domain?"

*Similar to the proxy answer in a section below; you must tell the program where to find the server. In this case start up the client with this commandline option: -Djava.rmi.server.hostname=hostname.domainname

  1. (Sect. 15) RMI seems to have stopped working for me in JDK 1.1. Why is this?

*The rules for where the client looks for a stub class seem to have changed making it necessary to reset your class path on the client after starting the RMI registry. In particular, it looks like rmic was not updated to the new "don't need $CLASSPATH for current dir" convention as the compiler was. You are best off setting classpath explicitly.
Other sites:
There are several very good sources available from Sun which cover many simple and advanced RMI problems.

  1. (Sect. 15) After a number of RMI client to server connections (55 on my system), subsequent RMI clients trying to connect fail. Why?

*You are hitting the default limit of 64 open file descriptors. Try increasing the limit in your OS.
In addition there is currently a practical RMI connection limit imposed by the scalability of the VM and the performance of object serialization. This is addressed in JDK 1.2. The actual number of active clients you will be able to support will depend on the workload mix you have (i.e. the number of clients, how often they talk to the server, and how much work must be done per call).

  1. (Sect. 15) I want to use JDK 1.2 at one end of my RMI system, and JDK 1.1 at the other end.

*You're getting an error message about version compatability, right? The RMI Compiler has a -v1.1 option for generating 1.1 compatible stubs and skeletons. It should work with that .

  1. (Sect. 15) I'm using RMI on Win95, and the Naming.lookup() call is taking a long time, even for localhost. How do I fix it?

*(See also the first answer in next section below, and note that this Windows workaround has never worked for some people). Try adding a definition for the machine in your "hosts" file. Typically, this file will be named c:\windows\hosts (if it doesn't exist, there should be a file called c:\windows\hosts.sam). The hosts file is searched by your TCP/IP stack before it resorts to DNS, so adding an entry in this file can speed up your lookups considerably. The hosts file is used to map IP addresses to symbolic addresses. To enter the name "localhost" with address 127.0.0.1 (the IP loopback address), enter the following line in your hosts file. 127.0.0.1 localhost

Windows Networking

  1. (Sect. 15) Why does < Microsoft Windows RMI/my java debugger/IDE/other> hang for a couple of minutes if my PC is not dialed up to the Internet?

*The Java language has networking support built in. When the program starts the Winsock DLL automatically gets loaded. The first thing this does is to try to resolve the fully qualified domain name for your machine under the name "localhost". If your system doesn't have this name mapped, it will try to query a nameserver on the internet, which is typically (on a PC) your dialup ISP. So it either prompts you to connect to the ISP, or waits till the attempt times out.

Some people say you can avoid the Win95 problem by giving your system another way to resolve DNS names. This tip has never worked for me. Edit the hosts file for your system so that localhost and the full domain name are both mentioned. On Windows 95 systems the hosts file is: %windir%\HOSTS (for example, C:\WINDOWS\HOSTS). On Windows NT systems the hosts file is: %windir%\System32\DRIVERS\ETC\HOSTS (for example, C:\WINNT\System32\DRIVERS\ETC\HOSTS).
One gotcha under Win95 is that if the last entry in the hosts file is not concluded with a carriage-return/line-feed then the hosts file will not be read at all. So if my system is called goober.best.com change the hosts file from

 

        127.0.0.1 localhost

    

to

 

        127.0.0.1 goober.best.com localhost

    

Showing more of the file:

 

     # Hosts file

     127.0.0.1       localhost

     129.146.77.177  goober

     

Another alternative is to dial up with a PPP connection to your ISP whenever you want to run networking programs.

Fundamentally the experience of some people has been that networking is not completely satisfactory on Windows95 using Winsock 1.1, and has intermittent unexplained failures. You could try downloading Winsock 2.0. To get Winsock 2.0, you need to drag in all the other junk from Microsoft Windows Sockets 2.0 Software Development Kit. This free software can be downloaded from the following addresses: http://www.microsoft.com/win32dev/netwrk/winsock2/ws295sdk.html or ftp://ftp.microsoft.com/bussys/WinSock/winsock2/

The patches needed to improve Win95 networking are already in Win98.

Other Networking Issues

  1. (Sect. 15) If I call the InetAddress.getByName() method with an IP-address-string argument, like "192.168.0.1", get an UnknownHostException on some platforms, but not others. Code like

Socket sock = new Socket("155.152.5.1", 23);

triggers the exception. Why?

*This is a platform difference that arises out of different semantics in the underlying network libraries, and is [said to be, but subject to confirmation] fixed in JDK 1.1. On Solaris and Windows NT, the IP address string only works for IP addresses that have an associated hostname. On Linux and Windows 95, the IP address string works in all cases.
When InetAddress is instantiated with an IP address, a reverse DNS lookup is done. If the IP address is not associated with a valid hostname, the instantiation will fail. This is part of anti DNS-spoofing, and in JDK 1.1 works because the reverse lookup will not occur until the hostname is asked for. So in JDK 1.1,

 

        InetAddress in = InetAddress.getByName("155.152.5.1");

    

[Note: this info is still to be confirmed. Net gurus?]
Other sites:

Microsoft has several network-related patches at its site http://www.microsoft.com/

  1. (Sect. 15) I want to pass a class file to willing recipients who are using my applet. Any ideas how?

*You could use a trick: put your .class file(s) in a .zip archive and use showDocument() on the URL. A person accessing this will get a dialog box put up asking them about saving the file to their local hard disk.
Other sites:

You can see this in action and try it out yourself at:
http://www.best.com/~rmlynch/saveit.html

  1. (Sect. 15) How do I get a URLConnection to work through proxy firewalls? I.e. How do you get your application to do its web accesses through a proxy?

*This is typically needed for any net access to another domain. Tell the run time system what you are trying to do, by using these commandline arguments when you start the program.

 

java -DproxySet=true -DproxyHost=SOMEHOST -DproxyPort=SOMENUM  classname

Note proxyPort is optional and it defaults to 80. Without this, you will see an exception like java.net.UnknownHostException or java.net.NoRouteToHostException

The proxy settings work for java.net.URLConnection, but apparently not for java.net.Sockets. Update! The proxyHost and proxyPort systems properties (from 1.0.2) are deprecated, you should use http.proxyHost and http.proxyPort. They are for HTTP proxies only. If you are using java.net.Socket you are not using the URL classes, and cannot get the proxy behavior.

Netscape's and IE's JVMs (at least in versions 4.x+) take the proxy settings for applets from the browser's proxy configuration. You can also do URL proxies in applications (not applets) with the following code

 

    // set up to use proxy

    System.getProperties().put("proxySet", "true");

    System.getProperties().put("proxyHost", "myproxy.server.name");

    System.getProperties().put("proxyPort", "80");

     

But how do I know the name of the proxy server?
This code just tells you how you can get a URL connection to the outside. Since it is your proxy server, you are expected to know the name of it. There isn't any code that you can write that will allow arbitrary URL connections to be initiated from outside the firewall. Think about it! If there were, the firewall would not be doing its job.

Also note there are corresponding socksProxyPort and socksProxyHost for when socks is used instead of proxy. The default socks port is 1080.

  1. (Sect. 15) What is "swizzle", as in "Swizzle this object?"

*It means serialize. To swizzle an object is to recursively serialize or flatten composed objects.

  1. (Sect. 15) I have been using the Serializing capabilities in 1.1 to save some objects to disk. I added a new field to one of my objects that get serialized and now deserializing my old data no longer works. I get this exception:

13. 

14.java.io.InvalidClassException: MacroData; Local class not compatible

 

*You need to add a declaration such as

 

    static final long serialVersionUID = 4021215565287364875L;

     

in the modified class. The actual value of this long is supplied by the "serialver" utilitity suppied with the JDK. Any versions of a class other than the first version require this static to be defined in the class. This is how versioning is achieved.

  1. (Sect. 15) My socket code looks good, but is broken!

*When using sockets you typically open both inward and outward streams. A TCP connection is full duplex, but either the send or receive side may be closed independently. By default, the remote end will take the close as indicating that the connection has simply been closed, and will close its end as well. Check whether this is happening for you, by adding the matched pair. Use tcpdump to check this.

  1. (Sect. 15) How do I map between IP address and hostname?

*In Java 1.1 (earlier releases were buggy) use:

 

    String host = InetAddress.getByName("211.10.2.119").getHostName();

     
  1. (Sect. 15) How do I embed an anchor in a URL? Just putting it as part of the string in the constructor doesn't work.

*Like this:

 

    URL url = new URL("http://www.my_domain.com/my_page.html");

    URL anchor = new URL(url, "#section2");

    this.getAppletContext().showDocument(anchor);

     
  1. (Sect. 15) How do I POST to a CGI script from an applet?

*POST passes the form data to the next page as part of the HTTP headers, while GET sends the data appended to the URL as a querystring. in the manner of http://www.someurl.com/page.htm?varname=value. POST and GET are different ways of transmitting form data to a server-side application. GET is limited to a small amount of text data that can be appended to the address. POST handles larger amounts of text and binary data and does not show up in the address URL.

Why have two access methods if the only difference is in syntax? The real difference is that GET is "idempotent", meaning that you can call it again and again with absolutely no side-effects for the retrieval of the page. If you do GET on the same page twice, the page may legally be sent to you from your browser cache, a proxy cache, or the webserver itself.

If you do a POST the browser knows the page must always be retrieved by going through all the layers to the server and extracting the data again. If it is a webpage that is being fetched this doesn't matter, but if you're calling a script (CGI, servlet, or similar) then the difference is huge. If the script has side-effects that should be done on each access of the webpage (such as access control, or making the user pay something) you will definitely want to invoke the script each time it is called. See http://www.rfc-editor.org/rfc.html for RFC 1945 (HTTP/1.0) or RFC 2068 (HTTP/1.1) to get the absolute formal meanings of the difference between GET and POST.

When you do a GET, since the data is actually added onto the end of the URL string, the user can actually bookmark it, and submit the same info later by going to the bookmarked site. This is why search engines often use GET.

Note that (in Java) POST is more troublesome than it might seem at first, and that GET is preferred. For an untrusted applet, the CGI script can only be on the server that served the applet. POSTing to the server involves sending key/value pairs, not just a message. Also values must be encoded. To send "words to the server" you might try:

 

StringBuffer sb = new StringBuffer();

String str="words to the server";

 

sb.append("message=");

sb.append(java.net.URLEncoder.encode(str));

URLConnection cn = url.openConnection();

 

// set properties

cn.setDoOutput(true);

cn.setUseCaches(false);

cn.setAllowUserInteraction(false);

cn.setRequestProperty("content-type","application/x-www-form-urlencoded");

 

// send parameters

PrintWriter out = new PrintWriter(cn.getOutputStream());

out.print(sb.toString());

out.close();

 

// read stuff

 

BufferedReader in = new BufferedReader(

                      new InputStreamReader(

                        cn.getInputStream()));

 

sb = new StringBuffer();

String inputLine;

 

while ((inputLine = in.readLine()) != null){

    sb.append(inputLine);

    sb.append("\n");

 

}

in.close();

    

Note, if you request a URL via the URLConnection/HttpURLConnection, the server sets the content type, and your applet can use URLConnection.getContentType() to get the type. Alternatively, use setRequestProperty to set it, like this:

 

    url = new URL(cgiUrl);

    urlc = url.openConnection();

    urlc.setRequestProperty(

                   "Content-type",

                   "application/x-www-form-urlencoded");

    

Other sites:

There's a pretty good explanation at http://www.javaworld.com/javaworld/javatips/jw-javatip41.html


See also the Marty Hall book Core Web Programming (Prentice Hall ISBN: 0-13-625666-X). It has comprehensive coverage of writing Java technology-based programs that interface to CGI scripts. Better still, use servlets, write everything in the Java programming language, and discard your CGI code.

  1. (Sect. 15) How can I write CGI programs in the Java programing language?

*CGI (the Common Gateway Interface for web servers) is an API for writing programs that use the web as its user interface. By far, the most popular language for this task is Perl, because of its powerful text handling capabilities, and excellent resources available for making the jobs of CGI programmers easier. CGI programs can be written in any language, including Java.
Unfortunately, the interface between the web server and the CGI program uses environment variables extensively. Use of environment variables has always been deprecated in Java programming langauge, because of portability issues (not all systems have environment variables). The way to get around this is to write a "wrapper" for the Java program in a language that supports environment variables, and can then invoke the Java technology-enabled program with the appropriate environment data passed in as Java properties.
Because the Java runtime environment is not a lightweight process, it might take a moment for the CGI program to get started before anything happens. This is particularly true on operating systems, like NT, that have a large overhead to spawning new processes.
In preference to using Java for CGI on the server, you might consider using the Java servlet API in Netscape's Enterprise Server. This allows you to develop server-side programs without suffering the same performance restrictions and other limitations of the CGI API.
Other sites:
See http://search.netscape.com/comprod/server_central/ query/eval_guide/enterprise/advantage.html for more details.

  1. (Sect. 15) How can I write the "ping" program?

*You can't do it directly. Quoting from the Java Networking FAQ,

Ping requires ICMP packets. These packets can only be created via a socket of the SOCK_RAW type. Currently, Java only allows SOCK_STREAM (TCP) and SOCK_DGRAM (UDP) sockets. It seems unlikely that this will be added very soon, since many Unix versions only allow SOCK_RAW sockets to be created by root, and winsock does not address ICMP packets (win32 includes an unsupported and undocumented ICMP.DLL).

You could write a program that handshakes with a remote system, to simulate ping, or you could use native code for the raw socket. Other sites:

You can find the Java Networking FAQ at http://www.io.com/~maus/JavaNetworkingFAQ.html

There is an additional Java Networking FAQ (which is being modified and reposted regularly) at http://www.davidreilly.com/java/java_network_programming/

  1. (Sect. 15) Why, when I make a call to DatagramPacket.getlength() does it returns the wrong size?

*You are probably reusing a Datagram packet, and it has no way to grow its buffer if a longer packet comes in. Take care of it by calling setLength(max) before reuse.

Failing to do this is a very common mistake.

  1. (Sect. 15) Why do my networking programs freeze on the Mac?

*You shouldn't println to a socket. This is the subject of Apple Technical Note 1157 at http://developer.apple.com/technotes/tn/tn1157.html
The problem is that many socket protocols expect CR+LF to terminate a string, but println delivers a platform-specific EOL mark. On the Mac, it is just CR. Therefore the server hangs waiting for the Mac to send a LF. It never does. But the program works fine on platforms that send CR+LF.

  1. (Sect. 15) How do I "timeout" a socket read, as the "select" function in Unix does?

*There are two timeouts at issue here.
Use the ServerSocket.setSoTimeout(int millis) for timing out your 'accept()' calls.

For a select() like mechanism, you can poll InputStreams of your connections for available() > 0

URLConnection doesn't have a method for this, but you can do it by using multiple threads. Create a timer thread that would just track time and close the connection after your specified timeout period. Check the URLConnection to see if it's got any data flowing through it (calling URLConnection.connected() is probably a sufficient test). The URLConnection should be in a separate thread.


16. Security

  1. (Sect. 16) What is a "trusted applet"?

*JDK 1.1 introduced the notion of a "trusted applet" which is one that has been cryptographically signed to guarantee its origin and make it tamper-resistant. Trusted applets can be granted more system access privileges than untrusted applets.
You preconfigure your browser with a list of whose X.509 certificate you trust, and then applets arrive with X.509's attesting to their keys. It's easier than it sounds.

  1. (Sect. 16) What is the story with Java and viruses? What is the blackwidow virus?

*The technology was designed with security in mind. The security features make it very difficult, probably impossible, to attach a virus (self-copying code) to a Java applet. There has never been a Java virus carried from system to system by applets.
There has been mention of a "Java virus" called "BlackWidow" in the media (it was mentioned in Unigram in late 1996, and obliquely on the RISKS newsletter in February 1997). A request to the editor of Unigram for more information brought the answer that there was no more information, it was just a report of a rumor. As far as is known, this story exists only as rumors reported on by the press. There is no actual Java virus or blackwidow virus (there was a legitimate commercial product of that name, since renamed).
In spring 1998 there were press reports of a "Java applet" called White Ghost. It turns out that it relies on security flaws in ActiveX, and the only susceptible systems are Microsoft's Active Desktop. If anyone has a URL for a copy of this code, and an analysis of it, please contact the FAQ author.

In August 1998, Symantec had some information about a Java program (application) that could append itself to some other Java program. They termed it "Strange Brew". That is just normal file processing, no different to a program written in C, C++, Fortran, COBOL, etc. What makes PC viruses dangerous is when they have a hidden means of travelling between places, such as being attached to code that is automatically executed, like boot sector code, or Word macro initialization files. No one has yet produced a virus that does this in Java.

In March 1999, reports surfaced of a virus called BeanHive. Again this was not Java-related, but relied on the browser user explicitly accepting an unknown certificate as trusted when prompted. If the user allowed that, then any code from that source will be uploaded and run without further input from the user. Don't remove security for untrusted code simply because it asks for it, is the lesson here.
If anyone has more concrete information about a virus that can attack an applet (again, this is thought to be impossible), please contact the FAQ author.

  1. (Sect. 16) Why do I get the warning string "Unsigned Java Applet Window" at the bottom of popup windows in my applets?

*This is a security feature, to make certain that users can always tell that a window asking for their password and credit card details (or whatever) is from an applet. There should be no way for an untrusted applet to work around this message.
Also in the FAQ:
See also the answer to Q12.7.

  1. (Sect. 16) Where can I find information on signing applets?

*Please take a look at the "Code Signing for Java Applets" page at http://www.suitable.com/Doc_CodeSigning.shtml. The page explains how to sign your Java applet so that it can be used in both Navigator/Communicator and Internet Explorer.

  1. (Sect. 16) Where can I find crypto libraries?

*Cryptographic libraries are not part of the release because US Government policy classifies strong cryptography under the same rules as munitions. Its export is regulated under the International Traffic in Arms Regulations. Many people regard this as a Kafka-esque (and futile) attempt to stem the use of cryptography inside the US.
Other sites:

  1. (Sect. 16) How do I find out what these terms mean?

*Read Bruce Schneier's excellent book "Applied Cryptography 2nd Ed." for more info on what these terms mean. Read David Kahn's excellent (and exhaustive) book "The Codebreakers" for more info on the history and background of encryption.

  1. (Sect. 16) Where is Javasoft's Security FAQ?

*Javasoft's security FAQ can be found at:
http://java.sun.com/sfaq/index.html
Other sites:

http://java.sun.com/products/jdk/1.1/docs/guide/security/

  1. (Sect. 16) Where is that online book on Java Security?

*Gary McGraw and Ed Felten's book Securing Java can be found on the web at
http://www.securingjava.com/

  1. (Sect. 16) How can I accept a password from the console without echo?

*When you want to pick up a password from the console, you don't want to have the characters echoed as the user types them.

There is no way to accomplish this in Java using console I/O. You have an easy approach and a hard approach. The easy approach is to use the AWT (Textfield) or Swing (JPasswordField). The harder approach is to write native code to disable and enable echoing to the console.


17. For C and C++ Afficionados

  1. (Sect. 17) How do I translate C/C++ into Java programming langauge or vice-versa?

*In general it is not simple to translate C/C++ into Java programming language, as Java lacks the arbitrary pointer arithmetic of those languages. If your C code does not use pointer arithmetic, automatic translation gets a lot simpler. Try these URLs:

http://www.ist.co.uk (search for X-Designer 4.6: Java edition).
http://members.aol.com/laffra/c2j.html
http://www.ilog.com/

Going the other way there are currently three freely-available tools to translate Java programming language into C. It seems that these have been done for hacking value, rather than practical purposes.

    • j2c from Japan,

http://www.webcity.co.jp/info/andoh/java/j2c.html

    • Toba from the Sumatra research project, translates 1.0.2 .class files into .c source code

http://www.cs.arizona.edu/sumatra/toba

    • JCC from Nik Shaylor.

http://www.geocities.com/CapeCanaveral/Hangar/4040/

None of them support the AWT yet, and both j2c and JCC have additional restrictions.

There are several products to convert Visual Basic to Java. Details at

http://www.greymatter.co.uk/gmWEB/nodes/NODE06C0.HTM
http://www.blackdirt.com and
http://www.javadelphi.com (also a Delphi-to-Java source converter) and
http://www.tvobjects.com

There's a product to translate COBOL source to Java source, see
http://www.Synkronix.com/

This program dumps info about the class file:

http://www.professionals.com/~cmcmanis/java/dump/index.html

Chuck McManis was one of Sun's original Java implementors.

  1. (Sect. 17) How are finalizers different from C++ destructors?

*Java programming language objects are not explicitly deleted and do not have destructors. Instead they are implicitly garbage collected when the JVM realizes your program can no longer access them. This technology is not based on reference counting and will cope with circular references.

Every object has a routine called finalize() which will be called before the object is collected. This is the nearest equivalent to C++'s destructor. However, it is not a good idea to rely on finalization for the timely freeing of resources. This is because garbage collection and hence finalization may be arbitrarily delayed, and may never happen at all if the program terminates before it runs out of memory. You should instead provide your objects with methods similar to Graphics.dispose() to free resources, and call the dispose() method explicitly when you have finished using them - typically within the "finally" clause of a "try/catch" block. You may then call your dispose() method from within your finalize() method as a last-ditch attempt to free the resource if someone forgets.

Alas, all this means the C++ idiom of "object construction is resource aquisition" does not translate well to the Java programming language. However, note that 90% of destructors in C++ are there to free memory, and the GC means you don't need to do that. As well as fixing an important source of bugs, the GC is essential to Java's security model; without it you could forge object references by preserving the reference after the object has been deleted.

If your program appears to be crashing due to running out of some system resource (like File, Window or Graphics handles), it probably because the system is running out of handles before it has run out of memory. Check that you have called the dispose() method (or equivalent) on every object that uses system resources. You can help the GC a little bit more by explicitly NULLing out references that you've finished with.

  1. (Sect. 17) What's the equivalent of sizeof()?

*There isn't one. sizeof() in C and C++ is used in three main places:

1.      To check on the size of a primitive type. In Java, the sizes of primitive types are fixed in the language specification (a short is _always_ 16 bits; an int is _always_ 32 bits, etc), so this is no longer necessary.

2.      In memory allocation (i.e. malloc (32 * (sizeof(int));) In Java you always allocate a specific type of object, rather than a block of raw memory that you will fill as you like. The system always knows the size of the kind of objects you are allocating. So sizeof is not needed.

3.      In pointer arithmetic (i.e. p += sizeof (int)) Pointer arithmetic of this type is not allowed in Java, so this isn't necessary, either.

For all these reasons, there is no need for a Java sizeof() operator. Some people have suggested that you can find out the size of an object by having the object serialize itself to a ByteArrayOutputStream, and looking at the bytearray.length.

That won't work because a lot of additional data is written when an object is serialized. The additional data includes a description of the class, any objects referenced by the serialized object, null references (written as a single byte), etc. If you write another instance of the same class, the amount of data written can differ dramatically. And if you serialize the same object again, it isn't written at all -- even if its data fields have changed! Instead, a one byte token and a four byte "sequence number" that refer to the first writing are output. Using Object Serialization to determine the size of an object does not (except by coincidence) give the right answer.

  1. (Sect. 17) Does Java have the equivalent of "const" arguments in C and C++?

*Java 1.1 adds the ability to use the "final" keyword to make arguments constant. When used to qualify a reference type, however, this keyword indicates that the reference is constant, not that the object or array referred to is constant. For example, the following Java code:

void foo(final MyClass c, final int a[]) {
    c.field = 7; // allowed
    a[0] = 7; // allowed
    c = new MyClass(); // final means this is NOT allowed
    a = new int[13]; // final means this is NOT allowed
}

is roughly equivalent to the following C/C++ code:

void foo(MyClass * const c, int * const a) {
    c->field = 7; // allowed
    a[0] = 7; // allowed
    c = new MyClass(); // const means this is NOT allowed
    a = new int[13]; // const means this is NOT allowed
}

Java does not have any equivalent to the following C/C++ function declarations:

void foo(const MyClass *c); // a pointer to a const class
void foo(const int *a); // a pointer to a const int
void foo(const int a[]); // a pointer to an array of const ints
  1. (Sect. 17) Are there any hacks around this?

*Certainly! There are always hacks around stuff. One way of enforcing constant values is to have two interfaces, a constant one and a non-constant one, e.g.

public interface ConstFoo {
   int getValue();
}
 

public interface Foo extends ConstFoo {
    int getValue();
    void setValue(int i);
}

Then when you want to receive a parameter that cannot be modified you have:

void noChange(ConstFoo foo);
            

For a parameter that can be modified

void change(Foo foo);
            
  1. (Sect. 17) How can I write C/C++ style assertions?

*The two classes shown below provide an assertion facility. Set Assert.enabled to true to enable the assertions, and to false to disable assertions in production code. The AssertionException is not meant to be caught--instead, let it print a trace. Since the exception is not meant to be caught, we just extend Error instead of RuntimeException. As with RuntimeException, a method does not need to declare that it throws Error. In addition programmers are less likely to write "catch(Error) ..." than "catch(RuntimeException)".

With a good optimizing compiler there will be no run time overhead for many uses of these assertions when Assert.enabled is set to false. However, if the condition in the assertion may have side effects, the condition code cannot be optimized away. For example, in the assertion

Assert.assert(size() <= maxSize, "Maximum size exceeded");

the call to size() cannot be optimized away unless the compiler can see that the call has no side effects. C and C++ use the preprocessor to guarantee that assertions will never cause overhead in production code. Without a preprocessor, it seems the best we can do in the Java programming language is to write

Assert.assert(Assert.enabled && size() <= maxSize, "Too big");

Alternatively, use

    if (Assert.enabled)
        Assert.assert( size() <= maxSize, "Too big" );

In this case, when Assert.enabled is false, the method call can always be optimized away totally, even if it has side effects. The relevant sections of the JLS are Section 13.4.8, final Fields and Constants and Section 14.19, Unreachable Statements. 13.4.8 requires that primitive constants ("a field that is static, final, and initialized with a compile-time constant expression") be inlined. So everywhere Assert.enabled is refered it is replaced at compile time with its value. Writing:

      if (Assert.enabled) Assert.assert(size() <= maxSize, "Too big");

is exactly the same as writing:

      if (false) Assert.assert(size() <= maxSize, "Too big");

... assuming Assert.enabled is false at compile time. Section 14.19 discusses compiling away such dead code. To sum up: the inlining of the primitive constant is required by the spec. The subsequent optimization of not generating code masked by (what turns into) an "if (false) ..." is not required but is implemented by many existing Java compilers.

public class AssertionException extends Error {
    public AssertionException(String s) {
       super(s);
    }
}
 

public final class Assert {
    public static final boolean enabled = true;
    public static final void assert(boolean b, String s) {
        if (enabled && !b)
            throw new AssertionException(s);
    }
}
  1. (Sect. 17) How do I do stuff like scanf and sscanf in C/C++? And how do I do stuff like sprintf, e.g.

8.    float x = 12345.6789;

9.    printf("%6.3f/n", x);

*You can break a string like "5 loaves 2 fishes" into its parts by using java.util.StringTokenizer. This is the Java programming langauge equivalent of sscanf().

StreamTokenizer does a similar thing on a file or any stream (i.e, what scanf() and fscanf() do in C).

To do formatted character output, create a format string, and then use that to format your binary value, e.g.

import java.text.*;
 

float fi = 1234.56789F;
DecimalFormat mydf = new DecimalFormat( "###0.000" );
mydf.setMinimumIntegerDigits(3);  // for example
System.out.println( mydf.format(fi) );

gives:

1234.567

If you want to see a float print out as "0.0000001" instead of "1E-7", use:

java.text.DecimalFormat myFmt = new
    java.text.DecimalFormat("#,###,###,###.############");
System.out.println(myFmt.format(myFloat));

There are lots of different characters you can feed to the DecimalFormat constructor, not just "0" and "#". See $JAVAHOME/src/java/text/DecimalFormat.java source for details.

The always excellent Acme site has an sprintf() package written in Java See http://www.acme.com.

  1. (Sect. 17) What is the equivalent of C++'s "friend"?

*The keyword "friend" in C++ is a hack to allow a piece of code to access the private member declarations of another class. In the Java programming language, you would do this by labelling, not the friend, but the private members. Instead of making them private, make them either protected or package (no keyword) or public.

The four different protection levels are: private, package, protected, and public.

    • private members can only be accessed by the containing class and internal classes.

    • package (specified by omitting other keywords) is the default level of protection; members are accessible from any class within the package of the containing class.

    • protected is package-level-access plus access to sub-classes of the containing class. So "protected" is less protected than the default.

    • public fields in public classes are accessible from all classes.

  1. (Sect. 17) Does anything like the C++ Standard Template Library exist?

*Yes, only it's better and simpler to use. It's called the Java Generic Library. This library (JGL) is freely downloadable from http://www.objectspace.com/

It includes about a dozen nice data structures (including sets and bags) and algorithms like unions, searching, and sorting.

It has over 100,000 users and 11 OEM distributors. [Some Java vendors are bundling it with their next release]

  1. (Sect. 17) What happens to post-increment when an exception is thrown?

*If you have the code:

    array[i++] = foo();

and foo() throws an exception, i will be incremented anyway. This can cause problems if sometimes foo() throws an exception and you don't want i incremented in cases when it does.

This is a consequence of JLS 15.25.1 and 15.6.1 "the left-hand operand of a binary operator appears to be fully evaluated before any part of the right-hand operand is evaluated." (assignment is taken as a binary operator). Note that this is not how C++ behaves.

 

JAVA Index

For more details contact the webmaster