Why Java can be used for games
by Jacob Marner
Originally written June 15th, 2000. Last edited August 16th, 2001.
(Note: If you have read this article before you will see that the conclusions has changed and old outdated links are removed. This is because Java technology has improved since the article originally was written and many of things no longer was true. This article view of Java is based on the use of Sun's JDK 1.3.1.)
Often when I tell people that I am writing a game in Java they sniff and say something like "You must be kidding; Java is too slow", "Real men don't program Java", or "Java is not a real programming language". This opinion is very often caused by the fact that those people only have tried to run a Java applet in their browser and have seen that it runs very slowly.
In the following I will clear up some common misconceptions and make sure that you understand that Java really is useful for game programming and C++ is not the only choice. I am not saying that C++ is bad or anything; just that using Java for a gaming project can be a real benefit that should not be missed.
This articles is generally targeted at C++ programmers that are wondering or skeptical about whether Java can be used for professional games.
To understand this article you need some general programming experience and at least a basic knowledge of C++. Some basic knowledge of Java is also required, but reading a small tutorial somewhere should be enough.
This article assumes that the goal is to write high performance games similar to those boxed ones being released commercially for sale in stores. The target platforms we are interested in are the PC and consoles.
Also, we will not compare Java with other high level languages such C# or Visual Basic .NET, but merely consider Java when compared with the de facto game development language of today: C++.
Start by opening your mind
If you are a C++ programmer then you are probably very tired of all those Java evangelists back in 1995 claiming that Java is superior is every regard and that 100% pure Java is the best thing there is. Chances are that you tried it back then, saw how awfully it ran, and the dismissed it as a web development toy.
Fortunately most the hype surrounding Java has since then died out and the compilers and virtual machines has improved significantly.
We will now try to figure out what Java really is useful for.
I have heard the same hyped arguments and originally dispelled the use of Java as anything but a web applet language because of the many promises that was clearly not true. After all, if something needs justification then it is usually not worth the effort - usually.
And if you do a quick web search on "Java games" you get nothing but small crappy applets that nobody cares about. These are actually making the reputation of Java gaming worse, because you and many other people get the impression that that is the only thing Java can do.
However, all this does not means that Java is useless for all gaming purposes. In this article I will argue that Java does in fact has it uses within gaming and can help you build better games with less effort.
The advantages of using Java
I have heard other people say that they do not want to switch to Java from C++ because there is not benefit in doing so, especially since we by using native code loose the main Java benefit of cross-platform programming. That is very wrong.
Java and C++ look alike on purpose to make the transition easier to make for C++ programmers but this is only on the surface. Many things are easier in Java than in C++. A few is mentioned below. If you disagree on some of these points please read this in-depth discussion.
Some people complain that Java is actually missing some of the features that they need. Most of them you are actually better left without:
You may think that the advantages of Java may seem very few and if you are very productive in C++ you may think that you can live without them. I thought so myself before changing to Java in 1999. I was surprised how much faster development in Java really is. You really have to try Java before judging it.
IDC have made a large study that shows that Java applications written in 100% pure Java yield a 25% overall time/cost saving and 40% in the coding phase. The reduction in costs of code maintenance was around 30%. I am not sure exactly how big the reduction is for games, but it is a fact that Java increases your productiveness both by increasing code writing speed but also by reducing the number of bugs. This assertion is based both on my personal experience with both Java and C++ but also on a number of articles/studies.
According to Jeff Kesselman (a Sun Java engineer and ex-game developer) most Java game developers report a productivity gain of a factor of 2 to 4.
Myth: Java is slow!
No this is not true, except in some cases and it is these cases that has given Java a reputation for being slow.
The cases when Java is slow
It is very true that interpreted Java applets in modern browsers are very slow. Often a factor of 10 or more than C++ programs. You have probably experienced this first hand by playing some small games in on some web page through your browser. In this environment it is true that commercial-class games will never see the light of day.
Browsers use an old version of the Java technology that is very slow compared to what is possible today. The last couple of years major improvements has been gained in the speed of Java that makes almost as fast as C++ code. Today's interpreters actually internally compile the code to machine code and even use information gained at run-time to do run-time optimizations on the code.
You may also have run your own tests using Microsoft J++. Judging Java based on that is not fair, since that is one of the slowest versions you can get of Java. (We know how Microsoft and Sun feel about each other, don't we?)
You may have tried Java applications outside your browser and found them slow too. This is because the Java Windows system (mainly Swing) is cross platform and therefore draw all the windows controls manually. This is very slow. However, since games usually does not contain a lot of windows and other widgets this is really not a problem for games.
In all other cases Java is fast!
Modern Java programs are not slow (here we are talking about Java virtual machines 1.3 or later). They more or less run the same speed as C++ programs. However this assumes that they are well-written. Java programs must be written using a clean object oriented approach, otherwise they will suffer.
A rough estimate would say that current typical Java games rare approximately a factor of 1.5 to 2 slower than what is possible with C++ depending on the application - I have made no formal tests so this estimation is based on the performance I see in games.
This is due to either of two reasons:
For some actual bench marks that compares C and Java and than supports this see Runtime Vs Static Compilation - Performance Comparison. This benchmark is a year old. As you can see the result vary a lot depending on the application but overall Java does not place bad.
People often say that Java cannot compete with hand optimized C++ code. This is also wrong. But of course this also assumes that the Java code is also hand optimized. As with any language Java has its pros and cons and as any good programmer you should know what is fast and what isn't.
A common misconception is that Java does not run compiled code. Although it reads byte code it also compiles and optimizes that code based on run-time information and the architecture it is running on. No C++ can do that! This means that, although it is not the case today, that Java virtual machines very well may get more efficient than C++ code. If you meet somebody telling you otherwise they probably don't know about the recent advances in technology making all this possible.
If you want to know about all the cool stuff the Java virtual machine is capable of I recommend reading The Java Hotspot Performance Engine architecture white paper.
But why is most of the Java applications I see so slow then?
And remember, if somebody shows you a slow Java program then it is likely one of the following things are happening:
The first case, that the program is poorly written, happens more often than you think. Although I cannot back the following up I believe that it has to do with:
In conclusion the main reason that Java programs are slow is that developers don't know how to use it properly. Writing efficient programs can be bit tricky especially since many of the optimization "truths" you know from C++ no longer is true in Java due to adaptive optimizer. That said, during optimization in Java is generally much cleaner than in C++ that usually get very messy when you optimize heavily. Java is designed to work best with well-designed clean object oriented program.
Static native code compilers
Some companies has created native code compilers for Java, i.e. compilers that convert Java source code directly to a static machine code executable just like C++ compilers do. They simply consider Java to be yet another language that you can program in. Native code compilers are also called static compilers.
When running programs compiled with a native code compiler the program is not interpreted and does not need a Java run-time environment (JRE), although some run-time DLLs may be needed. (Note that some native code compilers require the final executable to use Sun's Java DLLs. This this case, due to JRE license restrictions, the full JRE must be be distributed with your application even if it is not used.) Native code compilers create regular *.exe files and even *.dll files.
Several good native code compilers exist out there. These include:
My favorite is Excelsior Jet. A time-limited evaluation version is available for download from Excelsior. If you intend on maintaining a zero-budget then the only option is GCJ, but that is a little more complicated to use.
And just to set something straight:. The following Java compilers/IDEs do NOT include a native code compiler. Some such as Webgain Visual Cafe claim that they do, but they merely include wrappers that but interpreted code into and exe file.
Most of the mentioned Java native code compilers, support everything that you are used to from Java including all the standard libraries, AWT, Swing and all the standard extensions (such as Java3D). You can even import byte code supplied by 3rd party developers and compile them directly to native code. The only thing that you cannot make is native code applets, but this would not make much sense anyway.
Java has the advantage of being a simple language, which means that optimization has greater potential than in C++, which is a fairly complex language with many special cases that makes optimization hard to do, so you can expect to see even better Java compilers in the future - possibly generating faster code than those C++ compilers we know today.
For the record, it should be noted that native compilation does not come without a price. If you use native compilation you loose some Java features:
But is native code compilers faster than using a hotspot virtual machine? Often. Try it out for your application. However, in the long run hot spot virtual machines are going to win because they optimize the game automatically to take care of the architecture it is running on. If, for instance, a static compiler compiled it for a Pentium 2 and it is run on a Pentium 3 performance will suffer. This will not happen with a hotspot virtual machine.
Some Java evangelists will claim that Java virtual machines are always just as fast as native code but this is simply not true today. If you disagree on this I recommend reading The Java Performance Report (August 2001 Edition) which is an independent bench mark comparing the compilers. This report also explains some of the benefits of native code compilers. I do admit, however, that the gap between native code compilers and regular virtual machines has closed much in the last years and the reason to use them are smaller than before.
Myth: Garbage collection
I often hear people say that they dislike the idea of a garbage collector that may kick in at any time and pause the system for a few seconds. That would admittedly be a bad thing in many cases, because everything would hang in the meantime. Not a good thing in a high-performance real-time game. Fortunately, due to recent improvements in garbage collector technology they is nothing to be afraid of since the risk of that happening is very low.
Garbage collection is not inherently slower at execution time than manual deallocation. It is actually often faster since you (depending on the schemes used) more easily can avoid memory defragmentation on the heap or often can reduce the overhead of deallocating object. Remember; when you use a garbage collector then the system does not have to use time to deallocate the object when you are done as it has to in C++; the cleaning methods only use time with the objects that you keep; if you have a lot of small objects that are temporary deallocation takes zero time for those!
Be warned there is several pages about garbage collection on the net. These claim that garbage collection is slow. This is usually because they have evaluated slow schemes. Ground research in the last few years a found results to make this untrue. In fact comparing with the explicit deallocation in C++, garbage collection is much faster. It should be noted, that it also needs to be since Java programs generally do more allocations than C++ programs.
For those of you with some knowledge of garbage collection should know that Java today uses a generational garbage collector with very fast new-space (nursery) combined with a old-space that runs either a mark-compact garbage collector or an incremental garbage collector, depending on options given to the virtual machine at startup.
For more information about garbage collection see Richard Jones' The Garbage Collection Page.
Myth: Java does not support native Windows, DirectX or OpenGL!
Java comes with an interface called JNI (Java Native Interface) that lets Java communicate with external *.dll files and *.obj files. This is actually how the libraries included with Java itself is written. This means that you can call (or be called by) Windows, DirectX or any other C/C++ library absolutely without problems. This also means that if you a changing to Java you can still utilize any library you may have written in C/C++.
Unfortunately, in an effort to be portable, JNI is pretty slow and the use of it should be minimized. So when designing the interface between C++ and Java an effort should be made to avoid calls over the boundary. This can be done by putting code on the C++ side to make the interface more high level. For instance, if you intend to use OpenGL you might be better of writing some high level primitives in C++ in order to bundle calls.
Like all other optimizations this can be postponed until a late state in the project, however it is generally a good idea to access C++ in a high level, i.e. let each JNI call have a large amount of functionality to help reduce the overall number of calls.
Myth: You can't write Java programs for game consoles!
Wrong again. It is true that there are no Java virtual machines available for the Nintendo 64, Sony Playstation or the Sega Dream cast, but because GCJ (the Java GNU compiler) can run on any platform that has a port of gcc and because gcc ports exist for the consoles you can in effect write efficient GCJ programs for consoles.
The main drawback of using GCJ is that it only supports Java 1.1 and support for inner classes are at the time of writing still experimental, but GCJ is getting better all the time so this problem will likely be gone soon.
However things look to be much better around the middle of 2002. Here the first implementation of the Java Game Profile will be ready. This is a standard interface that allows implementing Java platforms to run games in a standardized and portable way, i.e. games will be able to be ported between consoles and other gaming devices very easily.
Myth: Java is slower than C++ because...
Java can't allocate objects on the stack
Yes in the old days a garbage collector was slow but not today. Java uses a so-called generational garbage collector. In short this divides the heap into two sections. One for short-lived objects, called the nursery, and one for long-lived objects. Objects are allocated in the nursery. This is always compacted so allocation of new objects is usually just the matter of moving a pointer in memory. Deallocation occurs when the nursery is full and then only the objects still alive are even touched. So if the program has many small objects which mostly is short-lived temporary ones then deallocation is practically free (it is not completely free since many objects fill the nursery faster). So in practical terms this is often faster than C++. Read more about the garbage collector here The Java Hotspot Performance Engine architecture white paper.
Java program run interpreted
Yes in 1995 and 1996, but not today. Hotspot virtual machines and static native compilers both compile the code to machine code before it is run (JIT compilers did the same, but was just not very efficient).
Hotspot compilers use what is called adaptive optimization. This means that it analysis the code at run-time and compiled and optimizes it then. Since this allows optimization not possible in static compilers these have the potential of get faster than C++ compilers. It should be noted that C++ compilers are unlikely to adopt this technology is C++ is a complex language, which making the creation of such compilers virtually impossible to do.
Java can't do global optimization
Because Java contains support for dynamic class loading this is true using traditional compiler techniques. But hotspot is not traditional. In fact since optimization is done at run-time it can easily do global optimization. If one or more of the classes involved are suddenly changed then the optimization will be redone.
The optimization then uses all the traditional optimization techniques on the result:
More will likely be added in the future. Note also that programs often run faster after having run for some time since more and more code is being optimized while it runs.
Java requires many dynamic casts and virtual method calls
See the above section on Java and global optimization. The optimizer handles both these situations so both dynamic casts and virtual method calls become very cheap, or even free in some cases.
Java has range checking and null pointer checks
See the above section on Java and global optimization. The optimizer handles both these situations so they even some time can be eliminated fully.
There is many people telling my it is slow, so it must be
Usually, people only tried Java at a time it was slow or tried using applets or even Swing applications. This given Java a reputation for being slow that is not correct today. A lot of old articles about Java remain on the Internet that keep this myth alive - those articles are targeted at old versions of Java. They are no longer true.
Myth: No commercial games use Java!
All these arguments is worth nothing if there is no actual proof that it is possible to write high performance games in Java. Below is a list of those I know about.
Also in most development areas Java is gaining heavy ground. For some reason game developers are slow to follow suit. However, game developers was also slow to embrace C++ when that came out, so this is probably no surprise. Read this ZDNet article from 16th August 2001 referring to an IBM survey about what programming languages people use.
One example of Java in games is the highly acclaimed game Vampire - The Masquerade from Nihilistic software. This game uses Java as its s cripting engine (i.e. control code) and has its engine written in C++ and is therefore an example of mixed code. This game runs with very high performance. According to the Gamasutra postmortem of Vampire, Nihilistic Software very satisfied with using java in it (and this was in interpreted Java 1.1 which much slower than what is possible today).
Also noteworthy is the best selling Who wants to be a Millionaire. Here the logic was written in Java and the rest in C++.
Of other commercial games using this scheme (logic in Java) can be mentioned You don't know Jack and Majestic.
On the freeware scene a few games are worth trying. Take a look at Arkanae. It uses the free Java based Opale.Soya 3D engine. This cool freeware game runs better than most C++ games. The engine is written on the C++ side using only the free library gl4Java, a popular and portable OpenGL wrapper for Java. This wrapper uses JNI a lot so it should be possible to increase performance even more. gl4Java is a good example of a library that can be used for games directly.
You should also look at WildTangent. WildTangent is a 3D engine for Java (and other languages) wrapping an improved version of the original Genesis3D engine. It runs very impressively. Note that although it is no apparent from the WildTangent web page, it is actually able to run outside web browsers.
I have myself written a mixed code game engine called Role Maker. It is only supplied with a small demo world, but it scales fine even with Java. This used both JWindows (A Java wrapper for MFC) and 6DX for Java (A Java wrapper for the Eldermage 6DX 3D engine)
On QuakeCon 2001 a company called Fullsail showed a Quake clone, Jamid, they had made. The Quake fans present was generally impressed with the speed which according to the reports from the Con was no slower than similar games in C++. This was written in pure Java using Java3D.
Another one is the on-line game Roboforge. Roboforge uses Java3D to render its graphics.
Other commercial games written in Java include Shadow Watch, ruthless.com, and Tom Clancy's Politika, all from Red Storm Entertainment. Red Storm also tried mixing some of the Java code into their product Rainbow 6, but according to the Postmortem of Rainbow Six this turned out not to be an advantage.
Pure Java in browser applets (slow!)
Although applets are very slow indeed compared to mixed code games, it is still instructive to see what can be achieved with them. A good example is Runescape, which is a 3D Gouraud shaded MMORPG.
Myth: Java is dead and will no longer be improved
Wrong yet again. Sun works very actively on Java and releases dozens of new versions of java related product every month!
Sun states that it is goal for them to make Java as good as possible a gaming platform. Words is of course not enough, but we have already seen a lot of improvements in Java over the last years that make it seem that they are actually keeping their promises and working on it.
As a concrete gaming related example is the Java 3D interface (Java3D). That interface has become much faster over the previous years and are today near competitive to C++-only 3D engines.
At the Game Developers Conference 2001 it was announced in this press release that Sony and Sega among others will collaborate to build a Java gaming API. Sony and Sega are very influential when it comes to games and their presence in the scene promises a bright future for Java gaming. This Java gaming API (called the The Java Game Profile) is being primarily to allow game consoles and other game devices, such as the Gameboy Advance or Arcade machines, to get the software written in Java in a standardized yet fast way.
Sun has launched a web site for Java game development called www.javagaming.org.
Another future improvement to standard Java that has direct benefit to games is the introduction of direct buffers in the JDK 1.4 (currently in beta). Read an introduction and try the demo at JCanyon: Grand Canyon for Java Another improvement in JDK 1.4 is support for full screen mode. Improvements such as these promise to close the gap completely between Java and C++ and make C++ completely unnecessary in Java gaming development.
In more general terms Java virtual machines has been vastly improved over the last few years and it is likely that this will continue.
Recommended development strategy
When starting out a game project with Java the general best approach to take is first to try to build the game in 100% pure Java. This has the added benefit of being cross platform which is good if you later need to port it to, say, a console system or to Macs or Linux.
Also, try out Excelsior Jet or another native code compiler to to see if you gain extra speed on your target platform. You will naturally need a different native code compiler for each platform you target, and for those without such compilers you can just make do without it. Although it is likely to be faster with a static native code compile today this is likely to change in the future so there is no need to buy anything before the end of your development cycle.
In the final stages of your product you can profile it and then figure out if there is some sections that is run very often. Just as people in the C++ world would optimize this code you should try to optimize the Java code to avoid the things in Java that are slow, but that you probably used because it was more convenient. This should only be done as an optimization in heavily used code since it complicates the code and hence reduces productivity.
Also, when you evaluate the speed of your Java code you can expect it to get faster with time even if you don't do anything. It is common knowledge that computers get faster but Java compilers and virtual machines and compilers also get more efficient so you will automatically leverage the benefit of ever more sophisticated optimization techniques as they are released. And this is no empty propaganda. The last few years virtual machines for Java gotten much faster and I just observe that this seems to be going on still.
Common optimization myths about Java
In general Java has been designed such that well-designed object oriented applications are the fastest. There is many articles on the Internet and else where giving various tips about how Java can best be used. These are usually based on old versions of the Java technology or they assume the same techniques apply to modern compilers. Beware of these.
For up to date tips on optimizing Java code in Java I recommend reading Java Platform Performance: Strategies and Tactics by Steve Wilson and Jeff Kesselman.
Beware also of benchmarks comparing various instructions in Java. The relation has changed a lot the last few years, so unless you are looking at benchmarks written made for JDK 1.3 or newer, don't trust them.
Myth: You can speed up allocation using pools
Some optimization articles (even some famous ones) state that one should avoid allocation at all cost and use other techniques, such as pools instead. However, this might actually slow the program down since this will make some of the temporary objects in the nursery become long lived which will slow the garbage collector down.
Myth: Small immutable objects are a sin to use!
Yes, in JDK 1.2 and before. In JDK 1.3 or later it is perfectly fine to make many small object due to the way allocation works. However, if the constructor of the object is slow then object creation is also slow, so it is generally not a good idea to have big constructors for small objects.
Myth: After profiling your code move extensively used code into C++
Although C++ code with some tweaking can get a little faster than what current (1.3.1) hotspot compilers can do, this is usually a bad idea:
However, if speed is extremely essential to you, and you have some heavy weight algorithms that can be separated cleanly from the rest of the code then yes, you might get some performance benefits from JNI, but still on the expense of productivity and portability.
In general there is only 2 reasons for using native (C++) code:
In conclusion, using writing games using pure Java will let you produce at least 25% more without any speed reduction. This is not bad at all!
It is only in rare cases you have to mix with C++:
Generally, it does not pay to "optimize" by putting code in C++.
The time saved this way can be used to add more features, to reduce bug count or even to release the game faster. Today games are often about 2 years underway. If a game is written in Java you could probably cut off maybe up to 4-5 months which would cut production costs and bring the game onto an earlier market, which means that it will sell better.
The only catch is that as a C++ programmer you will have to learn a new way to program and this will take you some time in the first project, but this will quickly caught up by your increased productivity.
As time goes by, productivity tend to mean more and more. You can probably remember the time when nobody wanted to make Windows programs because DOS was in full control of the machine and that was the way to do it. I remember reading an interview with a game developer in those times where it was stated that DOS would always prevail because games needed all the speed they could get. Even further back in time everybody used assembler and didn't like the idea of using C. It was too slow, they said, but then John Carmack came along in 1993 and showed that Doom could be written almost solely in C. That changed the world for game developers. Today no sane developer would use assembler for a full commercial game. In fact on QuakeCon 2001 John Carmack spoke about the importance of high level tools and languages in development today. Java may very well be the de facto language in the future. That John Carmack does consider Java a good language can be documented from this quote concerning the Quake 3 development: "We are still working with significant chunks of an existing code base. If I did want to go off and start fresh, I would likely try doing almost everything in Java." (The article)
Jacob Marner holds a B.Sc. in Computer Science and is a graduate student of that same subject. He studies at the University of Copenhagen, Denmark. He is currently specializing in development of computer games, especially role-playing games. His Master's Thesis is a computer role-playing game authoring system. Visit his site at www.rolemaker.dk. He has taught computer architecture, compiler design, kernel design, networking, C++ and Digital Alpha assembler programming for two years at the university as an assistant teacher. He has written a book in Danish about how to do low-level programming on the Digital Alpha architecture. This book is currently in use at his local university. He can be contacted at firstname.lastname@example.org.
This articles does not come out of limbo. After writing the article I have has comments from C++ programmers, Java programmers, Sun Java engineers, and have had suggestions and flames from multiple forums including those at www.javagaming.org and www.gamedev.net. Thanks. Without your help the article wouldn't be as good as it is today.