What are some best practices to build memory-efficient Java applications?
java, memory-leaks, performance
Solution
Some techniques I use to reduce memory:
- Make your own IntArrayList (etc) class that prevents boxing
- Make your own IntHashMap (etc) class where keys are primitives
- Use nio's ByteBuffer to store large arrays of data efficiently (and in native memory, outside heap). It's like a byte array but contains methods to store/retrieve all primitive types from the buffer at any arbitrary offset (trade memory for speed)
- Don't use pooling because pools keep unused instances explicitly alive.
- Use threads scarcely, they're super memory hungry (in native memory, outside heap)
- When making substrings of big strings, and discarding the original, the substrings still refer to the original. So use `new String` to dispose of the old big string.
- A linear array is smaller than a multidimensional array, and if the size of all but the last dimension is a power of two, calculating indices is fastest: `array[x|y<<4]` for a 16xN array.
- Initialize collections and `StringBuilder` with an initial capacity chosen such that it prevents internal reallocation in a typical circumstance.
- Use `StringBuilder` instead of string concatenation, because the compiled class files use `new StringBuilder()` without initial capacity to concatenate strings.
Problem
Java programs can be very memory hungry. For example, a `Double` object has 24 bytes: 8 bytes of data and 16 bytes of JVM-imposed overhead. In general, the objects that represent the primitive types are very expensive. The same happens for any collection in the Java Standard Library. There are even some counterintuitive facts such as a `HashSet` being more memory hungry than a `HashMap`, since a `HashSet` contains a `HashMap` inside (http://docs.oracle.com/javase/7/docs/api/java/util/HashSet.html). Could you come up with some advice when modeling data and delegation of objects in high performance settings so that these "weaknesses" of Java are mitigated?