Java is great way to make a cross-platform product. But for various reasons, Java may not be the right technology. Here are some technologies that might help.
QT from Nokia is a good cross-platform GUI framework. It is LGPL licensed. It is feature rich and comes with a lot of classes to make cross-platform programming easier. If you are used Java’s Swing, it will be similar. However, if you are used to sub-classing Swing elements, you will be looking for a different way to do things in QT. The heavy lifting of QT classes is private classes with the public classes and methods being more of an API into the private classes. The event model in QT slot/signal based.
WxWidgets is another LGPL GUI framework. I haven’t used it, but others speak highly of it.
Ice from ZeroC is a communications framework. It is not only cross-platform but cross-language. This allows a client program to be written in whatever language that Ice supports and the server can be written in a different language. This flexibility is especially nice for distributed applications. A client program could use a simple scripting language and the server could make use of a more robust compiled language. They use an IDL to create the interfaces for the programs. Implementing the interfaces is quite simple and makes the client-server communication a breeze.
Boost is a collection of high quality cross-platform libraries. They contain a lot of the objects one needs to deal with different operating systems in an abstract manner, like the filesystem. Their smart pointer and threading libraries are useful.
.Net and Mono are another way to go. The same binary can be used for Windows, Linux and MacOSX. However, the user will need to have Mono installed and run the program with Mono.
This is not an exhaustive list, but it should give an idea of the alternatives to Java. These alternatives are not without their drawbacks. You will need to compile a binary(ies) for each target system. Java has the clear advantage in this with its bytecode and virtual machine.