Java is a robust language used by big enterprises
Java is a statically typed object orientated language. It belongs to the group of Java Virtual Machine languages:
Java
Kotlin
Scala
Clojure
Groovy
Jython
JRuby
You write your code as text and then using the javac tool you compile your code to platform independent byte code. The same byte code can be run on any operating system as long as the Java Virtual Machine (JVM) is installed on that operating system. The JVM interprets the platform independent byte code and calls the native libraries of the underlying operating system.
The compiler is itself written in Java and the JVM is written in C.
Unlike C, Java has been created with its own garbage collection functionality. This means that the Dev does not need to deallocate memory.
In fact Java provides plug-able Garbage Collectors which manage the clean up of your memory. Some of these garbage collection implementations are pretty smart and can give performance savings over a developer managing their own memory in C (because the design pattern is well designed).
One of the concerns people have is that they think Java cannot be fast as C for it is another layer on top of the JVM which is written itself in C.
However as explained previously, the design pattern used for Garbage Collection can actuall increase performance in deallocating memory. Basically Java can deallocate memory in chunks and thus save on CPU cycles.
Garbage Collection needs to be understood in Java when you are working with low latency systems. Every so often the JVM can pause the running of the application to perform garbage collection. This can be triggered by lack of available memory. i.e. some threshold has been met which triggers the garbage collection. During this pause the garbage collector will look for memory which is no longer referenced and de-allocate it in chunks. This garbage collection eats CPU cycles. If there is a lot of memory allocated to the JVM this can take some time. It can even take several seconds. It is called a "Stop the World Pause".
Stop the World Garbage Collection Pauses are not good for low latency systems. To reduce this time you can configure your JVM to have a max memory size. Instead of expanding automatically to ever bigger memory it will crash out if the max memory limit is met. This ensures that you cannot have a long stop the world pause.
So in low latency trading systems written in Java they will design their system so that have lots of interconnected JVMs running instead of a single JVM eating a lot of memory. This means the max stop the world pause is known in advance. As long as that pause is acceptable we are good to go for using Java for low latency system.
There are also different garbage collectors that can be configured. There is even a Zero Garbage Collector. With this option your program just crashes out when it reaches max memory. In order for a Zero Garbage Collector to work you need to preinitialize instances at start up and never use the "new" keyword to create new instances. This means that in order to use the Zero Garbage Collector all instances have to have a reference kept to them for the entire duration of the JVM. i.e. all java instances must be "Long Lived". In this scenario you will typically be using a lot of arrays of objects and the objects will have fields in them which say if they are being used or not. When you have finished using them the object is cleaned and marked as "unused" (with your custom boolean flags). It then becomes available for re-usage. This is tricky programming but is used in VERY low latency systems (systems that care about nano seconds).
Use a Zero Garbage Collector - this is an extreme option which should only be used by experts
Set max memory for the JVM
Use long lived instances and very short lived small instances. Do not use middle lived instances. Long lived instances are kept for the duration of the JVM and will not thus be garbage collected. If the instances are not garbage collected they will not contribute to Stop the World pauses. Dependency Injection (also called Inversion of Control) is about keeping singletons and injecting them where ever they are needed at startup. Short lived small instances can be claimed immediately and will not effect latency much.
There will be extra coding to allow one JVM to call functionality on another JVM. This code needs to be fast so it is usually socket based. When the JVMs start up they connect to each other and send periodic keep alive messages. If they do not receive a keep alive message they recreate their connections.
For very fast inter JVM communication you can communicate over Memory Mapped files. This can allow one million messages to pass from one JVM to another JVM in one second which is pretty fast in the grand scheme of things.
Back: Overview of Tech
Page Author: JD