Tuesday, 18 November 2008

Writing OS-independent JAVA code

One of the best things about Java is the fact that it’s applications are OS independent.
This means that you can write application on one OS, and run it on some completely different.

We ought to thank to JVM for this. It is JVM that cares how things should be done on certain OS.

When you say, for example:

new Thread(new Runnable(){public void run(){System.out.println("Hi, I'm thread!");}}).start();

Different OS will create this new Thread , set it’s priority , execute it and do many other things on completely different way, but thanks to JVM Java developers do not have to care about these things...

Another good example is file chooser. For example, windows and Solaris have different file chooser , and if you use it’s APIs to call it your code would look completely different, but in Java you don’t care about it. Code:

JFileChooser jfilechooser = new JFileChooser();
if (jfilechooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION)

will work on windows, and on Linux, and on about any other OS that you can find JVM for it...

But, there is always a "BUT..."!

Yes, with Java and it’s JVM over 90% of your apps will work on any OS that has JVM for it, but there are some rules that you must stick to when developing app that will run on different OSs.

These are mostly trivial things, but enough to make your app not working correctly on a different OS.

These are some of the most common:

-Using "/" or "\" instead of System.getProperty("file.separator"). Different operating systems has different file separators. So, if you don’t know on which OS your app will run on, it is wise that instead of using, for example,

String some_path = ".\\some_file.txt";

you use

String some_path = "." + System.getProperty("file.separator") + "some_file.txt";

-Using absolute, instead of relative path. It is wise to use relative instead of absolute path because different OS have different file paths! For example, "c:\\some_file.txt" doesn’t mean anything on some linux, but "." + System.getProperty("file.separator") + "some_file.txt" , for example, certainly does!

-Using sockets on port < 1023. Be aware that on some operating system ( for example linux ) only special users ( root) can use ports smaller than 1023. It is very wise to use port > 1023 if you can...

-It is wise to use System.getProperty("line.separator") instead of "\n" at the end of the line when writing something to files.

-Using OS-specific command when executing OS commands.
Process process = Runtime.getRuntime().exec(command); can be very convenient , but be aware that different operating systems have different commands!

-Mixing letter case when working with files and folders. This is very common problem. Many developers that use windows just forget that other OS are case-sensitive. So, in linux , if you try to read from file
"." + System.getProperty("file.separator") + "some_file.txt"
and that file is realy a "Some_file.txt" or , for example, "Some_file.TXT" you wan’t be able to read it, and your app will not work correctly...

And the last ( and probably the least ):
-You probably will never create so many threads so that your OS will not be able to process them all, but if you are using some older OS, or create very very large number of threads, different OS will act differently because not all OS have the same limitation for maximum number of active threads at the same time ( native threads, not green threads )

These are just some of the rules you should stick to, if you want your app to really work the same way on different operating systems. No matter how trivial they are, people often forget about it...