Класс JvmComprehension является основным в данной программе и загружается при её запуске. Затем с помощью ClassLoader происходит поиск и загрузка других классов, необходимых для работы JvmComprehension (например класса Object), подготовка класса к выполнению и инициализация класса.
В момент вызова метода main создается фрейм (кадр) main в стеке. Затем работа происходит следующим образом:
- В созданный фрейм main добавляется переменная i.
int i = 1;
- Далее происходит создание нового объекта new Object(), который попадает в heap (кучу), а переменная о, которая ссылается на этот объект, попадает в фрейм main.
Object o = new Object();
- Затем создается локальная переменная ii, которая ссылается на объект типа Integer, равный 2. Сам объект попадает в heap, а переменная в фрейм main.
Integer ii = 2;
- При вызове метода printAll в стеке создается новый фрейм, в котором будут храниться переменная i и переменные o и ii, ссылающиеся на объекты находящиеся в heap: Object и Integer.
printAll(o, i, ii);
- В фрейме метода printAll создается ссылка uselessVar. Объект Integer, на который она ссылается помещается в heap.
Integer uselessVar = 700;
- Создается новый фрейм в стеке, куда передается ссылка на о, а также переменные i и ii. Осуществляется вывод полученной строки в консоль. После этого фрейм printAll освобождается, а объект Integer, созданный им останется в куче до вызова сборщика мусора, который проверит все фреймы на наличие ссылки uselessVar, на данный объект, и только не найдя её произведет удаление объекта.
System.out.println(o.toString() + i + ii);
- В куче создается новый объект String со значением "finished". Ссылка на него передается в новый фрейм. Происходит вывод строки в консоль.
System.out.println("finished");
По завершении работы метода main его стековая память очищается. В этой же строке завершается работа программы. Т.е. Runtime очищает всю память и заканчивает работу программы.