A JFrame
, который создается только через new JFrame()
без каких-либо дополнительных действий, не будет открыт на экране и не помешает сборке мусора. Только реализация, подключенная к устройству отображения, будет ссылаться из реализации AWT и не сможет собирать мусор до тех пор, пока он не будет явно отключен.
Что можно проверить с помощью следующего кода:
public static void main(String[] args) {
check(new JFrame(), "just creating a JFrame", x -> {});
check(new JFrame(), "creating and connecting a JFrame", JFrame::pack);
check(Frame.getFrames()[0], "calling dispose()", Frame::dispose);
}
private static <T> void check(T obj, String description, Consumer<T> action) {
System.out.println(description);
action.accept(obj);
WeakReference<T> r = new WeakReference<>(obj);
obj = null;
System.gc();
if(r.get() == null) System.out.println("collected immediately");
else {
System.runFinalization();
System.gc();
if(r.get() == null) System.out.println("collected after finalization");
else System.out.println("still alive");
}
}
, который будет печатать
just creating a JFrame
collected immediately
creating and connecting a JFrame
still alive
calling dispose()
collected after finalization
в типичных реализациях.
Стоит отметить, что кадр, который никогда не был подключен к устройству отображения, сразу собирается как обычный объект, тогда как кадр который был подключен и позднее отключен с помощью вызова dispose()
, требуется действие очистки, которое происходит после первого запуска сборщика мусора.
Кроме того, в примере используется pack()
вместо setVisible(true)
, чтобы продемонстрируйте, что кадр может быть подключен к устройству отображения, не будучи видимым. Это делает разницу между isDisplayable()
, который отражает, подключен ли компонент к экранному устройству, и isVisible()
, который сообщает, было ли установлено свойство visible до true
. Наконец, компонент сообщает isShowing()
как true
, когда он отображается и отображается, а все его родители показывают.