For every new Class added to a Java application, what is the cost in terms of memory?
Edited after cruftex's answer: This is my understanding of class splitting:
This is my understanding of class loading now:
Is this roughly how it works?
For every new Class added to a Java application, what is the cost in terms of memory?
It usually doesn't matter. Generally speaking, only a small proportion (say, 5%) of overall memory use is taken up by code in its various forms. Therefore, even if you did manage to reduce code size by half, overall memory usage would decrease only marginally.
In contrast, overly long source files make a code base hard to navigate, and the larger scopes make it harder to get an overview of what exactly the class does and whether a certain change is safe. Therefore, long source files make modifying the code significantly more expensive and error prone.
- On first use Class is loaded into memory (Memory used is roughly the size of the class file)
Correct.
- If JIT is used, some additional machine-friendly binary version is created by the JIT compiler which uses a little more memory
- If Hotspot is used only some of the frequently used classes are optimised with machine-friendly versions (to balance memory and speed)
Hotspot is a JIT, so you're repeating yourself here. But yes, JIT does increase code size (but increases speed far more).
Once a class is loaded, creating additional instances has negligible overhead (about 50-100 bytes?) (assuming no instance variables)
That is JVM specific. On the Oracle Hotspot JVM, memory overhead per object is about 8 bytes, as the following program demonstrates:
public class Test {
public static void main(String[] args) {
Object[] array = new Object[10_000_000];
Runtime rt = Runtime.getRuntime();
long usedBefore = rt.totalMemory() - rt.freeMemory();
for (int i = 0; i < array.length; i++ ) {
array[i] = new Object();
}
long usedAfter = rt.totalMemory() - rt.freeMemory();
System.out.println(usedBefore);
System.out.println(usedAfter);
System.out.println((double)(usedAfter - usedBefore) / array.length);
}
}
- Once a class is loaded the class itself is never garbage collected
While it is not mandated by the Java Language Specification, every JVM I ever used frees a class when its ClassLoader becomes unreachable (granted, the bootstrap class loader will always remain reachable, but custom ClassLoaders can become unreachable).
You question cannot be answered specific, so I try it in a general way. Your questions aim at memory consumption. However, if you save memory it is most likely that your performance suffers from that, that is called space time trade off. See: http://en.wikipedia.org/wiki/Space%E2%80%93time_tradeoff
The easiest way to save memory - if you are only concerned of your program size - would be to switch off the just in time compiler completely. This way you save the program storage for the machine code of your java classes. BTW: There are a lot of VM options that impact the memory consumption!
Is it better to have huge 5000+ lines classes or several 500-1000 line classes (if all of them are loaded anyway)
In general the chances are more likely that you can reuse code better within smaller units. Which means, you probably save code lines when aiming at smaller sizes.
If the code/methods stay the same and you just distribute them between classes, then an additional overhead adds for the classes.
Even if you ask three experts on that and they have a look at the code, they will come up with different answers, because it heavily depends on your real code, the usage patterns and what the JIT is doing with it at runtime.
That said, even an experiment might lead you in the wrong direction, because you need to simulate the same usage patterns.
A last note on that: Take a look on how many classes your VM loads and decide whether it is really worth saving a view.
Each time an Object is instantiated is it true that the only additional memory usage is for the instance variable references
Plus a constant overhead for memory management.
For a 5000-line class with no instance variables, what is the scale of cost when the class is loaded.. is the size of the class file a rough approximation?
Without the JIT: yes.
Is the size of the jar file any indication of either usual or max size of memory that classes will occupy?
No, not at all, because the classes are only loaded when needed.
Some advice:
If you are concerned about the memory usage of your program, first check the heap twice. I recommend jmap and eclipse memory analyzer for that.
Then, you may have a look on your classes and methods. You can debug the JIT and see how much space the compiled methods are needing by: -XX:-PrintCompilation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With