Сбор мусора в Java выполняется на основе «достижимости». JLS определяет этот термин следующим образом:
«Доступаемый объект - это любой объект, к которому можно получить доступ в любом потенциальном продолжающемся вычислении из любой живой нити».
blockquote>Пока объект доступен *, он не подходит для сбора мусора.
JLS оставляет его до реализации Java, чтобы выяснить, как определить, является ли объект может быть доступен . Если реализация не может быть уверенной, она свободна рассматривать теоретически недостижимый объект как достижимый ... и не собирать его. (Действительно, JLS позволяет реализации не собирать ничего, никогда! Никакая разумная реализация не сделает этого.)
На практике (консервативная) достижимость вычисляется путем трассировки; глядя на то, что может быть достигнуто следующими ссылками, начиная с переменных класса (статических) и локальных переменных в потоковых стеках.
Вот что это значит для вашего вопроса:
Если я вызываю:
blockquote>myTree = null;
, что действительно происходит с связанными объектами TreeNode внутри дерева? Будет ли собран мусор, или я должен установить null все связанные объекты внутри древовидного объекта ??Предположим, что
myTree
содержит последнюю оставшуюся доступную ссылку на корень дерева .
- Ничего не произойдет немедленно.
- Если внутренние узлы ранее были доступны только через корневой узел, тогда они теперь недоступны и имеют право на сбор мусора. (В этом случае назначение
null
ссылок на внутренние узлы не требуется.)- Однако, если внутренние узлы достижимы с помощью других путей, они предположительно все еще достижимы, и поэтому НЕ имеет права на сбор мусора. (В этом случае ошибка присваивания
null
для ссылок на внутренние узлы является ошибкой. Вы разбираете структуру данных, которую что-то еще может попытаться использовать.)Если
myTree
не содержит оставшуюся оставшуюся ссылку на корень дерева, тогда обнуление внутренней ссылки является ошибкой по той же причине, что и в 3. выше.
Итак, когда должен вы
null
вещи, чтобы помочь сборщику мусора?Случаи, когда вам нужно беспокоиться, когда вы можете что ссылка в некоторой ячейке (локальная, экземпляр или переменная класса или элемент массива) больше не будет использоваться, но компилятор и среда выполнения не могут! Случаи делятся примерно на три категории:
- Ссылки на объекты в переменных класса ... которые (по определению) никогда не выходят за рамки.
- Ссылки на объекты в локальных переменных, которые все еще в области ... но не будут использоваться. Например:
В приведенном выше сообщении мы знаем, что еслиpublic List<Pig> pigSquadron(boolean pigsMightFly) { List<Pig> airbornePigs = new ArrayList<Pig>(); while (...) { Pig piggy = new Pig(); ... if (pigsMightFly) { airbornePigs.add(piggy); } ... } return airbornePigs.size() > 0 ? airbornePigs : null; }
pigsMightFly
является ложным, то объект списка не будет использоваться. Но никакой основной компилятор Java не может рассчитывать на это.- Ссылки на объекты в переменных экземпляра или в ячейках массива, где инварианты структуры данных означают, что они не будут использоваться. Пример экземпляра @ edalorzo - пример этого.
Следует отметить, что компилятор / среда выполнения иногда может определить, что переменная в области видимости эффективно мертва. Например:
public void method(...) { Object o = ... Object p = ... while (...) { // Do things to 'o' and 'p' } // No further references to 'o' // Do lots more things to 'p' }
Некоторые компиляторы Java / runtimes могут распознавать, что «o» не требуется после окончания цикла и обрабатывает переменную как мертвую.
* На самом деле речь идет о сильной достижимости. Модель достижимости GC более сложна, если вы рассматриваете мягкие, слабые и фантомные ссылки. Однако они не имеют отношения к случаю использования ОП.
Мне удалось решить проблему сразу после публикации вопроса. Исправление состояло в том, чтобы создать новый UInt8Array, а затем создать новый BLOB-объект из этого UInt8Array. По сути, это означает, что последний метод становится:
public onGotAllSlices(docdataSlices) {
let docdata = [];
for (let i = 0; i < docdataSlices.length; i++) {
docdata = docdata.concat(docdataSlices[i]);
}
const byteArray = new Uint8Array(docdata);
const blob = new Blob([byteArray]);
const a = document.createElement('a');
url = URL.createObjectURL(blob);
a.href = url;
a.download = 'WordTest.docx';
document.body.appendChild(a);
a.click();
setTimeout(function() {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 0);
}