Can you please explain, where the instances of Exception or it's children are allocated in memory? Is it heap or stack, or something else?
Thanks!
Select Advanced system settings and then select Settings in the Performance section on the Advanced tab. Select the Advanced tab, and then select Change in the Virtual memory section. Clear the Automatically manage paging file size for all drives check box.
std::bad_alloc is a type of exception that occurs when the new operator fails to allocate the requested space. This type of exception is thrown by the standard definitions of operator new (declaring a variable) and operator new[] (declaring an array) when they fail to allocate the requested storage space.
Memory allocation is the process of reserving a partial or complete portion of computer memory for the execution of programs and processes. Memory allocation is achieved through a process known as memory management.
There are two types of memory allocations. Static and dynamic.
For most JVM's all Object are created on the heap and Exception is not an exception. ;)
A JVM could allocate objects on the stack using Escape Analysis, however this is usually limited to objects which are used only in one method and not returned. i.e. it is highly unlikely that Exceptions would be a good candidate.
Something which is special about the way Throwables (incl Exception) are created on many JVMs is that the stack trace elements are not created until they are needed. This is because most of the time they are not needed and they are expensive to create. However the information to create the stack trace is retained some where by the JVM and associated with the Throwable, but it is not visible to the debugger or reflection.
public static void main(String... args) {
Throwable t = new Throwable("here");
System.out.println("Throwable before getStackTrace()");
shallowDump(t);
System.out.println("\nThrowable after getStackTrace()");
t.getStackTrace();
shallowDump(t);
}
private static void shallowDump(Object pojo) {
for (Field f : pojo.getClass().getDeclaredFields()) {
if (Modifier.isStatic(f.getModifiers())) continue;
f.setAccessible(true);
Object o;
try {
o = f.get(pojo);
if (o == pojo)
o = "{self}";
if (o instanceof Object[])
o = "Array of "+(o.getClass().getComponentType());
} catch (Exception e) {
o = e;
}
System.out.println(f.getName() + ": " + o);
}
}
prints
Throwable before getStackTrace()
detailMessage: here
cause: {self}
stackTrace: null
Throwable after getStackTrace()
detailMessage: here
cause: {self}
stackTrace: Array of class java.lang.StackTraceElement
So the question arises, where is the information which used to create the StackTraceElement retained. Looking at the code, native methods are used to access the information. There is a mysterious field called backtrace
which you cannot see using reflection.
System.gc();
for (int i = 0; i < 5; i++) {
Throwable[] ts = new Throwable[10000];
long free = Runtime.getRuntime().freeMemory();
for (int j = 0; j < ts.length; j++)
ts[j] = new Throwable();
long used = free - Runtime.getRuntime().freeMemory();
System.out.printf("Average Throwable size was %,d%n", used / ts.length);
}
System.gc();
for (int i = 0; i < 5; i++) {
Throwable[] ts = new Throwable[10000];
long free = Runtime.getRuntime().freeMemory();
for (int j = 0; j < ts.length; j++)
ts[j] = Throwable.class.newInstance();
long used = free - Runtime.getRuntime().freeMemory();
System.out.printf("Average Throwable.class.newInstance() size was %,d%n", used / ts.length);
}
This gets the size of a Throwable created in the current method and a Throwable created in a deeper method via reflection (which has a deeper stack)
Average Throwable size was 302
Average Throwable size was 302
Average Throwable size was 302
Average Throwable size was 302
Average Throwable size was 302
Average Throwable.class.newInstance() size was 247
Average Throwable.class.newInstance() size was 296
Average Throwable.class.newInstance() size was 296
Average Throwable.class.newInstance() size was 296
Average Throwable.class.newInstance() size was 296
The size of a Throwable is much larger than you might expect from the fields it has. One can assume some additional information is being stored on the heap to help this class, however, is all the information were stored in the Throwable object , you expect the second type of Throwable to be larger.
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